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.


Проверим список запущенных контейнеров.


Просматриваем назначенные подсети.


Файл конфигурации контейнера 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/companies/selectel/articles/755076/


Интересные статьи

Интересные статьи

Привет, Хабр!  В этой статье хотел бы поделиться опытом участия в процессе цифровизации огромной компании. Под катом расскажу об особенностях, с которыми столкнулся при взаимодействии с большим к...
Согласно данным Всемирной организации здравоохранения, серьезные проблемы со зрением испытывают около 300 миллионов человек на нашей планете. Из них более 40 миллионов являются полностью незрячими.Это...
Что такое 3DEXPERIENCE? Это бренд, объединяющий в себе платформенные решения Dassault Systemes из разных доменов, например, PLM-решения бренда ENOVIA, CAD-решения бренда CATIA или CAE-решения бренда S...
На предприятиях и в конструкторских бюро делают все для того, чтобы участники процесса разработки продукции действовали в едином ключе. Но заносить данные, поступающие из...
В 2021 году уже известно, что Zabbix предлагает в качестве средства комплексного мониторинга инфраструктуры VMware набор шаблонов, использующих функционал Low Level Discovery (LLD) и элем...