Kubernetes monitoring от простого к сложному (Николай Храмчихин)

dyxx2omqfakjaexoiytae-23jg4.jpeg

Разберём как при помощи VictoriaMetrics замониторить kubernetes. Откуда собирать метрики и как автоматически обнаруживать новые цели. Черная магия релейблинга и как она работает. Аннотации для мониторинга приложений и что делать когда их гибкости не хватает

e48wueqw8vhctbnlydjrehzhekc.jpeg

Всем привет! Меня зовут Николай Храмчихин. Я работаю разработчиком в компании VictoriaMetrics.

VistoriaMetrics — это быстрая и простая в установке база данных временных рядов с открытым исходным кодом

qyfkof7sxy3sfh71tmesziy2yj0.jpeg

Сегодня я расскажу:


  • О сборе метрик из Kubernetes,


  • О том, как это устроено у нас изнутри,


  • И о том, как это можно использовать вам.


axk8yp4e31t4r1-k0swaonkpsli.jpeg

Есть небольшие requirements для базового знания Kubernetes. Я на слайде привел картинку из официальной документации.

Что такое Kubernetes в двух словах? Kubernetes — это открытое программное обеспечение для автоматизации развертывания, масштабирования и управления контейнеризированными приложениями.

Он состоит из рабочих уpлов — worker nodes, на которых запускаются пользовательские приложения и Kubernetes Control Plane, который отвечает за работу кластера.

ytke3ewe9loqsads8ykqq8g7fgk.jpeg

Что там можно мониторить? В первую очередь это сам Kubernetes Control Plane. Центральным его узлом является API-сервер, который хранит свое состояние в базе данных etcd. И к нему подключаются разнообразные системные компоненты. Это Controller Manager, Kebelet, Scheduler и прочее.

_cswv70ucsaqbwtut-8hk3jlijw.jpeg

Для мониторинга рабочих узлов решения из коробки нет. Kubernetes предоставляет базовую информацию о том, сколько там приложение запрашивает оперативной памяти и CPU, но это не отражает реальную ситуацию. Поэтому самым популярным решением для сбора данных метрик является запуск node-exporter на каждом из worker nodes, который предоставляет эту информацию, собирая ее с самого сервера. Это использование CPU, памяти и прочих разнообразных параметров.

47u-qltr_fsfs1rpki1uwdrlrmc.jpeg

Достаточно важным системным компонентом в Kubernetes Control Plane является Kubelet, который запускается на каждом сервере. Он является связующим звеном между API-сервером и Container Runtime Interface, такими как Docker, Podman. Их сейчас достаточно много появилось. А Container Runtime Interface запускает уже сами контейнеры.

Интересны метрики, которые предоставляет Kubelet находятся на двух API.


  1. Это /metrics, который показывает информацию о взаимодействии с API-сервером, разнообразно примонтированных volumes к этому серверу.


  2. И /metrics/cadvisor, который предоставляет информацию непосредственно по самим контейнерам, т. е. сколько они используют CPU, оперативной памяти в файловой системе, в сетевой системе.


zghd1-tcelg_v8zbwcfxeskzka8.jpeg

И конечно это сами пользовательские приложения, которые запускаются в кластере Kubernetes. Их тоже можно и нужно мониторить.

epyjgjp5x9osgovjnkqfgbxtod0.jpeg

Я буду рассматривать сбор метрик с приложений, экспортирующих сами метрики в prometheus text формате.

В этом случае приложение запускает у себя web-сервер, один из endpoint«ов, который отдает эти метрики. А коллектор приходит к этому приложению и http-запросом их забирает.

В control-plane Kubernetes все компоненты отдают метрики в prometheus text формате.

aqeza6fsvd206yzjbyvfnk9coam.jpeg

И с помощью VictoriaMetrics Single версии, которая при помощи конфигурационного файла, задаваемым флагом --promscrape.config, будет это собирать.

Но приведенная информация справедлива не только для VictoriaMetrics, но и для vmagent и Prometheus, с которым VictoriaMetrics совместима, можно использовать один и тот же конфигурационный файл.

zdug3ntyker_sesqlanafqni4ew.jpeg

Небольшой пример. Важная секция — это scrape_configs, в котором описывается каждая из параметров jobs, которые будут забирать эти метрики.

Можно использовать как статичные configs, которые никогда не поменяются, просто задать IP-адрес хоста или его DNS-имя.

Также можно использовать Service Discovery Configs, которые будут динамически получать метрики из Kubernetes и как-то взаимодействовать с этими всеми объектами.

