Настройка взаимодействия с nats по tls

Время на прочтение

Здравствуйте, меня зовут Александр, я backend-разработчик. В данной публикации хочу поделиться опытом настройки мониторинга NATS JetStream. Рассказать для чего в принципе это может понадобиться. А также  привести пример необходимого стека сервисов поднятых в docker для мониторинга. В статье не рассматриваются настройки dashboards в Grafana, принципы и особенности работы NATS.

Может возникнуть вопрос для чего же требуется мониторинг, особенно для программного продукта, который в принципе является рабочим. Т.к. мониторинг не является бесплатным – для него требуется настройка и поддержание нескольких сервисов. Однако для оптимизации, добавления новых фич, требуется понимание того, как в реальности используется функционал приложения. И именно метрики могут нам в этом помочь. Метрика — эта численная мера, некоторого свойства или поведения программного обеспечения. В отличии от логов, метрики собирают не все детали, а только готовую выжимку: например, количество запросов к сервису.

Простой пример: есть endpoint который работает, скажем 10 секунд, и на первый взгляд, кажется, что можно попробовать выделить ресурсы для его оптимизации. Но, сбор статистики за месяц показывает, что этим endpoint-ом практически не пользовались. Следовательно, встает закономерный вопрос: стоит ли тратить ресурсы на оптимизацию этого endpoint?

Для начала несколько слов про NATS JetStream. NATS – это система очередей сообщений, которая появилась в 2010, написана на языке Go. NATS хорошо подходит для передачи сообщений в режиме реального времени. На сегодняшний день в NATS JetStream реализована долговечность и гарантированная доставка сообщений.

Для мониторинга NATS будет использоваться следующий стек:

  • Prometheus nats exporter – сервис выступающий неким адаптером между  NATS и сервисом Prometheus

  • Prometheus – отдельный сервис для сбора телеметрии

  • Grafana – для непосредственного отображения результатов

Для запуска в docker можно использовать следующий docker-compose файл

version: "3.8"
services:
  nats:
    image: nats:latest
    command: --js --debug --trace --sd /data -p 4222 -m 8222
    ports:
    - 4222:4222
    - 6222:6222
    - 8222:8222
    volumes:
    - ./jetstream-cluster/n1:/data

  prometheus-nats-exporter:
    image: natsio/prometheus-nats-exporter:latest
    command: "-connz -varz -channelz -serverz -subz -healthz -routez http://host.docker.internal:8222"
    ports:
      - "7777:7777"

  prometheus:
    image: prom/prometheus:latest
    hostname: prometheus
    volumes:
      - "./prometheus.yml:/etc/prometheus/prometheus.yml"
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    hostname: grafana
    ports:
      - "3000:3000"

Немного подробнее о настройках данных сервисов.

В NATS необходимо включить возможность мониторинга на нужном порту. Это можно сделать при помощи параметра -m <номер порта> при запуске сервиса. Более подробно можно прочитать в официальной документации.

NATS поддерживает различные типы метрик. Можно выделить следующие:

  • varz – общая статистика

  • connz – статистика соединений

  • routez – информация о маршрутах

  • subsz – информация о подписчиках

  • jsz – информация о стримах (jetstreams)

Результаты, отображаемые в данных метриках, можно посмотреть в сервисе NATS по пути :http://localhost:8222/<название метрики>, к примеру http://localhost:8222/varz

Еще про Ниссан:  Какой аккумулятор устанавливается на Ниссан Альмера Классик?

Далее в конфигурационном файле NATS Prometheus exporter необходимо указать источник данных, т.е. сервис NATS (порт, который указан в параметре -m), а также указать какие именно метрики нужно собирать. Это выполняется при помощи команды

prometheus-nats-exporter -varz "http://localhost:5555

где через дефис указываются необходимые метрики.

Итоговый результат полученных метрик из Prometheus nats exporter можно увидеть по пути http://localhost:7777/metrics. Этот путь можно переопределить при помощи параметра -path.

Более подробно про доступные метрики, – в официальной документации.

Сервис Prometheus занимается сбором телеметрии, в нем имеется список источников данных, и он периодически опрашивает их. Для запуска Prometheus можно использовать файл prometheus.yml

Далее можно проверить доступность источника данных prometheus nats exporter. Все доступные источники данных для prometheus отображаются по адресу http://localhost:9090/targets

Источники данных prometheus
Источники данных prometheus

Наконец необходимо настроить отображение интересующих нас метрик в Grafana, и можно приступать непосредственно к мониторингу.

В качестве примера работы метрик, будет рассмотрена следующая ситуация: в новый stream публикуется 2 сообщения, а спустя несколько минут появляется Subscriber читающий данный stream.

Для отправки сообщения используется утилита nats_cli, команда отправки имеет вид:

