Привет, Хабр! Меня зовут Дмитрий, я старший системный инженер в Selectel, работаю с серверами и клиентским оборудованием.
Ранее я написал статью о том, как появилась идея создать бота на базе API Telegram, который анализирует показатель S.M.A.R.T дисков. Теперь более детально расскажу о его разработке и о том, как было развернуто приложение.
Перед тем как мы погрузимся в детали, добавлю, что у меня нет опыта коммерческой разработки и администрирования инфраструктуры. В сети довольно много информации о том, как это делать в теории, но мало практических материалов для выхода на уровень продакшена.
Как системный инженер я изучаю новые вещи «методом тыка». Поэтому все представленные сборки приложения и способы его развертывания основаны на личном опыте и умении искать информацию в сети, а также применении «метода тыка» для получения конечного результата.
Воспользуйтесь навигацией, чтобы выбрать интересующий вас блок:
→ Инфраструктура
→ Разработка
→ Заключение
Инфраструктура
Важный аспект при планировании инфраструктуры приложения — ее готовность к будущему масштабированию. Начнем с визуализации и описания схемы взаимодействия компонентов.
Основные компоненты модели взаимодействия:
- Сервер: виртуальная машина с двумя vCPU, 4 ГБ ОЗУ и 10 ГБ SSD. Операционная система — Ubuntu 22.04.
- Внутрикорпоративные сервисы Selectel: сервисы с содержанием актуальных данных S.M.A.R.T и пользователей, которые могут с ними взаимодействовать.
- Telegram: интеграция с Telegram API для уведомлений и связи с пользователями.
- Сеть: задает связи между компонентами.
- Инженер: имеет доступ в ОС через SSH-ключ и на веб-панель Portainer.
Сервер
Сервер — ключевая часть инфраструктуры, я развернул его в облаке Selectel. В качестве ОС выбрал Ubuntu 22.04.
> root@server:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 10G 0 disk
├─sda1 8:1 0 10G 0 part /
└─sda14 8:14 0 8M 0 part
sr0 11:0 1 492K 0 rom
Сетевые интерфейсы
IP-адрес сервера — 172.168.1.1.
> ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether fa:16:3e:a9:a5:8a brd ff:ff:ff:ff:ff:ff
altname enp0s3
altname ens3
inet 172.168.1.1/24 brd 172.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fea9:a58a/64 scope link
valid_lft forever preferred_lft forever
Настройка SSH-доступа
В данном примере SSH-ключ копируется на сервер для безопасного доступа. Также изменяется конфигурация SSH для отключения входа по паролю.
ssh-copy-id</i> <i>root@172.168.1.1
> sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config
> sed -i 's/PasswordAuthentication.*/PasswordAuthentication no/g' /etc/ssh/sshd_config
> systemctl restart sshd
Все шаги по развертыванию приложения будем выполнять с использованием Ansible.
Установим Ansible на локальную операционную систему
> apt-add-repository ppa:ansible/ansible
> apt update
> apt install ansible -y
> ansible --version
ansible [core 2.15.2]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] (/usr/bin/python3)
jinja version = 3.0.3
libyaml = True
В файле
/etc/ansible/hosts
определяем удаленный хост srv-smart.[servers]
srv-smart ansible_host=172.168.1.1
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Проверяем доступность удаленного хоста.
> ansible srv-smart -m ping
srv-smart | SUCCESS => {
"changed": false,
"ping": "pong"
}
На схеме взаимодействия указаны:
-
Порт 22
— для удаленного доступа к серверу по SSH, -
eth0
— интерфейс, на который подан VLAN для связи с внешней и внутренней сетями сервисов Selectel.
Для развертывания приложения использую Docker, в котором работают три контейнера:
-
portainer
— для запуска Portainer, который позволяет управлять контейнерами в Docker, -
mongodb
— для развертывания MongoDB, -
service
— для запуска сервисов приложения на Node.js.
Сначала клонируем репозиторий на локальную ОС.
> git clone git@bitbucket.org:khamchenko/smart-slc.git
> curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
> echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
> apt update
> apt-cache policy docker-ce
> apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Проверяем статус.
> systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-06-06 15:55:44 UTC; 30s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 3371 (dockerd)
Tasks: 9
Memory: 27.1M
CPU: 706ms
CGroup: /system.slice/docker.service
└─3371 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
> docker -v
Docker version 24.0.5, build ced0996
Редактируем переменные окружения в файле
smart-slc/docker.infra/.env
.MONGO_USER=<mongo-user>
MONGO_PASS_PROD=<mongo-pass-prod>
MONGO_PASS_DEV=<mongo-pass-dev>
MONGO_DB=<mongo-db>
MONGO_INITDB_ROOT_USERNAME=<mongo-root>
MONGO_INITDB_ROOT_PASSWORD=<mongo-root-pass>
MONGO_INITDB_DATABASE=<mongo-init-db>
TG_TOKEN=<tg-token-jwt>
JWT_SECRET=<jwt-secret>
TELEGRAM_TOKEN_DEV=<tg-token-dev>
TELEGRAM_TOKEN_PROD=<tg-token-prod>
Для сборки приложения используется webpack. Для этого выделили отдельный контейнер
nodejs-build
, который содержит окружение node.js.> cd ./smart-slc/docker.infra/nodejs-build
> docker compose up -d
> bash build-prod.sh
Запускаем Ansible-плейбук для развертывания инфраструктуры на удаленном хосте
srv-smart
.> ansible-playbook docker.infra/ansible/srv-smart/main/pb_main.yml
После развертывания на удаленном хосте проверяем статус контейнеров.
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
adb13e7089d8 mongo:latest "docker-entrypoint.s…" 33 seconds ago Up 32 seconds 0.0.0.0:35689->27017/tcp, :::35689->27017/tcp mongodb
b6c3e9e2fdfe nodejs-nodejs "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:5001-5002->5001-5002/tcp, :::5001-5002->5001-5002/tcp services
694bb2e80cb5 portainer/portainer-ce:latest "/portainer" 18 minutes ago Up 18 minutes 8000/tcp, 9000/tcp, 0.0.0.0:9443->9443/tcp, :::9443->9443/tcp portainer
Контейнер Portainer
Portainer.io предоставляет средство управления Docker-контейнерами. Рассмотрим его структуру и взаимодействие с другими контейнерами.
-
Подсеть (172.18.0.0/16)
с названиемnetwork-smart
создана для связи между контейнерамиmongodb
иservices
, обеспечивая их взаимодействие. -
Подсеть (172.17.0.0/16) bridge
. -
Порт 9443
предоставляет внешний доступ к веб-интерфейсу Portainer.
Конфигурационный файл
docker-compose.yml
.version: "3.8"
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
hostname: portainer
restart: always
ports:
- 9443:9443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- {{ path_infra }}/smart-slc/portainer/data:/data
Переходим в браузерной строке на https://172.168.1.1:9443 и задаем
username
и password
.Проверим список запущенных контейнеров.
Проверим подключение к базе данных извне с помощью MongoDB Compass.
Файл конфигурации контейнера
docker-compose.yml
.version: "3.8"
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
hostname: portainer
restart: always
ports:
- 9443:9443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- {{ path_infra }}/smart-slc/portainer/data:/data
Контейнер MongoDB
Представляет собой NoSQL базу данных MongoDB. В этом контейнере созданы коллекции users (пользователи) и devices (устройства). Более подробно со схемами коллекций можно ознакомиться здесь. Давайте рассмотрим структуру контейнера и проверим работу.
На схеме указаны:
-
Порт 35689
— используется для подключения к базе данных, - связь с контейнером
services
осуществляется через сетьnetwork-smart
.
docker-compose.yml
.version: "3.8"
services:
mongodb:
image: mongo:latest
container_name: mongodb
hostname: mongodb
restart: always
env_file: [.env]
ports:
- 35689:27017
volumes:
- {{ path_infra }}/smart-slc/mongodb/data:/data/db/
- {{ path_infra }}/smart-slc/mongodb/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js
networks:
- network-smart
logging:
options:
max-size: "200k"
max-file: "3"
networks:
network-smart:
external: true
Проверяем версию установленной
Mongodb
.> docker exec -it mongodb /bin/bash
> mongosh
Current Mongosh Log ID: 64d7802347ddb6a2ae56c7b0
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.10.1
Using MongoDB: 6.0.8
Using Mongosh: 1.10.1
Проверим подключение к базе данных извне с помощью MongoDB Compass.
Контейнер Services
Представляет собой среду node.js с пакетом pm2. Внутри контейнера запущены следующие компоненты приложения:
-
workers-smart
— обработчики для синхронизации MongoDB с БД Selectel и синхронизации пользователей во внутренних сервисах, -
srv-smart
— обработчик для анализа информации S.M.A.R.T., -
tg-smart
— обработчик событий Telegram.
docker-compose.yml
.version: "3.8"
services:
mongodb:
image: mongo:latest
container_name: mongodb
hostname: mongodb
restart: always
env_file: [.env]
ports:
- 35689:27017
volumes:
- {{ path_infra }}/smart-slc/mongodb/data:/data/db/
- {{ path_infra }}/smart-slc/mongodb/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js
networks:
- network-smart
logging:
options:
max-size: "200k"
max-file: "3"
networks:
network-smart:
external: true
Файл
Dockerfile
с инструкциями для создания образа контейнера.FROM node:18.14.0
RUN npm install pm2 -g
Файл
init-node.sh
для запуска сервисов.#!/bin/bash
docker exec -it services /bin/bash -c "cd /srv/tg-smart && npm install"
docker exec -it services /bin/bash -c "cd /srv/srv-smart && npm install"
docker exec -it services /bin/bash -c "cd /srv/workers-smart && npm install"
docker exec -it services /bin/bash -c "pm2 start"
docker exec -it services /bin/bash -c "pm2 save"
Файл
upd-build.sh
для перезапуска сервисов после повторной сборки.docker exec -it services /bin/bash -c "cd /srv/tg-smart && npm install && pm2 restart srv-smart"
docker exec -it services /bin/bash -c "cd /srv/srv-smart && npm install && pm2 restart smart-slc"
docker exec -it services /bin/bash -c "cd /srv/workers-smart && npm install && pm2 restart workers-smart"
Файл конфигурации pm2
ecosystem.config.js
.module.exports = {
apps : [{
name: "tg-smart",
script: "/srv/tg-smart/api.prod.js"
},{
name: "srv-smart",
script: "/srv/srv-smart/api.prod.js"
},{
name: "workers-smart",
script: "/srv/workers-smart/api.prod.js"
}]
}
Проверяем работу сервисов.
docker exec -it services bash
> root@services:/# pm2 status
> root@services:/# pm2 monit
Схема связей:
-
Порты 5001-5003
используются для внутреннего взаимодействия. - Связь
tg-smart
иsrv-smart
осуществляется через socket.io для доставки сообщений. - Связь
mongodb-smart
иsrv-smart
. - Cвязь
mongodb-smart
иtg-smart
. - Cвязь
mongodb-smart
иworkers-smart
— для синхронизации пользователей и пороговых значений S.M.A.R.T. - Cвязь
worker-smart
ивнутрикорпоративных сервисов Selectel
. - Связь
tg-smart
иTelegram
.
Внутрикорпоративные сервисы Selectel
Доступ к сервисам Selectel строго ограничен правами группы доступа. Для управления логикой взаимодействия с сервисами создал контейнеры
mongodb
и services
. Сервис workers-smart
выполняет эту логику взаимодействия, а база данных MongoDB
хранит пороговые значения S.M.A.R.T и информацию о пользователях.Telegram
Для взаимодействия с Telegram API использую npm-пакет node-telegram-bot-api. В составе сборки сервиса
tg-smart
он обрабатывает логику подключения к Telegram.Сеть
Как я описал выше, отдельные компоненты инфраструктуры имеют связи. Они обусловлены организацией сети на уровне Docker и самой ОС. Доступ извне ограничен правилами iptables и ufw.
Текущий вывод iptables после запуска контейнеров Docker.
>iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:9443
ACCEPT tcp -- anywhere 172.18.0.2 tcp dpt:5002
ACCEPT tcp -- anywhere 172.18.0.2 tcp dpt:5001
ACCEPT tcp -- anywhere 172.18.0.3 tcp dpt:27017
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
Проверим сетевые интерфейсы.
>ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether fa:16:3e:a9:a5:8a brd ff:ff:ff:ff:ff:ff
altname enp0s3
altname ens3
inet 172.168.1.1/24 brd 172.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fea9:a58a/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:06:d0:81:b1 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:6ff:fed0:81b1/64 scope link
valid_lft forever preferred_lft forever
4: br-6bf419f6296f: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:e0:a6:17:ae brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.18.255.255 scope global br-6bf419f6296f
valid_lft forever preferred_lft forever
inet6 fe80::42:e0ff:fea6:17ae/64 scope link
valid_lft forever preferred_lft forever
5: br-7a47cf77f7b2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:b8:d1:fc:36 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.19.255.255 scope global br-7a47cf77f7b2
valid_lft forever preferred_lft forever
inet6 fe80::42:b8ff:fed1:fc36/64 scope link
valid_lft forever preferred_lft forever
25: veth011a094@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-6bf419f6296f state UP group default
link/ether ba:5e:30:fe:7e:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::b85e:30ff:fefe:7eb9/64 scope link
valid_lft forever preferred_lft forever
27: veth664666f@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-7a47cf77f7b2 state UP group default
link/ether 92:81:05:84:5b:8e brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::9081:5ff:fe84:5b8e/64 scope link
valid_lft forever preferred_lft forever
29: veth373aaf8@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-6bf419f6296f state UP group default
link/ether ea:71:35:2a:9f:fb brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::e871:35ff:fe2a:9ffb/64 scope link
valid_lft forever preferred_lft forever
В файл
/etc/ufw/after.rules
добавим правила.*filter
:DOCKER-USER - [0:0]
:ufw-user-input - [0:0]
-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-USER -m conntrack --ctstate INVALID -j DROP
-A DOCKER-USER -i eth0 -j ufw-user-input
-A DOCKER-USER -i eth0 -j DROP
COMMIT
Далее выполняем команды для перезапуска службы
ufw
, открытия портов 22
и 9443
и включения ufw
.> systemctl restart ufw
> ufw allow 22
> ufw allow 9443
> ufw enable
Результат сканирования портов.
> nmap -p- 172.168.1.1
Nmap scan report for 172.168.1.1 Host is up (0.030s latency). Not shown: 65533 filtered tcp ports (no-response) PORT STATE SERVICE 22/tcp open ssh 9443/tcp open tungsten-https
Инженер
Роль инженера в данной схеме описывает его взаимодействие с компонентами инфраструктуры:
- доступ в ОС через SSH-ключ;
- доступ к веб-интерфейсу Portainer.
Разработка
Предлагаю пройтись по основным моментам разработки.
Что использовал?
koa.js, axios, lodash, moment, mongoose, nodemon, uuid, babel, webpack, jwt, socket.io, node-telegram-bot-api
Ниже вы можете кратко ознакомиться с некоторыми деталями.
webpack
Сборщик модулей, который используется для упаковки и оптимизации кода приложения. Подробнее с конфигурацией можно ознакомиться в репозитории.
mongoose
Библиотека для работы с MongoDB. Используется для определения объектов со строго типизированной схемой, соответствующей документам MongoDB.
Подробнее со схемами коллекции устройств и пользователей можно ознакомиться в репозитории. Для подключения к MongoDB используется метод mongoConnection.
koa.js
Фреймворк для Node.js, используемый как middleware. Обеспечивает гибкость разработки и масштабируемость, минимизируя объем ресурсов для запуска.
socket.io
Библиотека на основе протокола WebSocket. Используется для обмена сообщениями между сервисами
tg-smart
и srv-smart
.Структура
.
├── .env // константы окружения
├── .babelrc // конфигурационный файл babel
├── api
│ ├── api.prod.js // build
│ ├── app.js // основной файл приложения на koa.js.
│ ├── server.js // точка входа в приложение
│ ├── collection // доступ к коллекциям mongodb
│ ├── config // формирование констант из окружения и конфигурационных файлов
│ ├── connectors // подключения к базам данных и другим сервисам
│ ├── constants // константы окружения
│ ├── handlers // обработчики ошибок и другие обработчики
│ ├── helpers // вспомогательные функции и классы
│ ├── services // вспомогательные методы для работы с данными
│ ├── socket // логика подключения socket.io
│ └── utils // утилиты для работы с окружением
├── config // содержит конфигурационные объект
├── package.json // зависимости
├── schemes // содержит схемы для работы с данными MongoDB
└── webpack // содержит конфигурационный файл webpack для сборки модулей
Сборка workers-smart
Я уже писал, что опущу подробности о сервисе workers-smart, так как его главная функция заключается в синхронизации с сервисами Selectel. Конкретно он занимается обновлением текущих пороговых значений атрибутов S.M.A.R.T в базе данных MongoDB. Детали его реализации находятся внутри нашего закрытого окружения и остаются в рамках строгой политики конфиденциальности и безопасности данных.
Сборка tg-smart
Подробнее ознакомиться с данной сборкой можно в репозитории. Этот сервис выделен в отдельный модуль, что обеспечивает удобство масштабирования приложения в будущем. Главные задачи tg-smart — это управление пользовательским интерфейсом, трансляция сообщений от других сервисов и проверка подлинности пользователей.
Благодаря использованию транспорта socket.io впоследствии появится возможность декомпозировать приложение на функциональные части и распределять нагрузку между различными сервисами.
tg-smart
через socket.io. Также в коде файла осуществляется подписка на события состояния соединения с другими сервисами через socket.io. Подключение к Telegram API реализуется через библиотеку node-telegram-bot-api.При подключении сервиса
srv-smart
сначала проверяется валидность токена с помощью метода jwt.verify. После успешной проверки сервис присоединяется к комнате “service”
в socket.io и ожидает сообщения для передачи в Telegram от других сервисов.В этой части кода реализована подписка на событие
“message”
от Telegram. Когда сообщение поступает, происходит проверка наличия пользователя в базе данных. Если пользователь уже существует, отправляется сообщение сервису srv-smart
через socket.io. В случае отсутствия пользователя он создается в базе данных, и ему отправляется приветственное сообщение, аналогичное тому, что генерируется при отправке события “/start”
. Обработка события “/start”
также предусматривает свой обработчик, который будет использоваться для отрисовки будущего меню.Сборка srv-smart
Подробнее ознакомиться с этим сервисом можно в репозитории. Данный компонент инфраструктуры занимается обработкой входящих сообщений и предоставляет информацию о состоянии атрибутов S.M.A.R.T.
“message”
от сервиса tg-smart
. Когда происходит получение сообщения, важно учесть, что информация о состоянии атрибутов S.M.A.R.T может быть представлена несколькими сообщениями.Для обработки этой ситуации используется механизм таймаута. Как только приходит сообщение, запускается таймаут длительностью одну секунду, в течение которого от пользователя ожидается следующее сообщение. При этом сообщение сохраняется в базе данных вместе с идентификатором таймера. Если в течение этой секунды не поступает новое сообщение, таймаут обнуляется, а все данные, связанные с ним, также удаляются из базы данных. Когда собирается достаточное количество информации, производится анализ сообщений на наличие данных о состоянии атрибутов S.M.A.R.T с помощью метода checkSmart.
Наконец, метод checkSmart выполняет анализ показателей S.M.A.R.T и определяет общий статус диска. После формирования ответа происходит вызов метода sendMessage для отправки сообщения в сервис
tg-smart
, которое затем передается в чат Telegram.Заключение
Вот так устроен и работает созданный бот для проверки дисков. Могу предположить, что появится вопрос про пороговые значения — отвечу сразу.
Я понимаю, что вопрос пороговых значений атрибутов S.M.A.R.T вызывает интерес. Но Selectel придерживается строгой политики конфиденциальности и безопасности данных. В связи с этим мы не можем раскрыть подробные пороговые значения по каждой модели накопителя. Вы можете настроить свои системы мониторинга, исходя из базовых параметров, которые я указал в прошлой статье.
Описанный бот — небольшая функциональность, которая облегчает жизнь инженерам дата-центров. Возможности мониторинга состояния инфраструктуры для клиентов мы реализуем на другом уровне. Сейчас мы рассматриваем возможность добавления новых функциональностей и улучшений в ближайшем будущем, в том числе за счет внедрения модуля IPMI. Это даст пользователям еще больше инструментов для мониторинга и управления своими ресурсами.
Другие полезные материалы
Комментарии (12)
esche_odin
17.08.2023 13:02+1троллейбус_буханка.джипег
dkhamchenko Автор
17.08.2023 13:02+2Ради искусства. Вы еще не видели, что способен сотворить инженер из пачкордов.
Спойлер
Например, плетку.
Wesha
17.08.2023 13:02У меня только один вопрос: а что Вы делать будете,
есликогда этот Ваш Телеграм — ффсё?dkhamchenko Автор
17.08.2023 13:02+2В компании существует отдел, занимающийся внутренними сервисами и вспомогательными инструментами. Думаю, в какой-то момент вся эта история перейдет в общий web-сервис со множеством вспомогательных инструментоа. Ну а пока боты, созданные инженерами в Телеграме, являются быстрым решением их задач.
AlexandreFrolov
17.08.2023 13:02Я у себя на сервисе настроил мониторинг всех серверов через Zabbix, в том числе состояние дисков. При этом в зависимости от уровней серьезности сообщения отправляются либо на E-Mail, либо на E-Mail+SMS, либо на E-Mail+SMS+Звонок_синтезированным_голосом+Отправка_в_Телеграм
И все, это, конечно, можно настраивать.
Для отправки SMS и голосовых звонков используются разные провайдеры.dkhamchenko Автор
17.08.2023 13:02Как я писал в комментарии выше, в компании также используется Zabbix. Из идей: можно было бы клиентам услуг Selectel добавлять интеграции с тикет системой. Например, по API создавать тикеты о планировании замены дисков или других комплектующих.
AlexandreFrolov
17.08.2023 13:02Тикеты да, создавать можно, только вот стоит ли это автоматизировать?
Обычно когда я получаю критичные сообщения от Zabbix, то вначале пытаюсь понять сам, что случилось и что делать.
Вот если бы у вас была служба администрирования серверов, которой можно было бы поручить решение подобных задач, то тут да, им можно было бы отправлять такие тикеты, созданные zabbix.dkhamchenko Автор
17.08.2023 13:02С одной стороны, да, в каждом тикете еще необходимо потвердеть действия, к которым мог бы приступить инженер. С другой, все зависит от количества арендуемых серверов и количества затраченных ресурсов. Для тех, у кого парк из десятков серверов, довольно длительно разбирать каждый. При правильно настроенном процессе на своевременную замену несправной комплектующей (блок питания, CPU, ОЗУ, диски, оптические трансиверы) риск возникновения проблем снижается.
К сожалению, услуги по администрированию сейчас не предоставляются. Техническая поддержка старается предлагать помощь партнеров.AlexandreFrolov
17.08.2023 13:02К сожалению, когда после перезагрузки одного из моих арендованных серверов произошла остановка из-за проблем с RAID-массивом, мне в тикете ничего такого не предложили - никаких партнеров. Хорошо что мне помог один мой хороший знакомый, а то была бы беда.
Полагаю, было бы неплохо вашей компании пересмотреть возможность предоставления подобных услуг. На мой взгляд, было бы очень даже ориентировано на клиентов!
TwenKey
Свои решения это всегда круто. У себя для этого используем smarctl exporter - prometheus - grafana. К ней можно прикрутить уже плагины на slack и прочие сервисы, или пользоваться alertManager.
dkhamchenko Автор
В компании для внутренних сервисов и облачной инфраструктуры активно используется Zabbix. Он интегрирован с пользователем alertManager в Jira, что позволяет автоматически создавать задачи. Далее, эти задачи дублируются в проекте инженеров для согласования и оперативных действий с дежурной сменой. Это позволяет довольно быстро и эффективно реагировать на проблемы и производить замены комплектующих даже в выходные и праздничные дни. Этот процесс также распространен на другие компоненты инфраструктуры.