nzhf_9qheywfxtpepraavzh1oto.jpeg

Нужен ли Service Discovery или нет? По идее самым простым способом сбора метрик из Kubernetes — это просто перечислить все нужные targets через static_configs. Это, в принципе, даже будет работать. Вы не каждый день добавляете новый API-сервер или удаляете старый. И в целом адреса для Controller Managers достаточно статичны. А у серверов можно руками поправить, если что.

-wykp4znl1kxfqkmsrpwgke7n08.jpeg

Но для пользовательских приложений это не работает. Если мы пытаемся описать каждое наше приложение через вычисления его IP-адреса и порта, откуда нужно забирать метрики, то у нас это не очень сильно получится, потому что приложения обновляются. Они могут меняться, и нам нужно будет каждый раз обновлять конфигурационный файл. Это не очень удобно. А на больших объемах это даже может быть невозможно.

j_tl6zpm2zykyikalj5tzmqkbyu.jpeg

Поэтому нам пригодится Service Discovery, который решает эту задачу, автоматически обнаруживая изменения в Kubernetes. Он запускает и останавливает сбор метрик с targets.

jyexhn0fvw7dghrzviegzhs38xo.jpeg

Как это происходит. VictoriaMetrics использует Kubernetes watch API, подписываясь на изменение объектов в API Kubernetes и как-то на это реагирует.

coarjsaq0tckdkemvvabhyupmfq.jpeg

Например, если мы подписываемся на изменение подов.

Под — это, наверное, самая маленькая единица API в Kubernetes, которая объединяет несколько контейнеров.

На примере у нас под с именем app-1. Он в каком-то namespace, там есть какие-то labels. И него есть один 80 порт.

После того, как VictoriaMetrics получает ответ от Kubernetes API, она преобразует полученную сущность, в данном случае под, в специальный список labels вида _meta_kubernetes с какими-то параметрами. Например, _meta_kubernetes_pod_name: app-1. Это имя пода. А label из metadata env будет в _meta_kubernetes_pod_label_env: dev с каким-то значением.

И также присутствует специальный label address, куда записывается ip пода и, соответственно, контейнер порт, с которого собирать метрики.

hzqv9h-0rxp83ukpqegh70labum.jpeg

Каждый обнаруженный элемент из списка labels проходит через фазу relabeling, где к нему применяются специальные правила. Например, базовое использование relabeling config.

ikmfmx2urtrxq_kyfmnto2ifnrs.jpeg

Что такое Relabeling, что это за магия? В интернете часто можно встретить гигантские relabeling_configs и как они работают не всегда понятно.

Relabel_cjonfigs — это набор правил, позволяющий выполнять различные операции над labels и их значениями. Каждое из правил выполняется последовательно и зависит от результатов предыдущего.

1nqgcqod6yfvoyunlflc2vujg74.jpeg

Что там доступно? Доступная секция — это source_labels, т. е. те labels, над какими нужно проводить операции. Может быть не одна, а несколько labels.

Есть action, который надо выполнить.

Modulus — это специальный модуль для action hashmod. Но он редко используется. Используется в основном для масштабирования и кластеризации собираемых целей.

Regex — это регулярное выражение, по которым должен происходить matching. Возможно использование группы захвата. Например, как здесь. И можно использовать в replacement в специальном поле, где можно поменять значение label.

Separator — это разделитель, потому что для большинства actions, при использовании несколько source_labels они конкатенируются в одну строку с заданным separator«ом. Разделитель по умолчанию — это точка с запятой.

Target_label — это название того label, куда нужно записать результат action.

ufum1az1wrn0pwrar-uwbjblhkq.jpeg

Какие нам доступны actions? Они делятся на две группы.


  1. Это actions, которые есть в VM и Prometheus:


  • Replace,


  • Keep,


  • Drop,


  • Labelmap,


  • Labelkeep,


  • Labeldrop,


  • Hashmod.



  1. И actions, которые есть исключительно в VM. Они немного расширяют функционал и делают его более удобным. Например, keep_if_equal. Я покажу дальше, как можно его использовать на примере match по порту.

e6dnqt-hcieo_xvubzeavyclakg.jpeg

Relabeling-правила можно использовать для:


  • Фильтрации обнаружения targets,


  • Изменения названия labels,


  • Изменения значения labels,


  • Добавления новых labels,


  • Удаления ненужных labels.


ipg3jsnu0zmunfnxxn-1abfxdli.jpeg

Пара простых примеров, как можно использовать relabel_configs.