nats publish <имя jetstream> <payload>

Время появление Subscriber на графиках выделено вертикальной линией. График количества Subscribers (метрика gnatsd_connz_total) имеет следующий вид:

Количество Subscriber
Количество Subscriber

На графике необработанных сообщений (метрика jetstream_consumer_num_pending) видно, что при появлении Subscriber, число необработанных сообщений становиться ноль.

Число необработанных сообщений
Число необработанных сообщений

При этом на графике общего количества сообщений (метрика jetstream_server_total_messages) изменений не происходит.

Общее число сообщений
Общее число сообщений

Можно выделить следующие важные метрики NATS.

  • gnatsd_varz_cpu – Потребление ресурсов процессора (CPU, %)

  • gnatsd_varz_mem – Потребление оперативной памяти

  • gnatsd_connz_total – Число Subscribers

  • jetstream_server_total_messages – Всего сообщений в jetstream

  • jetstream_server_total_message_bytes – Размер всех сообщений в jetstream

  • jetstream_consumer_num_pending – Ожидающие сообщений в jetstream

  • gnatsd_varz_in_msgs – Входящие сообщения от Publisher в NATS

  • gnatsd_varz_out_msgs – Ответы на сообщения от Subscriber в NATS

Все эти метрики можно вынести на отдельный экран, что позволит быстро анализировать актуальное состояние всего сервиса NATS JetStream.

В NATS доступен широкий спектр различных метрик. Необходимые метрики должны быть выбраны исходя из конкретной ситуации и в зависимости от цели мониторинга.

Внимание: Сертификаты необходимо выпускать строго на технологическом УЦ. Использовать 1 набор TLS сертификатов для аккредитованного и технологического УЦ нельзя!!! Также необходимо разделять DN для клиентских сертификатов, используемых в NATS TLS в технологическом УЦ и аккредитованном!

Предпологается что перед выпусом данных сертификатов, уже настроен технологический УЦ, в конфигурации c NATS без TLS.

  •          Выпустить корректные сертификаты, установить их с привязкой к ЗК (если серверов несколько то устанавливать сертификат необходимо на сервере где физически располагается соответствующий компонент УЦ)
  •          Прописать данные сертификатов в конфиг файле nats.conf
  •          Отредактировать файлы appsettings.json  для сервисов, внеся в них отпечатки сертификатов + включив TLS.
  •          Перезапустить УЦ уже с использованием TLS 
Еще про Ниссан:  Шины hankook

Список сертификатов для NATS TLS

1)      Серверный сертификат NATS, выпускается по шаблону TLS сервер и должен содержать в CN или в SAN DNS имя машины/IP адрес.

 Создание запроса на сертификат рекомендуем производить на машине, на которой непосредственно располагается соответствующий компонент УЦ, чтобы избежать в дальнейшем процедуры переноса ЗК.

Создание запроса и выпуск сертификатов могут выполнены как через веб интерфейс, так и с помощью утилиты pkica

Важно: для технологического УЦ,  чтобы разрешить выпуск не только квалифицированных сертификатов правим настройки ЦС 
Надо настройке QualifiedCertMode установить значение AttrFormat или None, Затем перезапустить службу ЦС.

Процедура подробно описана в  пункте 1.2.6. Руководства по эксплуатации.

Пример команд для выпуска сертификата, указаного пункте 1 списка сертификатов с ипользованием pkica

pkica ca new-cert-req -o<путь к файлу запроса на сертификат> -t 1.2.643.2.2.46.0.3 -s “CN=<DNSимя машины>” -c<Имя контейнера ЗК> –no-pin -k KeyExchange

Если Вы хотите добавить несколько DNS имен в SAN то запрос создание запроса должно выглядеть так:

pkica ca new-cert-req -o<путь к файлу запроса на сертификат> -t 1.2.643.2.2.46.0.3 -s ‘CN=Вебсервер,1.2.643.2.2.44.5=”<DnsName1>;<DnsName2>;<DnsName3>”‘ -c<Имя контейнера ЗК> –no-pin -k KeyExchange

/opt/cpca/pkica/pkica ca issue-cert -f  <путь к файлу запроса на сертификат> -n <Имя ЦС> -o <путь к файлу сертификата>

Устанавливаем сертификат с привязкой к ЗК(обязательно под тем-же пользователем под которым создавали запрос)

/opt/cprocsp/bin/amd64/certmgr -install -file <путь к сертификату> -container <Имя контейнера ЗК>  -store uMy –certificate

Пример выпуска сертификата, указаного пункте 1 списка сертификатов с ипользованием веб интерфейса

Создаем пользователя и выпускаем ему сертификат, по шаблону Сервер TLS, не забывая указать верные SAN

