Здравствуйте, меня зовут Александр, я 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
Наконец необходимо настроить отображение интересующих нас метрик в Grafana, и можно приступать непосредственно к мониторингу.
В качестве примера работы метрик, будет рассмотрена следующая ситуация: в новый stream публикуется 2 сообщения, а спустя несколько минут появляется Subscriber читающий данный stream.
Для отправки сообщения используется утилита nats_cli, команда отправки имеет вид:
nats publish <имя jetstream> <payload>
Время появление Subscriber на графиках выделено вертикальной линией. График количества Subscribers (метрика gnatsd_connz_total) имеет следующий вид:
На графике необработанных сообщений (метрика 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
Список сертификатов для 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 и остальные демоны УЦ