Мы можем оставить из всех обнаруженных под в кластере Kubernetes только те, которые находятся в namespace default. Для этого мы используем sourcelabels: [ _meta_kubernetes_pod_namespace]. В action мы используем keep — это значит, что нужно отфильтровать только те, которые попадают под нужные нам условия. И в регулярном выражении namespace default.

_5i8hw1njvajkexa8pkk0czffru.jpeg

Также можно обогатить все метрики, которые мы собираем с самого приложения, полезной информацией. Например, из label пода можно достать окружение, в котором он запущен и, например, namespace, в котором он запускается. Для этого нужно использовать source_labels и target_label, куда нужно это написать.

htg5ofeo9qcx7wthpmlkouelcys.jpeg

Более подробно ознакомиться с тем, как работает relabeling и на хороших примерах, можно по ссылочке: https://medium.com/@valyaya/cs-8b90fc22c4b2.

ogwsvyxelht_dn2fdh35iwhaaue.jpeg

Вернемся к Service Discovery. После фазы relabeling, все labels с прификсом __ meta отбрасываются.

Это нужно для того, чтобы снизить нагрузку на базу данных и уменьшить объем информации, которую нужно хранить. Kubernetes экспортирует достаточно большой объем metadata. И если записывать все, то будет 40–60 labels на 1 deploy, что достаточно много. И в 90% случаев вы их никогда не будете использовать.

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

sijijydhttzngrafb7u8ovkmw60.jpeg

Какие можно выбирать объекты из API Kubernetes? Они определяются специальной настройкой role.

Это может быть:


  • Pod,


  • Service,


  • Endpoints,


  • Endpointslice,


  • Node,


  • Ingress.


В зависимости от role, VM подписывается на изменение разных объектов и возвращает разные labels.

8xgquhp-c8o6hg7b-edtkflx5v4.jpeg

Давайте рассмотрим, какие role что возвращают.

Первая из них — это pod, которую мы видим на примере. Она возвращает список с элементами labels для каждого container port с ip-адресом этого пода.

На примере есть некий под, у которого 3 порта, один из которых находится в initContainer. И в статусе находится его ip-адрес.

Соответственно, VM на relabeling 3 элемента в списке с ip-адресом этого контейнера и с каждым из портов. Там дополнительная мета-информация из metadata и еще некоторая другая будет.

7uboc7l50l02n99ofh2hagbn6b8.jpeg

Role: service тоже достаточно простой. Он подписывается на изменения сервиса. И для каждого из портов этого сервиса создает label c мета-датой сервиса и адресом. Это доменное имя данного сервиса в формате: имя сервиса.namespace.svc и номер порта в порт секции.

eibtwb-mwfkxmbpbmwzk7vu02pm.jpeg

Далее идет достаточно интересный role: endpoint. Здесь нужно небольшое дать объяснение, что такое endpoint, потому что обычно руками их никто не создает.

Это специальная сущность в API Kubernetes, которая нужна для связи сервисов и подов. Она отображает состояние подов, насколько они работоспособны, а также позволяет направлять трафик только на работоспособные поды.

lhrwhre2sulsc0sw4c9z64phj_m.jpeg

Для Service Discovery это одна из интересных самых ролей, потому что здесь не одна сущность, как было в предыдущих ролях, а целых три, которые нужно отслеживать и обогащать.

Это service. Здесь есть его definition, endpoints и сам непосредственно под.

В приведенном примере на сервисе только один порт заэксплужен, это 8429. Соответственно, в endpoint«е он тоже один, а в контейнере два порта.

6jfnvk0_yp1hpaghq2hayw_ynxi.jpeg

И это преобразуется в список labels с двумя элементами. Здесь используется не только тот порт, который есть в endpoints, service, но и порт контейнера дополнительный 2003, который нигде не был указан, но у него не будет мета-информации по endpoint.

dcuiqoufvi4abuhcekp07d9lbno.jpeg

Endpointslice — это оптимизированная версия endpoints с точки зрения Kubernetes API. Технически она никак не отличается от endpoints, только там меняются названия префиксов для labels с meta_kubernetes_endpoint на meta_kubernetes_endpointslice.

Какие могут быть подводные камни не использования endpoint? Если у вас очень много endpoints, по-моему, больше 1 000, то Kubernetes их обрезает. Соответственно, вы не получите часть endpoints. Насколько я знаю, в следующей версии VM будет логировать данное сообщение с WARN ошибкой, если такое случается.

3vy9rlyegs6czi2zryrplfpwv5y.jpeg

