Проверка состояния сервисов в Consul

Consul logoВ прошлом посте мы создали небольшой Consul кластер с четырьмя сервисами в нём: двумя web сервисами и двумя db. Но так как мы не сказали Консулу, как мониторить их состояние, Консул-агенты абсолютно упустили из виду тот факт, что ни одного сервиса на самом деле не существует. Сегодня мы посмотрим, как это можно было бы исправить: как добавить проверки состояния сервисов, и как эти проверки влияют на способность сервисы обнаружить.

Что такое проверка состояния сервисов

Consul может повесить несколько проверок состояния как на отдельные сервисы, так и на хост целиком. Проверкой может быть что-нибудь простое, вроде HTTP запроса к сервису, либо что-нибудь посложнее, вроде запуска сторонней программы или скрипта и проверка её кода выхода. В зависимости от результата такой проверки сервис попадёт в одну из трёх категорий: healthy, warning или critical. В советской терминологии это «нормально», «всё плохо», «всё очень плохо».

Первые два статуса  практически не отличаются, но как только сервис попадает в critical, Consul перестаёт считать его за живого и тут же исключает из DNS списков. Как результат, другие сервисы найти его больше не могут, что даёт бедолаге время оклематься. Кроме того, Консул может полностью удалить сервис, если тот находится в критическом состоянии слишком долго, но это нужно включать отдельно.

Типы проверок состояния сервиса

Всего есть пять типов проверок: HTTP, TCP, Script, TLS и Docker.

HTTP

HTTP проверка — это обычный HTTP запрос к какому-нибудь URL. Если запрос возвращает ответ с 2xx статус кодом, то, естественно, сервис считается живым и здоровым. 429 («Too many requests»), в свою очередь, поставит сервису warning состояние. Всё остальное — critical. Что здорово, тело HTTP ответа пойдёт прямиком в заметки к результатам проверки, так что туда можно положить какие-нибудь дополнительные детали. Посмотреть их можно будет в Consul UI.

Настройка HTTP проверки тривиальная:

TCP

TCP проверка даже ещё проще, чем HTTP. Делается TCP запрос, и если сервис на него ответил, то всё хорошо. Если нет — всё плохо. Третьего не дано.

TTL

TTL (Time to live) использует совсем другой подход. Это проверка ожидает, что сервис сам будет слать HTTP запросы Консулу не реже чем раз в Х секунд (TTL). Если сервис не уложился во временные рамки, то он считается умершим (critical).

Сам сервис должен слать запросы Консулу на один из 3-х адресов:

Любой из них сбрасывает таймер на ноль, и, смотря на какой URL пришёл запрос, переводит сервис в одно из трёх состояний. JSON конфигурации всё ещё прост:

Script

Как следует из названия, script запускает стороннюю программу или скрипт. То, с каким кодом выхода завершилась программа, определяет, в какое состояние перейдёт сервис. 0 — значит здоровый, 1 — значит warning, а всё остальное — дела очень, очень плохи. Весь STDOUT при этом сохраняется в качестве комментария к проверке.

Это, возможно, не сразу очевидно, но состояние сервиса — это не только его способность отвечать на HTTP и TCP запросы. Мы может проверять что-то более любопытное, вроде насколько сильно он грузит процессор, как много диска оттяпал, или памяти. Script для этого подходит идеально.

Docker

Docker проверка работает точно так же, как и script. Просто в этот раз сторонняя программа запускается внутри контейнера и через docker exec.

Добавляем проверки в наш кластер

Итак, самые большие проблемы в созданном прошлый раз кластере были отсутствие смысла и сервисных проверок. Со смыслом уже ничего не поделаешь, но с проверками всё решаемо. Как насчёт того, чтобы создать одну проверку состояния для web сервиса, и одну для хоста целиком?

HTTP проверка для web сервиса

В прошлый раз мы остановились на такой конфигурации сервисов:

Проверку в неё можно добавить двумя способами: либо прямиком внутрь сервиса, либо отдельной секцией, но тогда придётся указывать, для кого она предназначена, через service_id: "id". Первый способ короче, так что остановимся на нём.

