Представляем k8s-image-availability-exporter для обнаружения пропавших образов в Kubernetes

в 6:26, , рубрики: devops, kubernetes, open source, prometheus, Блог компании Флант, системное администрирование, Флант

Представляем k8s-image-availability-exporter для обнаружения пропавших образов в Kubernetes - 1

Рады представить свой новый Open Source-проект. На этот раз мы сделали совсем небольшую, казалось бы, утилиту, но столь полезную буквально для любой инсталляции Kubernetes. В чем же её суть? K8s-image-availability-exporter — это Prometheus exporter, позволяющий проактивно предупредить пользователя об образах, которые прописаны в объектах Kubernetes (например, поле image в Deployment), но отсутствуют в реестре контейнеров (Docker Registry и т.п.).

Введение

Kubernetes — крайне динамическая система. Оперируя инфраструктурой в K8s-кластере, мы предполагаем, что в любой момент времени pod’ы — да что там pod'ы: целые узлы! — могут быть удалены. Чтобы убедиться в этом, мы применяем различные подходы chaos engineering, в основном убивая случайные узлы Kubernetes с тем, чтобы увидеть, готовы ли клиентские приложения к пересозданию pod’ов.

Для корректной работы приложения в таких динамических условиях Kubernetes надо соблюдать минимальные правила: создание PodDisruptionBudgets, деплой сразу нескольких реплик приложения, корректная конфигурация podAffinity, nodeAffinity и т.д.

Однако, несмотря на такие очевидные политики, мы не всегда можем повлиять на их применение. Реальность же такова, что нам пришлось (и не один раз!) встретиться с проблемами, когда у клиента по какой-то причине приложение запущено в единственной реплике. Оно работает так месяцами и почти не деплоится. Его редкие выкаты проводятся без нашего участия и, конечно, без werf (эта утилита смогла бы сделать всё сама). В то же время реестр настроен на автоматическое удаление всех старых образов.И вот однажды, когда по какой-то причине потребуется пересоздать pod, случится непоправимое.

Недавно — после того, как типовая операция перезаказа узла K8s привела к часовому простою, поскольку искали человека, который вообще сможет собрать приложение, — мы и решили написать k8s-image-availability-exporter. Идея утилиты — в автоматизации, позволяющей предотвратить последствия подобных ситуаций вне зависимости от соблюдения организационных политик и других «случайных» факторов.

Реализация

Общий алгоритм реализации сводится к следующему:

  • Запускаем 5 информеров. Таким образом, в памяти держится копия состояния всех следующих объектов кластера: Deployment, StatefulSet, DaemonSet, CronJobs и Secrets.
  • Все образы в PodTemplate’ах группируем и размещаем в очередь (priority queue).
  • Каждые 15 секунд (настраивается через опцию --check-period) достаём из очереди порцию наиболее долго не проверявшихся образов и смотрим их наличие в registry. Количество образов динамически варьируется так, чтобы за 10 минут проверить все возможные образы кластера.
    • Если в PodSpec присутствует imagePullSecrets, достаём нужные нам Secrets.
    • С полученными Secrets (если есть imagePullSecrets) или без них заходим в реестр образов (container registry) и проверяем, есть ли там нужный образ.

В результате проделанной работы экспортируются следующие виды метрик (под ТИП подразумевается deployment, statefulset, daemonset и cronjob):

  • k8s_image_availability_exporter_ТИП_available — ненулевое значение говорит об успешной проверке образа;
  • k8s_image_availability_exporter_ТИП_bad_image_format — ненулевое значение указывает на некорректный формат поля image;
  • k8s_image_availability_exporter_ТИП_absent — ненулевое значение говорит об отсутствии манифеста образа в реестре контейнеров;
  • k8s_image_availability_exporter_ТИП_registry_unavailable — ненулевое значение показывает на общую недоступность реестра (возможно, из-за сетевых проблем);
  • k8s_image_availability_exporter_deployment_registry_v1_api_not_supported — ненулевое значение указывает на первую версию Docker Registry API (такие образы лучше игнорировать с помощью аргумента --ignored-images);
  • k8s_image_availability_exporter_ТИП_authentication_failure — ненулевое значение свидетельствует об ошибке аутентификации в реестре контейнеров (проверьте imagePullSecrets);
  • k8s_image_availability_exporter_ТИП_authentication_failure — ненулевое значение свидетельствует об ошибке авторизации в реестре контейнеров (проверьте imagePullSecrets);
  • k8s_image_availability_exporter_ТИП_unknown_error — ненулевое значение говорит об ошибке, не поддающейся встроенной классификации (получите дополнительную информацию в логах экспортера);
  • k8s_image_availability_exporter_completed_rechecks_total — инкрементируется в каждом цикле проверки наличия образов в реестре.

Последний штрих — предусмотрен настраиваемый список образов, которые нужно игнорировать при этом мониторинге (--ignored-images).

Код написан на Go, распространяется на условиях свободной лицензии Apache 2.0 и доступен на GitHub. Если есть предложения по его улучшению или замечания по использованию утилиты — будем рады!

Мы уже внедрили утилиту на десятках Kubernetes-кластеров и результатами её использования очень довольны. Однако формально текущий статус разработки — альфа-версия, поэтому применяйте её на свой страх и риск.

Как начать пользоваться?

Достаточно трёх шагов:

  1. git pull https://github.com/flant/k8s-image-availability-exporter.git
  2. kubectl apply -f deploy/
  3. Настроить интеграцию с Prometheus: scraping и alerting rules.

Подробнее (включая примеры готовых конфигураций для Prometheus) — см. в README.

Итоги

Теперь — с k8s-image-availability-exporter — мы получаем алерты о том, что у каких-либо из запущенных Kubernetes-контроллеров пропал(и) образ(ы) контейнеров в registry. Это позволяет решить проблему до того, как она себя проявит.

Альтернативный путь решения — не чистить registry вообще или же повсеместно использовать утилиты, в которых эта проблема уже решена системно (как это сделано в werf).

P.S.

Читайте также в нашем блоге:

Автор: Андрей Климентьев

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js