Мониторинг кластера Kubernetes при помощи Prometheus

в 14:03, , рубрики: big data, devops, kubernetes, prometheus, Блог компании Издательский дом «Питер», Большие данные, контейнеры, распределенные системы, системное администрирование

Здравствуйте, коллеги.

Мы только что отдали в перевод интересную книгу Брендана Бёрнса, рассказывающую о паттернах проектирования для распределенных систем

Мониторинг кластера Kubernetes при помощи Prometheus - 1 Кроме того, у нас уже полным ходом идет перевод книги "Mastering Kubernetes" (2-е издание) и готовится к выходу в сентябре авторская книга о Docker, о которой обязательно будет отдельный пост.

Полагаем, что следующая остановка на этом пути — книга о Prometheus, поэтому сегодня предлагаем вашему вниманию перевод небольшой статьи Бьёрна Венцеля о тесном взаимодействии Prometheus и Kubernetes. Не забудьте пожалуйста поучаствовать в опросе.

Мониторинг кластера Kubernetes – очень важное дело. В кластере содержится масса информации, позволяющей ответить на вопросы из разряда: сколько сейчас в наличии памяти, дискового пространства, как активно используется cpu? Какой контейнер сколько ресурсов расходует? Также сюда относятся вопросы о состоянии приложений, работающих в кластере.

Один из состоявшихся инструментов для такой работы называется Prometheus. Его поддерживает фонд Cloud Native Computing Foundation, исходно Prometheus разрабатывался в компании SoundCloud. Концептуально Prometheus очень прост:

Архитектура

Сервер Prometheus может работать, например, в кластере Kubernetes и получать конфигурацию через специальный файл. Такая конфигурация, в частности, содержит информацию о том, где находится терминал, с которого нужно собрать данные по истечении указанного интервала. Затем сервер Prometheus запрашивает с этих терминалов метрики в специальном формате (обычно они доступны по адресу /metrics) и сохраняет их в базе данных временных рядов. Ниже приведен краткий пример: небольшой конфигурационный файл, запрашивающий метрики у модуля node_exporter, развертываемого в качестве агента на каждом узле:

scrape_configs:
  - job_name: "node_exporter"
    scrape_interval: "15s"
    target_groups:
    - targets: ['<ip>:9100']

Сначала определяем имя задания job_name, позже по этому имени можно запрашивать метрики в Prometheus, затем интервал снятия данных scrape_interval и группу серверов, на которых работает node_exporter. Теперь Prometheus будет каждые 15 секунд запрашивать у сервера путь path /metrics к актуальным метрикам. Выглядит примерно так:

# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 1.4852e-05
go_gc_duration_seconds{quantile="0.25"} 2.0702e-05
go_gc_duration_seconds{quantile="0.5"} 2.2059e-05
...

Сначала дается название метрики, затем подписи (информация в фигурных скобках) и, наконец, значение метрики. Самое интересное — функция поиска по этим метрикам. Для этой цели в Prometheus есть очень мощный язык запросов.

Основная идея Prometheus, уже описанная выше, такова: Prometheus с заданным интервалом опрашивает порт по поводу метрик и сохраняет их в базе данных временных рядов. Если Prometheus не может снять метрики сам, то существует и другая функциональность под названием pushgateway. Шлюз pushgateway принимает метрики, присланные внешними заданиями, а Prometheus с заданным интервалом собирает информацию с этого шлюза.

Еще один опциональный компонент архитектуры Prometheus – это alertmanager. Компонент alertmanager позволяет задавать пределы, и в случае их превышения посылать уведомления по электронной почте, slack или opsgenie.

Кроме того, сервер Prometheus содержит множество интегрированных возможностей, например, может запрашивать на Amazon API инстансы ec2 или запрашивать у Kubernetes поды, узлы и сервисы. Также в нем есть множество экспортеров, например, вышеупомянутый node_exporter. Такие экспортеры могут работать, к примеру, на узле, где установлено приложение вроде MySQL и с заданным интервалом опрашивать приложение по поводу метрик и предоставлять их на терминале /metrics, а сервер Prometheus может собирать оттуда эти метрики.

Кроме того, не составляет труда написать собственный экспортер – например, для приложения, предоставляющего такие метрики, как информация jvm. Есть, к примеру, такая библиотека, разработанная Prometheus для экспорта таких метрик. Эта библиотека может использоваться в сочетании со Spring, а также позволяет вам определять собственные метрики. Вот пример со страницы client_java:

@Controller
public class MyController {
  @RequestMapping("/")
  @PrometheusTimeMethod(name = "my_controller_path_duration_seconds", help = "Some helpful info here")
  public Object handleMain() {
    // Делаем что-либо
  }
}

