Healthcheck для Apache Airflow в Kubernetes кластере

Aug 26, 2021 11:07 · 350 words · 2 minute read airflow docker kubernetes jq curl

В одной из предыдущих статей мы довольно подробно рассматривали процесс развертывания Apache Airflow в Kubernetes кластере, особенностью которого был запуск веб-сервера и планировщика в одном docker-контейнере. В такой реализации довольно скоро я столкнулся с необходимостью использования кастомного хелсчека для проверки работоспособности сервиса - давайте разберемся!

Прежде всего стоит признать, что текущая реализация отличается от рекомендуемого шаблона проектирования приложений в Docker-контейнерах, который гласит, что следует использовать один процесс на один контейнер. В нашем Docker-контейнере (если не менять инструкцию CMD) запускаются планировщик (scheduler), воркер (worker) и непосредственно веб-сервер (webserver) - как и описано в entrypoint-скрипте.

В манифесте для запуска Apache Airflow в Kubernetes кластере указаны такие настройки для проверки liveness/readiness:

...
  livenessProbe:
    failureThreshold: 5
    httpGet:
      path: /health
      port: 8080
    initialDelaySeconds: 60
    timeoutSeconds: 5
  readinessProbe:
    httpGet:
      path: /health
      port: 8080
    initialDelaySeconds: 60
    periodSeconds: 5
    timeoutSeconds: 5
...

и kubelet честно использует эти настройки чтобы определить когда контейнер должен быть перезапущен (liveness) и когда контейнер готов принимать входящий траффик (readiness). Беда лишь в том, что таким образом проверяется работоспособность веб-сервера, а не всей системы в целом - бывают случаи когда процесс планировщика “зависает” и задачи перестают запускаться.

Примечание. Иногда об этом можно узнать из UI, когда на домашней странице появляется сообщение:

The scheduler does not appear to be running. Last heartbeat was received 1 day ago.
The DAGs list may not update, and new tasks will not be scheduled.

Решить эту задачу можно довольно просто и элегантно. Дело в том, что по пути /health Airflow также отображает статусы зависимых сервисов, в том числе и планировщика. Выглядит это примерно так:

{
	"metadatabase": {
		"status": "healthy"
	},
	"scheduler": {
		"status": "healthy",
		"latest_scheduler_heartbeat": "2021-08-26T10:39:08.143949+00:00"
	}
}

Получать данную информацию будем с помощью утилиты curl, а обрабатывать утилитой jq (ее нужно будет установить при сборке Docker-образа). Создадим простейший bash-скрипт следующего содержания:

Здесь мы получаем json c эндпоинта /health, сравниваем значение ключа .scheduler.status и возвращаем код завершения (exit status). Код завершения будет равен 0, если выражение .scheduler.status == "healthy" истинно.

Нам придется несколько видоизменить наш Dockerfile:

и подправить yaml-манифест для деплоя Airflow в Kubernetes кластере:

Теперь kubelet будет учитывать в своих проверках состояние планировщика и перезапускать его при необходимости.

tweet Share