Telegram-бот для диагностики дисков в серверах. Как я собрал инфраструктуру и что использовал для разработки

от автора

image

Привет, Хабр! Меня зовут Дмитрий, я старший системный инженер в Selectel, работаю с серверами и клиентским оборудованием.

Ранее я написал статью о том, как появилась идея создать бота на базе API Telegram, который анализирует показатель S.M.A.R.T дисков. Теперь более детально расскажу о его разработке и о том, как было развернуто приложение.

Перед тем как мы погрузимся в детали, добавлю, что у меня нет опыта коммерческой разработки и администрирования инфраструктуры. В сети довольно много информации о том, как это делать в теории, но мало практических материалов для выхода на уровень продакшена.

Как системный инженер я изучаю новые вещи «методом тыка». Поэтому все представленные сборки приложения и способы его развертывания основаны на личном опыте и умении искать информацию в сети, а также применении «метода тыка» для получения конечного результата.

Воспользуйтесь навигацией, чтобы выбрать интересующий вас блок:

Инфраструктура
Разработка
Заключение

Инфраструктура


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

Основные компоненты модели взаимодействия:

  1. Сервер: виртуальная машина с двумя vCPU, 4 ГБ ОЗУ и 10 ГБ SSD. Операционная система — Ubuntu 22.04.
  2. Внутрикорпоративные сервисы Selectel: сервисы с содержанием актуальных данных S.M.A.R.T и пользователей, которые могут с ними взаимодействовать.
  3. Telegram: интеграция с Telegram API для уведомлений и связи с пользователями.
  4. Сеть: задает связи между компонентами.
  5. Инженер: имеет доступ в ОС через SSH-ключ и на веб-панель Portainer.

Сервер

Сервер — ключевая часть инфраструктуры, я развернул его в облаке Selectel. В качестве ОС выбрал Ubuntu 22.04.

Этапы настройки удаленного хоста srv-smart

Разметка дискового пространства

> 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 

Этапы локальной установки Docker

Начинаем настройку Docker с установки его компонентов.

> 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

На Github есть полезная публикация с подробным описанием использования UFW и Docker.

Текущий вывод 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 впоследствии появится возможность декомпозировать приложение на функциональные части и распределять нагрузку между различными сервисами.

Подробнее о коде файла

В коде файла присутствуют два метода для работы с JWT: один – для проверки, а другой – для генерации токена для аутентификации сервисов, подключенных к 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. Это даст пользователям еще больше инструментов для мониторинга и управления своими ресурсами.

Другие полезные материалы


   


ссылка на оригинал статьи https://habr.com/ru/articles/755076/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *