Про наглого клиента, или мониторинг borg backup в prometheus на коленке

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Есть у меня один сервер в облаке hetzner, с него нужно было делать бекап на storage box, есть у хетцнера такое онлайн-хранилище.

Storage box поддерживает соединение по 22 и 23 портам (это важно для дальнейшего повествования)

Сам хетцнер рекомендует использовать для моей задачи borg, ну а почему бы и нет. Попробовал, работает, что-то там дедублицирует, сжимает, есть не просит.

Я написал два bash скрипта. Первый инициализирует borg, второй выполняет резервное копирование. Ничего особенного, но во втором скрипте сначала borg подключается и создает новый бекап, а потом sftp клиент подключается, на всякий случай, проверить сколько места осталось свободного.

При этом Borg подключается по протоколу ssh на 23 порт (Хетцнер называет это extended ssh service). А вот sftp клиент по умолчанию использует 22 порт.

Ssh ключ для подключений на оба порта один и тот же. Публичный ключик заранее загружен специальным образом в storage box. Приватный ключик положили тут ~/.ssh/id_rsa на сервере.

Если делать все ручками, то после первого подключения к storage box потребуется подтверждение отпечатков пальцев:

Are you sure you want to continue connecting (yes/no/[fingerprint])?

Когда мы согласимся, в файл ~/.ssh/known_hosts будет добавлена строчка для storage box, и дальше подключения будут проходить без лишних вопросов.

Если же хочется установку скрипта для бекапов автоматизировать, то можно заранее добавить нужную строчку в known_hosts. (Я это, как и всю установку и настройку, делаю ролью ansible)

А теперь внимание, вопрос знатокам! Могут ли у одного хоста быть разные отпечатки пальцев для разных портов? И если да, то как это будет выглядет в файле known_hosts?

Но, поехали дальше. Итак, я заранее добавил строчку в known_hosts:

myuser.your-backup.de ssh-rsa AAAA%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%...

и быстро убедился, что borg все равно запрашивает подтверждение отпечатков пальцев. При чем отпечатки для ssh-ed25519.

Вопрос знатокам номер два. Если мы подключаемся к хосту с ключом одного типа (ssh-rsa), может ли клиент запрашивать подтверждение отпечатков для другого типа ключа (ssh-ed25519 например) ?

Признаюсь, что сначала я не удосужился разобраться, почему это происходит, просто добавил вторую строчку в known_hosts:

myuser.your-backup.de ssh-rsa AAAA%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%...
myuser.your-backup.de ssh-ed25519 AAAA%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%...

И все заработало.

Но работало не долго. В один прекрасный день скрипт перестал создавать бекапы. И заметил я это случайно. Ну да, правда жизни. И да, ничего не мониторилось.

Некоторое время потребовалось для того, чтобы обнаружить, что вторая строчка магическим образом пропала из файла known_hosts.

Кто-то заботливо создавал резервную копию моего файла - known_hosts.old, появлялся новый known_hosts, уже без ssh-ed25519 ключа.

Потыкав, как это бывает, в разных направлениях, я нашел виновника. Повысив log-level sftp клиента я увидел следующее:

$ sftp -4 -vvv -i ~/.ssh/id_rsa myuser@myuser.your-backup.de
...
debug3: hostkeys_foreach: reading file "~/.ssh/known_hosts"
debug3: hostkeys_find: found ssh-rsa key at ~/.ssh/known_hosts:1
debug3: hostkeys_find: deprecated ssh-ed25519 key at ~/.ssh/known_hosts:2
..
debug3: client_input_hostkeys: 1 server keys: 0 new, 1 retained, 0 incomplete match. 1 to remove
debug2: check_old_keys_othernames: checking for 1 deprecated keys
debug3: check_old_keys_othernames: searching ~/.ssh/known_hosts for myuser.your-backup.de / (none)
debug3: hostkeys_foreach: reading file "~/.ssh/known_hosts"
...
Deprecating obsolete hostkey: ED25519 SHA256:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
debug3: hostkeys_foreach: reading file "~/.ssh/known_hosts"
debug3: host_delete: RSA key already at ~/.ssh/known_hosts:1
~/.ssh/known_hosts:2: Removed ED25519 key for host myuser.your-backup.de
...