Затем создаем pfx и устанавливаем его на УЦ под тем пользователем, под которым запускается демон Nats. 

Важно: при установке pfx не задаем пароль.

sudo -u <имя пользователя> /opt/cprocsp/bin/amd64/certmgr -inst -pfx -pin <пин код> -file <путь к файлу>

Для сертификатов, описанных в пунктах 2-6 списка сертификатов, отличаться будет только процедура создания запроса, мы будем использовать другой шаблон и для каждого пункта указывать свой уникальный DN. Процесс выпуска и установки отличаться не будет.

Пример команд для создания запроса на сертификат,  описанных в пунктах 2-6 списка сертификатов

pkica  ca new-cert-req -t 1.2.643.2.2.46.0.6 -s “CN=stan,C=RU” -c <Имя контейнера ЗК>  -e -k  KeyExchange  -o   <путь к файлу запроса на сертификат>

Пример выпуска сертификатов, указаных пункте 2-6 списка сертификатов с ипользованием веб интерфейса

Создаем пользователя и выпускаем ему сертификат, по шаблону Клиент TLS

Затем создаем pfx и устанавливаем его на УЦ под тем пользователем, под которым запускается демон соответсвующего сервиса. 

Еще про Ниссан:  Реле заднего дворника

Важно: при установке pfx не задаем пароль.

sudo -u <имя пользователя> /opt/cprocsp/bin/amd64/certmgr -inst -pfx -pin <пин код> -file <путь к файлу>

Редактируем файл nats.conf:

Сертификаты, описанные в пунктах 1 и 2, указываются в виде пути к файлу сертификата (путь прописан 2 раза –это нормально, так и нужно прописывать) в следующих разделах

Для серверного сертификата (описан в пункте 1 списка сертификатов), путь указывается в данном разделе:

  # серверныйсертификат NATS

Для клиентского сертификата (описан в пункте 2 списка сертификатов), путь указывается в данном разделе:

# NATS Streaming Configuration

    # клиентский сертификат NATS Streaming для подключения к сервису NATS

По умолчанию данный раздел выглядит так:

Не забываем добавить корректный порт и DNS имя (Именно DNS имя, а не IP) в раздел listen

Теперь в файлах appsettings.json соответствующих сервисов, в разделах NATS/STAN задаем отпечаток соответствующего им tlsсертификата(смотри список сертификатов) и выставляем значение параметра “Secure”: true. Не забываем что в разделе URL должно быть указано DNS имя а не IP 

После правки необходимых конфигов. необходимо остановить демоны сервисов УЦ(или процессы если запущено вручную)

Производим пробный запуск NATS c TLS через bash

Пример /opt/cpca_tls/nats-streaming/nats-streaming-server -sc /opt/cpca_tls/nats-streaming/nats.conf

Убеждаемся, что Nats успешно запустился -завершаем процесс

Если ранее для NATS без TLS был создан демон, необходимо отредактировать его настройки, указав путь к новому файлу конфигурации.

Так-же можно создать новый демон, отключив автозагрузку “старого”

Запускаем демоны сервисов УЦ, проверяя что соединение успешно установилось 

Важно: После того как мы включим TLS для NATS, через pkica нельзя будет выпускать сертификаты с неподписанными запросами.

Подписать запрос необходимо сертификатом оператора.

Пример подписи с использование cryptcp:

cryptcp -sign -thumbprintDF861BEA1B3066A99B77A1D39FC1B804A718FCDB -der <путь к файлу запроса> <путь к подписанному файлу>


Что если в конфигурации с NATS TLS по какой либо причине не смог выпуститься CRL, а предыдущий уже истек?

В такой ситуации новый crl не сможет выпуститься т.к. не построится TLS между компонентами 

Необходимо выполнить следующие действия:

Необходимо остановить демоны сервисов УЦ+ Nats(или процессы если запущено вручную) 

Через bash выполняем команду ручного запуска Nats c конфигом nats.no-tls.conf 

 nats-streaming-server -sc /opt/cpca/nats-streaming/nats.no-tls.conf

Послеуспешногозапуска NATS, правимфайл appsettings.json в   CryptoPro.Ca.Service, убирая требование Secure

Также правим appsettings.json в  pkica тем же образом 

через bash запускаем исполняемый файл CryptoPro.Ca.Service

Затем загружаем ключи (при необходимости) и вручную выпускаем CRL, указывая директорию публикации

pkica ca crl issue –name <имя цс>  –output-folder  <директория публикации CRL> 

После успешного выпуска crl, распространяем его на все компоненты УЦ.

Останавливаем CryptoPro.Ca.Service и Nats

Включаем в файлах конфигурации appsettings.json требование Secure

Последовательно запускаем Nats c TLS и остальные демоны УЦ

Оставьте комментарий