Настройка NATS сервера
В двух словах, NATS позволяет обмениваться данными, сегментированными в виде сообщений. Что-то подобное делает Kafka, RabbitMQ, Redis и многое другое. В данной инструкции будет рассмотрен процесс установки NATS сервера на Linux, а также его запуск в режиме кластера.
Установка, настройка и запуск сервера NATS
Установка
Запуск
Проверка
Включение JetStream
Добавление системной учетной записи
Настройка кластера
Отправка файлов
Включение встроенного мониторинга
Устранение ошибок
Установка и запуск
Рассмотрим отдельно процессы установки и запуска сервера nats.
Установка
NATS может быть развернут несколькими способами:
- Как процесс, работающий в docker.
- Как приложение Kubernetes.
- С помощью пакетного менеджера (далеко не для всех систем).
- Распаковка бинарника.
Последний вариант является универсальным и самым простым. Рассмотрим его.
Нам понадобятся следующие пакеты:
- wget — для загрузки архива.
- tar — для распаковки архива.
В зависимости от системы, команды для установки будут отличаться.
а) Для Deb (Ubuntu / Debian / Astra Linux):
apt update
apt install tar wget
б) Для RPM (Rocky Linux / РЕД ОС):
yum install tar wget
Переходим на страницу с релизами проекта в GitHub. Копируем ссылку на архив с последней версией (или конкретную, если требуется) nats server:
Используя ссылку, загружаем архив на сервер:
wget https://github.com/nats-io/nats-server/releases/download/v2.9.15/nats-server-v2.9.15-linux-amd64.tar.gz
Распакуем:
tar -zxf nats-server-*.tar.gz
Копируем бинарный файл в каталог /usr/bin:
cp nats-server-*-linux-amd64/nats-server /usr/bin/
Проверяем, что nats-server может быть запущен:
nats-server -v
Мы должны получить что-то на подобие:
nats-server: v2.9.15
Исходники можно удалить:
rm -rf nats-server-*-linux-amd64 nats-server-*.tar.gz
Запуск
Для разового запуска достаточно ввести команду:
nats-server
Мы должны увидеть что-то на подобие:
[153420] 2023/04/04 16:20:40.059157 [INF] Starting nats-server
[153420] 2023/04/04 16:20:40.059246 [INF] Version: 2.9.15
[153420] 2023/04/04 16:20:40.059254 [INF] Git: [b91fa85]
[153420] 2023/04/04 16:20:40.059264 [INF] Name: NDAXZI62G33F3IR6UGBMFCL4XMPPI6VDRCYDU4NP5OFSKYIH4TDQ63WQ
[153420] 2023/04/04 16:20:40.059268 [INF] ID: NDAXZI62G33F3IR6UGBMFCL4XMPPI6VDRCYDU4NP5OFSKYIH4TDQ63WQ
[153420] 2023/04/04 16:20:40.060083 [INF] Listening for client connections on 0.0.0.0:4222
[153420] 2023/04/04 16:20:40.060292 [INF] Server is ready
Прерываем работу сервиса клавишами Ctrl + C. Теперь выполним запуск nats в качестве сервиса.
Создадим конфигурационный файл для сервера nats:
mkdir /etc/nats
vi /etc/nats/nats-server.conf
cluster {
name: "test-nats"
}
store_dir: "/var/lib/nats"
listen: "0.0.0.0:4222"
log_file: /var/log/nats/nats.log
* где:
- cluster name — имя сервера кластера NATS.
- store_dir — путь к файлу хранилища данных.
- listen — адрес и порт, на котором будет слушать сервер.
- log_file — путь к файлу журнала.
Создадим служебную учетную запись nats:
useradd -r -c 'NATS service' nats
Создадим каталоги:
mkdir /var/log/nats /var/lib/nats
И назначим в качестве их владельца созданную учетную запись:
chown nats:nats /var/log/nats /var/lib/nats
Создадим systemd юнит-файл:
vi /etc/systemd/system/nats-server.service
[Unit]
Description=NATS messaging server
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/nats-server -c /etc/nats/nats-server.conf
User=nats
Group=nats
LimitNOFILE=65536
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Для разрешения автозапуска и старта сервиса вводим:
systemctl enable nats-server --now
Статус смотрим командой:
systemctl status nats-server
Подключение к серверу
Если мы хотим подключаться к нашему серверу по сети с другого узла, необходимо убедиться, что брандмауэр разрешает подключение по настроенному порту (в нашем примере, 4222). Для разных утилит управления фаерволом это делается по-разному.
а) В iptables (как правило, для систем deb):
iptables -I INPUT 1 -p tcp --dport 4222 -j ACCEPT
apt install iptables-persistent
netfilter-persistent save
* последние 2 команды для сохранения правил. Подробнее про настройку iptables и сохранение правил читайте в инструкции Настройка netfilter с помощью iptables.
б) В firewalld (как правило, для систем rpm):
firewall-cmd --permanent --add-port=4222/tcp
firewall-cmd --reload
* подробнее в инструкции Настройка firewalld в CentOS.
Тестирование работы сервера можно выполнить из командной строки. Для этого нужно установить клиента nats. В репозиториях системы его нет, но готовый пакет (deb или rpm) можно скачать с GitHub — переходим на соответствующую страницу, копируем ссылку на установщик, загружаем его в систему и выполняем установку.
а) Например, для Ubuntu / Debian / Astra Linux:
wget https://github.com/nats-io/natscli/releases/download/v0.0.35/nats-0.0.35-amd64.deb
dpkg -i nats-0.0.35-amd64.deb
б) Или для Rocky Linux / РЕД ОС:
wget https://github.com/nats-io/natscli/releases/download/v0.0.35/nats-0.0.35-amd64.rpm
yum localinstall ./nats-0.0.35-amd64.rpm
После мы можем выполнить команду для тестирования.
Вводим:
nats pub -s <адрес сервера> <тема> <сообщение>
Например:
nats pub -s 127.0.0.1 "test-subject" "Test message"
* в данном примере мы опубликуем сообщение Test message в теме test-subject на локальном сервере (127.0.0.1).
Система может вернуть ошибку:
bash: nats: command not found
Это происходит из-за того, что исполняемый файл помещается в каталог /usr/local/bin, а системная переменная PATH не включает данный путь. Как вариант, мы можем либо прописать полный путь к утилите:
/usr/local/bin/nats
Либо отредактировать конфигурационный файл шела, добавив путь к переменной PATH, например, для bash:
vi ~/.bash_profile
Добавим строку:
PATH=$PATH:/usr/local/bin
Применяем:
source ~/.bash_profile
Для подписки на тему, можно в другой сессии ssh или с другого компьютера ввести команду:
nats sub -s <адрес сервера> <тема>
При повторной отправки сообщения мы должны увидеть его текст из консоли, где выполнена подписка (nats sub).
Включение JetStream
JetStream в NATS предоставляет механизмы для хранения, репликации, управления и быстрого доступа к сообщениям, обеспечивая высокую производительность и надежность системы обмена сообщениями. Он предназначен для использования в приложениях, где требуется долговременное хранение сообщений, отслеживание их состояния и быстрый доступ к ним.
Для включения JetStream достаточно в конфигурационном файле добавить одну строчку:
vi /etc/nats/nats-server.conf
...
jetstream: true
И перезапустим сервис:
systemctl restart nats-server
В логе мы должны увидеть что-то на подобие:
tail /var/log/nats/nats.log
---------------- JETSTREAM ----------------
Max Memory: 3.61 GB
Max Storage: 15.69 GB
Store Directory: "/var/lib/nats/jetstream"
-------------------------------------------
Listening for client connections on 0.0.0.0:4222
Server is ready
Добавление системной учетной записи
При выполнении некоторых команд nats мы можем получить ответ:
nats: error: server request failed, ensure the account used has system privileges and appropriate permissions
По умолчанию, мы работаем с nats от анонимной учетной записи с ограниченными правами, которых недостаточно для выполнения некоторых команд или получении определенных сведений.
Для решения проблемы в конфигурационном файле необходимо прописать системную учетную запись, после чего указать клиенту, что мы будем работать под ней.
Так устроена система NATS, что мы не сможем работать с функциями JetStream от системной учетной записи, поэтому для полноценной работы нам нужно будет переключаться между контекстами. Об этом будет ниже.
Открываем файл:
vi /etc/nats/nats-server.conf
Добавим:
...
accounts: {
$SYS: {
users: [
{ user: sys-user, password: sys-pass }
]
}
}
...
* мы добавили системную учетную запись с логином sys-user и паролем sys-pass.
Перезапустим сервис:
systemctl restart nats-server
Теперь можно создать контекст, который будет работать с nats-server от созданной системной записи:
nats context save sys --user sys-user --password sys-pass
Также создадим контекст, который будет работать от анонимной учетной записи:
nats context save default
* default — просто название контекста и оно может быть любым.
После чего выбираем данный контекст:
nats context select sys
Теперь можно подавать клиенту nats любые системные команды, например:
nats server info
После можно переключиться на контекст с анонимной учетной записью:
nats context select default
Настройка кластера
Серверы NATS могут работать в режиме кластера, реплицируя сообщения. Для начала, нам нужно установить его на все ноды кластера. Предположим, что у нас есть 3 сервера со следующими адресами:
- 192.168.0.10
- 192.168.0.20
- 192.168.0.30
Создадим из них кластер NATS.
На всех серверах открываем наш конфигурационный файл:
vi /etc/nats/nats-server.conf
У нас уже была директива cluster — дополним ее, а также добавим опцию server_name:
cluster {
name: "test-nats"
listen: 0.0.0.0:6222
authorization {
user: nats-user
pass: nats-password
timeout: 2
}
routes: [
nats-route://nats-user:nats-password@192.168.0.20:6222
nats-route://nats-user:nats-password@192.168.0.30:6222
]
}
server_name: nats1
...
* где:
- listen — адрес и порт, на котором будут прослушиваться запросы к кластеру.
- authorization — директива отвечает за настройку авторизации кластера. В нашем примере мы укажем, что необходимо вводить логин nats-user и пароль nats-password. При желании, на каждом сервере могут быть свои данные.
- routes — перечисляем список серверов для подключения. В нем нужно указать соседние серверы, к которым необходимо подключиться. Обратите внимание, что строка также содержит логин и пароль для аутентификации.
- server_name — имя сервера. Данная опция обязательно для кластеров NATS с включенной функцией JetStream.
Будьте аккуратны при использовании спецсимволов в пароле nats. Они могу привести к ошибке парсинга конфигурационного файла.
На серверах 2 и 3 выполним такую же правку, только в routes должны быть значения, указывающие на соседние серверы, а также задан свой server_name.
На сервере 2:
...
routes: [
nats-route://nats-user:nats-password@192.168.0.10:6222
nats-route://nats-user:nats-password@192.168.0.30:6222
]
}
server_name: nats2
...
И на сервере 3:
...
routes: [
nats-route://nats-user:nats-password@192.168.0.10:6222
nats-route://nats-user:nats-password@192.168.0.20:6222
]
}
server_name: nats3
...
Открываем на брандмауэрах порт, который используется для нужд кластера (в нашем примере, 6222). Для разных утилит управления фаерволом это делается по-разному.
а) В iptables (как правило, для систем deb):
iptables -I INPUT 1 -p tcp --dport 6222 -j ACCEPT
apt install iptables-persistent
netfilter-persistent save
б) В firewalld (как правило, для систем rpm):
firewall-cmd --permanent --add-port=6222/tcp
firewall-cmd --reload
Перезапускаем сервисы на всех серверах:
systemctl restart nats-server
Смотрим в лог:
tail /var/log/nats/nats.log
Мы должны увидеть что-то на подобие:
Cluster name is test-nats
Listening for route connections on 0.0.0.0:6222
192.168.0.20:6222 - rid:4 - Route connection created
Для проверки можно на одном сервере запустить подписку из командной строки, также как мы это делали после запуска службы:
nats sub -s 127.0.0.1 "test-subject"
А на другом сервере отправить сообщение:
nats pub -s 127.0.0.1 "test-subject" "Test message"
В итоге, сообщение должно быть получено на первом сервере.
Также мы можем получить сведения о серверах в кластере командой:
nats server ls
Отправка файлов
При включеном JetStream мы можем отправлять в хранилище NATS файлы. Рассмотрим простой пример, как это сделать.
Для начала, создадим бакет:
nats object add test-bucket
Список бакетов можно посмотреть командой:
nats object ls
* если у нас настроен кластер, то наш бакет должен появиться и на других нодах.
Загрузить файл можно командой:
nats object put <имя бакета> <путь до файла>
Например:
nats object put test-bucket ./nats-0.0.35-amd64.rpm
* в своем примере я загрузил в созданное хранилище test-bucket ранее скачанный файл nats-0.0.35-amd64.rpm.
Увидеть содержимое бакета можно командой:
nats object ls test-bucket
Подробнее про работу с объектами можно почитать на официальном сайте.
Встроенный мониторинг
На мониторинге остановимся немного подробнее.
Включение
NATS содержит свой набор метрик, которые возвращают состояние сервиса. Для включения данной возможности открываем конфигурационный файл:
vi /etc/nats/nats-server.conf
Добавляем:
...
monitor_port: 8222
Перезапустим сервис:
systemctl restart nats-server
Теперь можно получать информацию в формате JSON с помощью http-запросов. Например, общие метрики:
curl http://127.0.0.1:8222/varz
Или метрика "жив — не жив":
curl http://127.0.0.1:8222/healthz
Весь набор запросов представлен в документации на официальном сайте.
Prometheus
Также разработчик предоставляет экспортера, который может отдавать показатели сервиса на сервер Prometheus. Рассмотрим процесс по шагам.
Установка, настройка и запуск экспортера
У нас уже должен быть развернут сервер Prometheus — если нет, читайте инструкцию Установка Prometheus + Alertmanager + node_exporter на Linux.
Теперь установим prometheus-nats-exporter на сервер NATS.
На официальной страничке Github ознакомимся с релизами экспортера. Копируем ссылку на бинарник (для linux amd64, архив tar.gz).
Перейдем в более подходящий для загрузки исходников каталог:
cd /usr/local/src
Скачаем их:
wget https://github.com/nats-io/prometheus-nats-exporter/releases/download/v0.10.1/prometheus-nats-exporter-v0.10.1-linux-amd64.tar.gz
Распакуем:
tar -zxf prometheus-nats-exporter-v*-linux-amd64.tar.gz
Копируем бинарник в bin-каталог системы:
cp prometheus-nats-exporter-v*-linux-amd64/prometheus-nats-exporter /usr/local/bin/
Проверим, что мы можем запустить экспортер:
prometheus-nats-exporter -version
Мы должны увидеть версию установленного пакета, например:
prometheus-nats-exporter version 0.10.1
Исходники можно удалить:
rm -rf prometheus-nats-exporter*
Теперь настроим запуск экспортера в качестве юнита systemd. Так как экспортер подразумевает возможность сбора различных групп метрик, рассмотрим более сложный вариант настройки сервиса.
Создадим пользователя, от которого будет запускаться и работать юнит:
useradd -r -c 'NATS Prometheus Exporter' nats-exporter
Создадим файл:
vi /etc/systemd/system/nats-exporter@.service
[Unit]
Description=NATS Exporter Service
After=network.target
[Service]
User=nats-exporter
Group=nats-exporter
Type=simple
EnvironmentFile=-/etc/prometheus-nats-exporter/%i.env
ExecStart=/usr/local/bin/prometheus-nats-exporter -%i $POINTSTRING -p $PORT "http://nats1:8222"
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
* обратите внимание, что в качестве источника мы указали http://nats1:8222, а не http://localhost:8222. Это сделано для того, чтобы на сервере Prometheus мы потом смогли отделить какие метрики с каких именно серверов пришли, в противном случае все данные будут отмечаться как с сервера http://localhost:8222, что усложнит анализ. Само собой, имя nats1 должно разрешаться в адрес нашего сервера. Этого эффекта можно добиться с помощью локальной DNS или файла hosts. На каждом сервере это будет свое соответственное имя.
Создадим каталог, в котором будем хранить файлы environment:
mkdir /etc/prometheus-nats-exporter
И создадим для примера 3 файла.
Первый:
vi /etc/prometheus-nats-exporter/varz.env
PORT="9155"
Второй:
vi /etc/prometheus-nats-exporter/leafz.env
PORT="9156"
Третий:
vi /etc/prometheus-nats-exporter/jsz.env
POINTSTRING="streams"
PORT="9157"
И так, что мы сделали. Как говорилось выше, встроенный мониторинг позволяет получить несколько групп метрик, например, leafz, jsz, varz и другие. Мы предусмотрели возможность запуска сервиса для нужной группы. Но необходимо позаботиться, чтобы для нее был создан свой environment-файл, в котором мы указываем порт, на котором будет работать экспортер. Обратите внимание, что некоторые группы требуют своего аргумента, поэтому мы также обозначили его переменной POINTSTRING.
В нашем случае мы создали возможность публиковать метрики для varz, leafz и jsz на портах (соответственно) 9155, 9156 и 9157.
Теперь разрешим и запустим сервисы:
systemctl enable nats-exporter@varz --now
systemctl enable nats-exporter@leafz --now
systemctl enable nats-exporter@jsz --now
Статус сервисов можно проверить командой:
systemctl status nats-exporter@*
Также сервер должен начать слушать на портах 9155, 9156 и 9157:
ss -tunlp | grep 915[5,6,7]
Посмотреть список метрик можно командами:
curl http://127.0.0.1:9155/metrics
curl http://127.0.0.1:9156/metrics
curl http://127.0.0.1:9157/metrics
Получение метрик сервером
Если сервер Prometheus находится на другом сервере и будет забирать метрики по сети, необходимо убедиться, что брандмауэр разрешит подключение. Для этого откроем порты, на которых настроили экспортер. В нашем примере, это 9155, 9156 и 9157.
Для разных утилит управления фаерволом это делается по-разному.
а) В iptables (как правило, для систем deb):
iptables -I INPUT 1 -p tcp --dport 9155 -j ACCEPT
iptables -I INPUT 1 -p tcp --dport 9156 -j ACCEPT
iptables -I INPUT 1 -p tcp --dport 9157 -j ACCEPT
netfilter-persistent save
б) В firewalld (как правило, для систем rpm):
firewall-cmd --permanent --add-port={9155,9156,9157}/tcp
firewall-cmd --reload
Брандмауэр настроен. Можно переходить к настройке самого сервера.
Открываем на сервере конфигурационный файл prometheus:
vi /etc/prometheus/prometheus.yml
Добавим:
- job_name: NATS Server
scrape_interval: 5s
static_configs:
- targets:
- 192.168.0.10:9155
- 192.168.0.10:9156
- 192.168.0.10:9157
* предполагается, что мы добавили к мониторингу один сервер с адресом 192.168.0.10.
Перезапустим сервис prometheus:
systemctl restart prometheus
Можно проверить таргеты в Prometheus.
Grafana
Визуализировать данные метрик можно с помощью графаны. Для этого можно использовать готовые дашборды, например:
- NATS Server Dashboard — общий мониторинг. Используем группу varz.
- NATS JetStream — мониторинг для JetStream. Используем группу jsz.
На страницах мы можем скопировать коды для импорта дашбордов, после чего загрузить их, выбрав в качестве источников данных базу Prometheus.
Подробнее о работе с графаной читайте в инструкциях Установка и настройка сервера Grafana на Linux и Создание графиков в Grafana на основе данных из Prometheus.
Решение возможных проблем
No cluster meta leader found
Натс не запускается в режиме кластера, а в логах мы можем увидеть ошибку:
WARNING: No cluster meta leader found. The cluster expects 8 nodes but only 4 responded. JetStream operation require at least 5 up nodes.
* особое внимание обратите на значения, отмеченные желтым. У вас это могут быть другие цифры. В моем случае это означает, что у меня кластер из 8 серверов, но так как доступны только 4, не создается кворума и кластер не может полноценно запуститься.
Причина: как правило, из-за того, что не все участники кластера запущены и доступны по сети.
Также проблема может возникнуть из-за быстрого переименовывания узлов кластера. В таком случае NATS не успевает перестроиться и начинает хранить как старые имена нод (которые уже не доступны), так и новые.
Решение: проверяем, что все узлы доступны по сети.
Если все участники кластера работают, но NATS продолжает писать ошибку или пишет неправильно число нод, то останавливаем все ноды:
systemctl stop nats-server
Удаляем файл:
rm -f /var/lib/nats/SYS/_js_/_meta_/peers.idx
* где каталог /var/lib/nats определен в конфигурационном файле и в вашем случае может быть другим.
После запускаем службу на всех участниках кластера:
systemctl start nats-server