Я признаюсь, и подумать не мог, что клиент так беспардонно может начать удалять отпечатки из known_hosts.

Подключаясь к хосту по порту 22, sftp клиент не увидел соответствия отпечаткам для ssh-ed25519, посчитал их неактуальными и удалил. И ему пофиг, что для другого порта этого же хоста запись нужна!

Теперь внимание, вопрос знатокам номер 3. Почему какое-то время скрипт мог работать? (Я сам не знаю ответа на этот вопрос)

Ладно, поехали дальше. Проблему решил добавлением в файл ~/.ssh/config двух строк:

Host myuser.your-backup.de
    UpdateHostKeys no

Теперь пришло время того, что должно было быть сделано сразу - мониторинг.

Пишем экспортер для мониторинга бекапа в prometheus

Я решил сделать максимально простое, но в то же время функциональное решение для мониторинга бекапов. А именно написать простейший exporter для prometheus, тем более сервер рабочий уже есть.

Погнали. Вот код на bash:

#!/bin/bash
while true; do
    {
        echo -e "HTTP/1.1 200 OK\nContent-Type: text/plain\n"
        cat /path/to/file_with_metrics
    } | nc -l -p 9999 -q 1
done

Что мы тут имеем? Бесконечный цикл, который прослушивает порт 9999 и отправляет туда текст из нашего файла с метриками, снабдив HTTP-заголовками.

Сохраняем скрипт например в /usr/local/bin/borg_exporter.sh Создаем systemd unit который будет его запускать:

[Unit]
Description=Borgbackup prometheus exporter
After=network-online.target

[Service]
ExecStart=/usr/local/bin/borg_exporter.sh
Type=simple
Restart=always

Сохраняем в /etc/systemd/system/borg_exporter.service.

Активируем наш новый сервис:

sudo systemctl daemon-reload
sudo systemctl enable borg_exporter
sudo systemctl start borg_exporter

Да, надо не забыть сделать скрипт запускаемым, да надо бы запускать все это не от root, и да, надо открыть порт на фаерволе и т.д. ...

Но это простое решение реально может работать с прометеусом!

Добавляем в его настройки (в prometheus.yml, в scrape_configs):

- job_name: borg
  static_configs:
    - targets:
      - 1.2.3.4:9999 # IP of your server
  scheme: http

где 1.2.3.4 - IP адрес сервера (если prometheus работает на том же сервере, то заменить на localhost)

Перезагружаем promehteus, и, если в файле /path/to/file_with_metrics есть хотя бы одна строка в формате

metric_name value

, то эта метрика будет им считываться. Value может быть только целым числом или числом с плавающей точкой.

Остается нам настроить обновление нужных метрик в файле, а также алерты.

Возвращаемся к моему основному скрипту, который запускает бекап, и да, код которого я тут не приводил.

Давайте я отброшу лишнее, и оставлю только то, что касается мониторинга.

#!/bin/bash
...
borg create ssh://myuser@myuser.your-backup.de:23/./folder::bckp_name /target/
borg_last_backup_error_code=$?
echo "borg_last_backup_error_code $borg_last_backup_error_code" > /path/to/file_with_metrics

echo "borg_last_run_timestamp $(date +%s)" >> /path/to/file_with_metrics

borg_storage_free_space=$((ssh myuser@myuser.your-backup.de 'df') | tail -n 1 | awk '{print $4}')
echo "borg_storage_free_space $borg_storage_free_space" >> /path/to/file_with_metrics

borg_storage_disk_space=$((ssh myuser@myuser.your-backup.de 'df') | tail -n 1 | awk '{print $2}')
echo "borg_storage_disk_space $borg_storage_disk_space" >> /path/to/file_with_metrics

