Здравствуйте, коллеги.
Мы только что отдали в перевод интересную книгу Брендана Бёрнса, рассказывающую о паттернах проектирования для распределенных систем
Кроме того, у нас уже полным ходом идет перевод книги "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-чарт.
Я внес самые простые изменения:
alertmanager.enabled: false
, то есть отменил развертывание alertmanager в кластере (я не собирался использовать alertmanager, думаю, предупреждения проще сконфигурировать при помощи Grafana)kubeStateMetrics.enabled: false
думаю, эти метрики возвращают лишь некоторую информацию о предельном количестве подов. При первом запуске системы эта информация мне не важнаserver.persistentVolume.enabled: false
пока у меня по умолчанию не сконфигурирован персистентный том- Я изменил в 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), и когда в последние несколько раз снималась информация:
Здесь видно, как Prometheus запрашивает метрики у apiserver, узлов, cadvisor, работающего на узлах и у конечных точек сервисов kubernetes. Можно посмотреть метрики подробно, перейдя в Graph и написав запрос для просмотра интересующей нас информации:
Здесь, например, мы видим свободное хранилище в точке монтирования “/”. В нижней части схемы заметны подписи, добавляемые 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