Это метрика, описывающая длительность метода, а другие метрики теперь можно предоставлять через терминал или проталкивать через pushgateway.

Использование в кластере Kubernetes

Как я уже упоминал, для использования Prometheus в кластере Kubernetes есть интегрированные возможности для снятия информации с пода, узла и сервиса. Самое интересное, что Kubernetes специально спроектирован для работы с Prometheus. Например, kubelet и kube-apiserver предоставляют метрики, доступные для чтения в Prometheus, поэтому организовать мониторинг очень просто.

В этом примере для начала я использую официальный helm-чарт.

Для себя я немного изменил конфигурацию helm-чарта, устанавливаемого по умолчанию. Во-первых, мне нужно было активировать rbac в установке Prometheus, в противном случае Prometheus был не в состоянии собирать информацию с kube-apiserver. Поэтому я написал собственный файл values.yaml, в котором описано, как должен отображаться helm-чарт.

Я внес самые простые изменения:

  1. alertmanager.enabled: false, то есть отменил развертывание alertmanager в кластере (я не собирался использовать alertmanager, думаю, предупреждения проще сконфигурировать при помощи Grafana)
  2. kubeStateMetrics.enabled: false думаю, эти метрики возвращают лишь некоторую информацию о предельном количестве подов. При первом запуске системы эта информация мне не важна
  3. server.persistentVolume.enabled: false пока у меня по умолчанию не сконфигурирован персистентный том
  4. Я изменил в Prometheus конфигурацию сбора информации, как это сделано в pull-реквесте на github. Дело в том, что в Kubernetes v1.7 метрики cAdvisor работают на другом порте.

После этого можно запустить Prometheus при помощи helm:

helm install stable/prometheus --name prometheus-monitoring -f prometheus-values.yaml

Так мы установим сервер Prometheus, и на каждом узле – установим под node_exporter. Теперь можно перейти в графический веб-интерфейс Prometheus и посмотреть некоторую информацию:

kubectl port-forward <prometheus-server-pod> 9090

На следующем скриншоте показано, с каких целей Prometheus собирает информацию (Status/targets), и когда в последние несколько раз снималась информация:

Мониторинг кластера Kubernetes при помощи Prometheus - 2

Здесь видно, как Prometheus запрашивает метрики у apiserver, узлов, cadvisor, работающего на узлах и у конечных точек сервисов kubernetes. Можно посмотреть метрики подробно, перейдя в Graph и написав запрос для просмотра интересующей нас информации:

Мониторинг кластера Kubernetes при помощи Prometheus - 3

Здесь, например, мы видим свободное хранилище в точке монтирования “/”. В нижней части схемы заметны подписи, добавляемые Prometheus или уже доступные у node_exporter. Мы используем эти подписи, чтобы запрашивать только точку монтирования “/”.

Настраиваемые метрики с аннотациями

Как уже было показано на первом скриншоте, где выведены цели, с которых Prometheus запрашивает метрики, также существует метрика для пода, работающего в кластере. Одна из приятных фич Prometheus – это возможность снимать информацию с целых подов. Если контейнер в поде предоставляет метрики Prometheus, то мы можем собирать эти метрики при помощи Prometheus автоматически. Единственное, о чем еще нам нужно позаботиться – снабдить установку двумя аннотациями; в моем случае nginx-ingress-controller делает это «из коробки»:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ingress-nginx
  template:
    metadata:
      labels:
        app: ingress-nginx
      annotations:
        prometheus.io/port: '10254'
        prometheus.io/scrape: 'true'
...

Здесь мы видим, что шаблон развертывания снабжается двумя аннотациями Prometheus. Первая описывает порт, через который Prometheus должен запрашивать метрики, а вторая активирует функционал сбора данных. Теперь Prometheus запрашивает у Kubernetes Api-Server поды, аннотированные для сбора информации, и пытается собрать информацию с терминала /metrics.

Работа в федеративном режиме

У нас есть проект, в котором Prometheus используется в федеративном режиме. Идея такова: мы собираем лишь ту информацию, что доступна только изнутри кластера (или эту информацию проще собрать именно изнутри кластера), включаем федеративный режим и получаем эту информацию при помощи второго Prometheus, установленного вне кластера. Таким образом удается собирать информацию сразу с нескольких кластеров Kubernetes, также захватывая и другие компоненты, не доступные изнутри данного кластера или не касающиеся этого кластера. Вдобавок, затем не приходится долговременно хранить в кластере собранные данные и, если с кластером что-то пойдет не так, мы сможем собрать некоторую информацию, например, node_exporter, и извне кластера.

Автор: ph_piter

Источник

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


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