Следующая роль — это node. Соответственно, worker node в Kubernetes, для которой используется в качестве адреса первый ip-адрес worker node. В нашем случае — это InternalIP. И порт Kubelet, который указан в описании этой ноды. И дополнительная metadata-информация тоже добавляется. Это annotations: some-annotation: value labels. Ее можно использовать.

iptyqk6fehemunl3kwgxq_uyjco.jpeg

Наверное, самая мало встречаемая роль — это ingresses. Она в основном нужна для мониторинга. Я много видел примеров с Blackbox Exporter, который мониторил состояние ingresses через Service Discovery.

И она возвращает комбинацию из хостов в rules с каждым из их путей. Соответственно, в адресе остается только host name, а сам path записывается в специальную _ _meta_kubernetes_ingress_path, как видно на примере.

ljopwq0wlobwt1feqtp3hw6eabw.jpeg

Полное описание для каждой роли и о том, какие labels она возвращает, можно найти на сайте Prometheus.io. Там достаточно хорошая документация на этот счет и много примеров того, что возвращается.

pwsh-1_tcl2cgnnq0qxmjzwhkl0.jpeg

Service Discovery возвращает все поды, но нам не обязательно собирать с них метрики, а, может, они их и не отдают.

Самым популярным решением для фильтрации данных подов является добавление специальной аннотации Prometheus.io/scrape: «true» в metadata.annotations объекта. В данном случае это в template пода в deployment указывается, что нужно собирать метрики.

r9lknlfnhz4wsr7-qcgg-mnaao4.jpeg

Магическим образом это не работает. Kubernetes не знает про это ничего, поэтому нужно использовать специальный конфигурационный файл для scraping, в котором можно фильтровать по мета-информации из annotation. Мы используем _ _meta_kubernetes_pod_annotation_prometheus_io_scrape с regex: true.

-j2mtesy8c8rjxjjlm__xxdaati.jpeg

Дополняют эту аннотацию две другие аннотации. Это prometheus.io/port с номером порта, который нужно использовать для scraping. И prometheus.io/path, откуда эти метрики нужно забирать.

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

Соответственно, в приведенном relabeling_config используются матчи, только если они не пустые.

5mt1vidclu45lmzkksglnyun1nu.jpeg

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

Если мы будем использовать эту аннотацию, то будут собираться метрики с трех портов, хотя initContainer уже не работает. И будет возвращаться ошибка.

hr37aptvmj1_l4w3quyd4_u75za.jpeg

К сожалению, prometheus.io/port тоже не сильно здесь поможет, потому что он будет фильтровать только по одному порту, а с другого мы уже данные получать не можем. В Prometheus есть интересный issues по этому поводу. К сожалению, здесь у меня ссылочки нет.

zbdrzh3o-1p2r0xkrpfxt130t3w.jpeg

Как это можно решить? Можно использовать кастомные аннотации, т. е. создать prometheus.io/scrape: «true», который будет собирать все метрики только с контейнеров, у которых один порт экспортирует метрики и отдельную config-секцию, которая будет по другой аннотации собирать либо с нескольких портов по их номерам, либо со всех, которые доступны. Это может быть не совсем удобно.

ajl2xjah7qf0veuyxvwyw_zzzga.jpeg

А можно создать под каждое приложение в конфигурационном файле отдельную секцию с именем этого приложения, с фильтрацией по какому-то из его labels для имени. И, соответственно, с указанием того порта, откуда нужно собирать метрики.

В примере используется endpoints, соответственно, с endpoints, на который экспортирует сервис.

ychd3rkaffqx8qr0qqqg1bgcos8.jpeg

Как можно решить еще? VictoriaMetrics operator — это последний подход. Он автоматизирует процесс генерации таких конфигурационных файлов для ваших приложений и дописывает нужные relabeling-правила, обогащая мета-информацией метрики с собираемого приложения. Ссылочка на него здесь есть.

bfpiw5ckghehkmkubp5g4encd_y.jpeg

Как он работает? Он использует Custom Resource Definitions. Это специальные объекты, расширяющие API Kubernetes через Custom Resource. И уже нужно описывать мониторинг в самом приложении через этот Custom Resource, и у вас все будет работать.

ktwof2sbyisgvvu3r7elleo76gg.jpeg

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

u1wtnhkt93goaemivttks2iywum.jpeg

И посмотрим, как это можно сделать.

Слева пример deployment, который описывает состояние самого приложения с именованием портов.

Справа пример VMPodScrape, который позволяет также в YAML-формате описать то, откуда мы будем забирать метрики. Соответственно, здесь у нас есть два порта: http и backup-metrics.

wohdstt0k__gfwega3zkd3_djxm.jpeg