Итак, чтобы убедиться, что web сервис ещё жив, мы будем слать ему запрос раз в 15 секунд:

Сохраняем изменения в services.json и скармливаем файл Consul агентам на host-1 и host-2:

Да, Со времени прошлого поста мой кластер успел отправиться в лучший из миров, реинкарнироваться и получить новые айпишки: 192.168.99.100 для consul-server и 192.168.99.102 и .101 для host-1 и host-2. Но конфигурация ни капельки не изменилась.

Как только сервисы перезапустились, идём к Консул-серверу в UI:

web сервис в критическом состоянии

И прямо с порога видно, что оба web сервиса лежат. Это, в принципе, предсказуемо, ведь их всё ещё не существует. Прежде чем мы это исправим, стоит посмотреть, как теперь выглядят DNS запросы к Консулу.

DNS запросы к упавшим сервисам

Так как db всё ещё считается живым, убедимся, что он находится через DNS:

Да, всё на месте, и хосты по прежнему рапортуют о двух db сервисах на них. Теперь попробуем найти павший web сервис:

Никого.

Это легко поправимо. Им нужен web? Их есть у меня:

Два nginx контейнера на 80х портах на обоих хостах должны утихомирить Consul. Смотрим UI:

С web всё в порядке

Теперь всё хорошо. В описании проверки даже HTTP ответ засветился:

Комментарии к проверке

DNS запросы теперь тоже работают. Проверял.

Проверка состояния хоста целиком

Проверить можно и хост целиком. Попробуем увести хост в критический статус, если, например, на нём заканчивается память. Для этого я сделал простенький shell скрипт, который выводит в STDOUT текущие показатели памяти и завершается с кодом 0, если всё нормально, 1 (warning), если съедено больше 80% памяти, и 2 (капут), если больше 98%.

Конфигурация Consul агента снова немного изменилась:

Сохраняем, рестартуем и снова смотрим на UI:

Проверка состояния хоста

На обоих хостах использовано по 6% памяти. До 98 далековато… Придётся изменить скрипт и выходить в critical статус, например, после 5%. Иначе как быстро убедиться, что проверка работает? Перезапускаем сервисы и… host-1 в панике:

Заваленная проверка по памяти

Что здорово, все сервисы, которые на нём были, теперь тоже в панике:

Все сервисы хоста в критическом состоянии

Эдакая массовая истерия. В них теперь даже DNS не верит:

Мораль

Сегодня мы рассмотрели несколько способов убедиться, что наши сервисы ещё живые, и другие с сервисы могут с ними работать, предварительно найдя компаньонов, например, через DNS. У Consul для этого есть и простые проверки, вроде HTTP запросов, и кое-что помощнее, вроде сторонних программ и скриптов. Проверки могут работать как на уровне отдельных сервисов, так и на хосте целиком.

Тут, правда, важно помнить, что эти проверки — не замена полноценному мониторингу хостов и приложений. Мониторинг детально отвечает на вопросы, что происходит сейчас, и как было раньше. Консулу же достаточно знать, кто из сервисов ещё жив. Больше ничего.

Проверка состояния сервисов в Consul: 2 комментария

  1. Вопрос: Паш, а для чего тогда подобное использование Consul-a, если ты говоришь, что полноценному мониторингу он не замена?

    1. Такие проверки нужны для service discovery. Если у нас есть load balancer, который спрашивает у консула, кому можно отдать новых запросов, а тот начнёт возвращать адреса умирающих сервисов, то мы и сервисы добьём, и тех клиентов, которые хотели к ним обратиться, подставим. А так сервисы из пула можно пачками уводить в оффлайн, например, для обновления, и консул сам заметит это, временно удалит их из списков, и там самым перенаправит нагрузку тем, кто ещё остался.
      Для меня консуловский мониторинг немного бинарен — просто проверяет можно ли с сервисом работать дальше. «Большой» мониторинг тоже может ответить на этот вопрос, но ещё он может замерить кучу других параметров и потом показать их динамику по времени. Я у себя не один баг нашёл только из-за того, что график на стене выглядел как-то непривычно.

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

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