Servlerless free cloud watchdog (telegram alerts).
Задача
При разработке пет-проекта Chipa bots одной из целей было достичь максимальной автоматизации: сделать рабочий SaaS самостоятельно (без инвестиций, помимо времени на выходных) и запустить его в формате “сделать и забыть”. Это требует автоматизации рутины везде где возможно. Дополнительно о проекте здесь.
Чтобы “сделать и забыть”, надо быть уверенным, что все работает, и что мы будем уведомлены, когда перестанет.
ТЗ:
- Watchdog должен быть размещен вне наблюдаемого сервера, на случай недоступности самого сервера.
- Watchdog должен отправлять уведомление в случае неуспешного health check системы.
Экономика пет-проекта
В нормальном проекте следовало бы положиться на решения мониторинга, например, prometheus alert manager. Однако пет-проект chipa запущен на сервере за 420 руб/мес (как говорил один мой знакомый, с деньгами любой может, а вы попробуйте сделать без денег!)
с мощностями в 2 vcpu и 2 gb ram, чего хватает только на запуск основных компонентов системы:
Очевидно что покупка второго сервера для watchdog сделала бы проект на данной стадии финансово нежизнеспособным. К счастью, облака AWS и Яндекс предоставляют free tier для serverless функций, и эти фукнции отлично подходят чтобы сделать watchdog!
Итак, watchdog будет реализован как function Яндекс облака. В рамках free tier доступно 1 000 000 вызовов yandex free tier », а для проверки сервиса раз в минуту достаточно 44640 вызовов в месяц.
Решение
Health check
В сервис добавлен smallrye-health, открывающий метод https://chipa.archertech.ru/api/q/health, который возвращает http status 200 и статус сервиса:
{
"status": "UP",
"checks": [
{
"name": "SmallRye Reactive Messaging - liveness check",
"status": "UP",
"data": {
"bot_csv_updated": "[OK]"
}
},
{
"name": "Reactive PostgreSQL connections health check",
"status": "UP",
"data": {
"<default>": "UP"
}
},
{
"name": "SmallRye Reactive Messaging - readiness check",
"status": "UP",
"data": {
"bot_csv_updated": "[OK]"
}
},
{
"name": "Database connections health check",
"status": "UP",
"data": {
"<default>": "UP"
}
},
{
"name": "SmallRye Reactive Messaging - startup check",
"status": "UP",
"data": {
"bot_csv_updated": "[OK]"
}
}
]
}
Что можно сказать о состоянии системы по этой информации:
- Сервер up
- Nginx up (т.к. nginx проксирует запросы https://chipa.archertech.ru/api на backend quarkus где запущен health check api)
- SSL сертификат ok
- Backend up
- Postgresql up
- Rabbitmq up
Для полной уверенности не хватает информации о keycloak, фронтенде и nlp системе, но это задел на будущее.
В случае недоступности подсистемы, healthcheck вернет http статус 503 (статус будет использован далее при проверках) и json:
{
"status": "DOWN",
"checks": [
{
"name": "SmallRye Reactive Messaging - liveness check",
"status": "UP",
"data": {
"bot_csv_updated": "[OK]"
}
},
{
"name": "Reactive PostgreSQL connections health check",
"status": "DOWN",
"data": {
"<default>": "UP"
}
},
...
Watchdog cloud function
Telegram bot
В телеграм необходимо настроить бота и группу, в которую бот будет писать уведомления. Инструкция ».
Токен и ChatID понадобятся далее в параметрах функции.
Function
Функция будет реализована на bash:
- curl вызывает api health check
- проверка http_code ответа
- curl отправки уведомления в телеграм, в случае ошибки
Curl запроса health check:
curl --connect-timeout 3 -s \
-w \nexitcode=%{exitcode}\nerrormsg=%{errormsg}\nhttp_code=%{http_code}' \
https://chipa.archertech.ru/api/q/health
При помощи ключа -w выводим несколько важных для анализа проблем параметров. Пример вывода curl при здоровой системе:
{healthcheck json}
exitcode=0
errormsg=
http_code=200
Пример ошибки (таймаута сервера):
exitcode=28
errormsg=Resolving timed out after 1000 milliseconds
http_code=000
Но! К сожалению, данный вариант требует версии curl 7.75.0, а в yandex cloud установлен 7.58.0 (версия в Ubuntu 18.04 LTS), потому в финальном скрипте я оставил только http_code.
Для проверки что все системы запущены, достаточно проверки http_code:
- 200 - сервис UP
- другие коды http - что-то сломалось (например 503 - сервис DOWN)
- код 000 означает что http ответ не получен, например, по таймауту вызова health check API, когда сервер недоступен
Полный скрипт watchdog:
#!/bin/bash
#https://core.telegram.org/bots/api#sendmessage
function sendTgAlert {
curl -s -X POST -H "Content-Type: application/json" \
-d "{\"chat_id\": \"$CHAT_ID\", \"text\": \"CHIP!!!\n\n$1\"}" \
https://api.telegram.org/bot$TOKEN/sendMessage
}
# need version 7.75.0
#healthcheck=$(curl --connect-timeout 3 -s -w '\n%{json}\nexitcode=%{exitcode}\nerrormsg=%{errormsg}\nhttp_code=%{http_code}' $URL)
# version 7.58.0
healthcheck=$(curl --connect-timeout 3 -s -w '\nhttp_code=%{http_code}' $URL)
# extract http_code from last line
http_code=$(echo "$healthcheck" | tail -n1 | cut -d= --fields=2)
if [ $http_code == 200 ]; then
echo "healthy"
elif [ $http_code == 000 ]; then
sendTgAlert "http_code=$http_code => health check API unavailable\n\nsee $URL"
else
sendTgAlert "http_code=$http_code\n\nsee $URL"
fi
Создаем яндекс функцию в консоли облака (см. инструкции Яндекс »), и сохраняем bash script:
Указываем параметры функции:
Timer
Функцию раз в минуту будет запускать timer.
Таймер можно создать в консоли здесь:
Для таймера требуется создать сервисный аккаунт:
Финальные настройки таймера:
Проверки
- Недоступность сервера
Изменим URL на несуществующий:
Алерт:
- Backend не отвечает
Остановим контейнер:
Алерт:
- Одна из систем лежит
Например, остановим rabbitmq:
Healtcheck при этом отвечает статусом 503 с телом ответа:
{
"status": "DOWN",
"checks": [
{
"name": "SmallRye Reactive Messaging - liveness check",
"status": "UP",
"data": {
"bot_csv_updated": "[OK]"
}
},
{
"name": "SmallRye Reactive Messaging - readiness check",
"status": "DOWN",
"data": {
"bot_csv_updated": "[KO]"
}
},
...
Алерт:
Теперь можно быть уверенным что все работает, если телеграм молчит. The end.