В результате у нас будет сгенерировано две секции scrape в конфигурационном файле, который будет выполнять matching по source_labels с названием того, который есть в deployments, и с именем порта, который указан в самом приложении.

9ojb9f6vwovoqhnradvzpjjdn9k.jpeg

Это только один из примеров использования VMPodScrape. Он также позволяет гибко настроить мониторинг приложения и делегировать эту конфигурацию владельцу приложения.

Таким образом можно построить Git-ops-подход для мониторинга.

Единственное, этот конфигурационный файл генерируется только для VMagent, который управляется оператором. Это нужно знать, это одно из ограничений.

3yd3zefjzvght3ruudciknxk1za.jpeg

Сегодня мы узнали:


  • Основные цели, с которых можно собирать метрики в Kubernetes.


  • Что такое Service Discovery.


  • Какие проблемы решает relabeling_congig.


  • Как они работают, что для них доступно и как их использовать.


  • Про аннотацию prometheus.io/scrape — ее плюсы и минусы.


  • И кратко рассказал про VM operator, о том, как можно декларативно описывать мониторинг приложения.


cegukytmmzludecjxj2nw7uk7lw.jpeg

Всем, спасибо! Ваши вопросы.

Спасибо большое! Как грамотно интегрировать мониторинг Kubernetes, например, с Service Management, либо с Service Desk для того, чтобы заводить тикеты на те или иные события, в том числе нас интересует мониторинг самого Kubernetes и также master nodes? Вы очень подробно нам рассказали о подах, а как мониторить master nodes и сам Kubernetes как инфраструктуру, чтобы заводить тикеты?

Как я вижу, здесь есть две части. Первая — это та, которая непосредственно собирает метрики. Вторая часть — это та, которая с ними взаимодействует. Под мониторингом этих метрик я подразумеваю какие-то правила, которые выполняются, т. е. насколько этот API-сервер жив или нет.

В экосистеме VM есть vmalert, который выполняет эти правила. И результат он отправляет в Alertmanager. У Alertmanager уже есть достаточно много интеграций, куда дальше передавать эти события, где их можно визуализировать и как ими можно управлять.

Лично я пробовал комбинацию из Alertmanager и alerta, где можно уже assign (назначать) все эти события, нездоровости API-сервера и как-то с ними уже взаимодействовать.

Мы можем интегрировать, например, метрики и события в Zabbix? Либо, к примеру, в Аксиусе напрямую? Kubernetes очень мониторится Prometheus«ом. Можно ли какую-нибудь использовать связку, чтобы эти события продублировать в Zabbix для того, чтобы удобнее было заводить заявки, например, в Аксиусе?

Я понял вопрос. Насколько я знаю, есть проект Glaber. Это практически Zabbix, только лучше. И он дает возможность получать различные бэкенды для хранения и можно интегрировать в VM через Glager для мониторинга.

Понял, большое спасибо!

Привет! Спасибо за доклад! У меня, может быть, вопрос не совсем по теме доклада, но все-таки задам. Какие планы у VM по downsampling?

Я ждал этого вопроса. Спасибо большое! Нам его очень часто задают. Мы над ним работаем. Я надеюсь, сделаем его в каком-то виде к концу года. Пока более точных сроков у меня нет.

Когда появится web-интерфейсы у ваших продуктов?

Он уже есть. Вы можете ознакомиться с документацией. Там есть Web UI. Он достаточно красивым в последнем релизе стал. Там можно скролить, листать, визуализировать метрики. И даже у VMalert появился отдельный UI. Мы над этим работаем, они развиваются.

Здравствуйте! Спасибо за доклад! Как у вас дела обстоят с OpenShift? Есть у вас с ним интеграция?

Лично я тестировал интеграцию с OpenShift при помощи оператора deployment. И он из коробки понимает все то, что генерирует OpenShift и можно это все мониторить, использовать. Насчет визуализации через графический интерфейс OpenShift — я не в курсе. Я не смотрел, но было бы достаточно интересно.

Расскажи, как Виктория падает? Какие есть самые яркие, запоминающиеся кейсы?

В основном пример, когда падает и плохо работает, это кластерная версия. Когда выходит из строя одна из storage node и кластер сильно утилизирован, то он какое-то время может не справляться с нагрузкой, потому что нужно зарегистрировать временные ряды на других storage nodes. Такое бывает, мы с этим работаем. Надеюсь, что все в будущем будет хорошо.

P.S. Чат по VictoriaMetrics https://t.me/VictoriaMetrics_ru1

© Habrahabr.ru