Что тут происходит?

borg create ... - запускается создание бекапа и сохранение его на storage box. Для работы команды нужны кое-какие дополнительные env-переменные, но я это опускаю.

Далее мы записываем код ошибки для команды borg create в файл метрик. 0 - если все ок.

Следующее - добавляем в файл метрик текущее время в формате unix.

И последние два - получаем сводное место на storage box (в блоках), добавляем третью строку с метрикой, получаем полный размер доступного диска, добавляем 4ю строку.

После запуска скрипта файл /path/to/file_with_metrics должен приобрести вид:

borg_last_backup_error_code 0
borg_last_run_timestamp 1728745782
borg_storage_free_space 444444444
borg_storage_disk_space 555555555

И эти метрики будет считывать prometheus.

Можно было бы обойтись и тремя метриками, но чтобы не заморачиваться размером блоков, будем считать оставшееся место в процентах.

С какой частотой запускать скрипт бекапа - дело ваше. В моем случае он раз в день запускается по cron.

Ну и последнее, алерты.

- name: borgbackup_alerts
  interval: 30s
	rules:
    - alert: InstanceDown
      expr: borg_last_backup_error_code > 0
      for: 60s
	  annotations:
		description: 'Oh, no, borg backup failed!'
		summary: 'Borg error code not equal zero'
      labels:
        severity: warning

Выше пример алерта, настраивается в конфиге prometheus. Всего предлагаю таких создать 4, т.е. создать 4 блока alert, вот с такими условиями (expr):

  1. up == 0 - если наш экспортер станет недоступен

  2. borg_last_backup_error_code > 0 - если команда borg create вернет ошибку (например не сможет подключиться к storage box)

  3. time() - borg_last_run_timestamp > 2 * 24 * 3600 - если последний запуск срипта был более 2х дней назад.

  4. (borg_storage_disk_space - borg_storage_free_space) / borg_storage_disk_space * 100 > 80 - если занято более 80% места storage box

Ну вот вроде бы и все, простой, но достатчно эффективный мониторинг бекапа.

И очередной вопрос знатокам. Возможна ли ситуация, что с бекапом что-то не так, но никакие алерты не сработают? )

Ну конечно. Как минимум стоило бы добавить периодический запуск команды borg check (и мониторинг ее результата), которая может проверять как состояние отдельного архива, так и всей репы.

Ну а уж если идти дальше, то можно написать такую автоматизацию: создание временного сервера, восстановление на него бекапа, проверка функциональности (с мониторингом результата в prometheus), и удалением сервера после проверки.

Если вы никогда не проверяли восстановление из бекапа, считайте что его у вас нет.

Конечно зависит от того, что за данные мы бекапим. А скорее всего, если используются такие решения "на коленке", то это какие-то местячковые бекапы.

По большей части баловство, хоть и интересное)

Всем спасибо за внимание!

Источник: https://habr.com/ru/articles/850422/


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

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

Привет, Хабр! На связи участница профессионального сообщества NTA Марина Коробова.Данные занимают центральное место в информационном обществе. Именно информация является основой для принятия решений, ...
Добавляем функционал быстрых ответов на любом тарифе Битрикс24Как добавить одну из самых полезных функций для чатов открытых линий для любого коммерческого тарифа? Все очень просто, нужно лишь..... ...
Доброго времени суток. При работе с Bitrix-инфраструктурой в определенный момент вы можете столкнуться с проблемой увеличения времени открытия различных страниц на вашей площадке (сайте), медленн...
Революция искусственного интеллекта не грядёт, она уже здесь и требует от компаний переосмысления бизнес-процессов, чтобы максимально использовать возможности искусственного интеллект...
В «1С-Битрикс» считают: современный интернет-магазин должен быть визуально привлекательным, адаптированным для просмотра с мобильных устройств и максимально персонализированным с помощью технологии Бо...