
Здравствуйте. Меня зовут Николай. И у меня паранойя в лёгкой форме, которая не мешает, а наоборот, помогает мне быть хорошим devops-инженером в компании INOSTUDIO. В мои обязанности входит настройка инфраструктур для разработчиков и продукции для клиентов, настройка CI/CD и поддержка, мониторинг оного, бэкапы. В этой статье я хотел бы поделиться частью личного опыта взаимодействия с Kubernetes и рассказать о том, как я к нему пришел.
Как я пришел к Kubernetes
Начинал с виртуализации на различных платформах, потом познал docker, затем облачные сервисы. Во всём этом можно было применить zabbix-agent, с написанным bash, python-скриптом, или собрать отдельный модуль zabbix-agent для настройки discovery-обнаружения контейнеров на хосте и передачи информации о контейнере в zabbix-server. Но при плотном изучении Kubernetes у меня сработала защитная реакция — как все это мониторить? Долго искать ответ на вопрос не пришлось, благо люди уже задавались таким вопросом ранее. Стек, в составе которого Prometheus + Alertmanager + Grafana. Из-за недостаточного опыта возникла проблема с простой и понятной инструкцией как запускать эту связку в кластере.
Какие задачи мониторинга решаем в Kubernetes
Мониторинг Kubernetes решает вопрос оповещения выхода из строя нод, под и прочего. Также анализ потребления ресурсов каждого deployment, statefulset т.д. Например, можно наглядно увидеть изменение потребления ресурсов после последнего деплоя.
Существуют некоторые готовые решения такие как:
1. kube-prometheus2. kube-Prometheus-Stack
3. bitnami Prometheus Operator
Мне показался наиболее подходящим kube-Prometheus-Stack с плагином devopsprodigy-kubegraf-app.
Dashboards плагина выглядят так:



Это малая часть dashboards. Графиков достаточно для любого анализа.
Архитектура Prometheus
Разница между prometheus и prometheus-operator в том, что в prometheus-operator дополнительно включена Grafana с готовыми дашбордами и ServiceMonitors для сбора метрик из сервисов кластера таких как: CoreDNS, API Server, Scheduler и другие.

Prometheus — главная составляющая всей конструкции. Система мониторинга, которая собирает показатели из ваших служб и сохраняет их в базе данных временных рядов. Если кратко, то она собирает метрики, на которые можно посмотреть при помощи Prometheus Web.
Grafana — веб-приложение для аналитики и интерактивной визуализации
Для построения графиков Grafana может брать данные не только из Prometheus, но и из таких систем как: Graphite, Elasticsearch, OpenTSDB, InfluxDB.
Alertmanager — инструмент для обработки оповещений. Он устраняет дубликаты, группирует и отправляет нотификации.
Экспортёры (агенты) — их задача собирать метрики из сервисов и переводить их в понятный вид для Prometheus. Видов экспортёров существует огромное количество например: mysql_exporter, memcached_exporter, jms_exporter и так далее.
В стеке используются экспортёры:
Node-exporter — собирает метрики о вычислительных ресурсах Node в Kubernetes.
Kube-state-metrics — собирает метрики со всех узлов Kubernetes, обслуживаемых Kubelet через Summary API. Создатели экспортёра были вдохновлены проектом Heapster.Подключение к кластеру
Тестовый проект я буду запускать в Google Cloud Platform. Но так же решение применяется в Azure, AWS. Уверен, оно будет работать и на других платформах.
Для запуска тестового kubernetes cluster в GCP нужно зайти в Kubernetes Engine, нажать Create cluster. Далее выбрать нужные настройки типа: локации, самой локации, описать конфигурацию машин, которые будут выступать в роли нод кластера, и настройку сети кластера. Этого достаточно для демонстрации. Примерно через 10 минут кластер готов к работе.
Подключение к кластеру может быть как через встроенную веб-консоль аккаунта GCP, так и через локальный компьютер. Для работы с GCP из локального компьютера нужно установить пакеты из google-cloud-sdk. Информация по скачиванию и установке пакетов для всех OS.
gcloud auth login

В консоли будет показан url link, по которому нужно перейти в браузер. Затем скопируйте код проверки из браузера в консоль.
Вводим ID проекта, в котором запустили кластер:
gcloud config set project Project-ID
Затем строку подключения к кластеру, которую можно скопировать в окне, открывшемся после нажатия Сonnect на кластере в веб-интерфейсе:


Установка HELM на Linux
Helm — это установщик пакетов для Kubernetes. Обычно его устанавливают локально на ОС, с которой управляется Kubernetes. Helm нам нужен для быстрой установки пакетов Kube-Prometheus-Stack в Kubernetes. Чтобы оставалась возможность обновлять helm, рекомендую сделать установку через apt:
curl https://baltocdn.com/helm/signing.asc | sudo apt-key add –
sudo apt-get install apt-transport-https –yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
Подготовка к установке Kube-Prometheus-Stack
Перед запуском Kube-Prometheus-Stack нужно описать файлы конфигурации Grafana и Alertmanager.
1. Добавление плагинов в Grafana
В самой Grafana нам понадобится плагин devopsprodigy-kubegraf-app из списка плагинов Grafana Labs. У него достаточно обширные dashboards.
Для добавления плагина мы создадим .yml-файл, который будем использовать при запуске установки Kube-Prometheus-Stack.
mkdir /opt/Kube-Prometheus-Stack
nano /opt/Kube-Prometheus-Stack/grafana.yml
В файле прописываем параметр:
grafana:
plugins:
- devopsprodigy-kubegraf-app
2. Добавление параметров в Alertmanager
Кроме визуальной информации нужно настроить оповещение о проблемах. Для этого и существует Alertmanager. Нам нужно, чтобы нотификации приходили в slack, канал #grafana. Потому мы заранее, в нужном нам workspace slack, генерируем webhook URL и создаем канал #grafana. Для изменения стандартных параметров Alertmanager, по аналогии с Grafana, — создаем файл alertmanager.yml, в котором будут указаны координаты отправки оповещений и шаблон самого сообщения — Prometheus Event Notification.
Заменяем содержимое переменных:
slack_api_url:
channel:
username:
nano /opt/Kube-Prometheus-Stack/alertmanager.yml
Содержимое файла:
alertmanager:
config:
global:
resolve_timeout: 5m
slack_api_url: 'https://hooks.slack.com/services/……’ # Ваш webhook URL
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
receiver: 'default-receiver'
routes:
- match:
alertname: DeadMansSwitch
receiver: 'null'
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'cluster', 'service']
receivers:
- name: 'default-receiver'
slack_configs:
- channel: '#grafana' # Ваш канал Slack для оповещений
username: 'Grafana-Kube' # Имя, отображаемое в оповещении
color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'
title: '[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] Prometheus Event Notification'
title_link: '{{ template "slack.default.titlelink" . }}'
pretext: '{{ .CommonAnnotations.summary }}'
text: |-
{{ range .Alerts }}
{{- if .Annotations.summary }}*Alert:* {{ .Annotations.summary }} - `{{ .Labels.severity }}`{{- end }}
*Description:* {{ .Annotations.description }}{{ .Annotations.message }}
*Graph:* <{{ .GeneratorURL }}|:chart_with_upwards_trend:>{{ if or .Annotations.runbook .Annotations.runbook_url }} *Runbook:* <{{ .Annotations.runbook }}{{ .Annotations.runbook_u
rl }}|:spiral_note_pad:>{{ end }}
*Details:*
{{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`
{{ end }}
{{ end }}
fallback: '{{ template "slack.default.fallback" . }}'
icon_emoji: '{{ template "slack.default.iconemoji" . }}'
icon_url: '{{ template "slack.default.iconurl" . }}'
send_resolved: true
- name: 'null'
Установка Kube-Prometheus-Stack
Наконец, мы подошли к установке того, ради чего все затевалось.
Для установки нужно добавить репозитории в helm:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
Теперь запускаем непосредственно установку Kube-Prometheus-Stack
helm install --set name=grafana my-test prometheus-community/kube-prometheus-stack -f /opt/Kube-Prometheus-Stack/grafana.yml -f /opt/Kube-Prometheus-Stack/alertmanager.yml
Спустя некоторое время можно проверить запущенные pods
kubectl get po
Проверяем, что настройки Аlertmanager применились. Для этого проксируем pod alertmanager на локальный порт:
kubectl port-forward alertmanager-my-test-prometheus-operato-alertmanager-0 9093
В браузере на странице alertmanager переходим во вкладку Status, где можно удостовериться, что текущие настройки соответствуют конфигу alertmanager.yml.
Генерация token для доступа к кластеру
Для подключения к кластеру Kubernetes ранее установленного в Grafana плагина нужно сгенерировать token.
Для этого применяем манифесты для kubernetes
kubectl apply -f https://raw.githubusercontent.com/devopsprodigy/kubegraf/master/kubernetes/serviceaccount.yaml
kubectl apply -f https://raw.githubusercontent.com/devopsprodigy/kubegraf/master/kubernetes/clusterrole.yaml
kubectl apply -f https://raw.githubusercontent.com/devopsprodigy/kubegraf/master/kubernetes/clusterrolebinding.yaml
kubectl apply -f https://raw.githubusercontent.com/devopsprodigy/kubegraf/master/kubernetes/secret.yaml
Генерируем token
kubectl get secret grafana-kubegraf-secret -o jsonpath={.data.token} | base64 -d
Настройка плагина в Grafana
Проксируем под Grafana
kubectl port-forward my-test-grafana-6d77c7fdc6-bxqh8 3000
Стандартный логин пароль — admin / prom-operator (войдя в веб-интерфейс, рекомендуем сменить пароль), url — localhost:3000
Переходим на вкладку Configuration →Plugins, выбираем плагин DevOpsProdigy KubeGraf и включаем его. В левой панели появится значок этого плагина — переходим в него — вкладка Clusters. В открывшемся окне добавляем наш кластер kubernetes — Add New Cluster.
Нас интересуют параметры:
Name: любое удобное имя
URL: можно получить введя команду
Информацию о подключаемом кластере можно получить командой:

Skip TLS Verify: Enable
Access via token: Enable
Откроется поле для ввода token, который получили в консоли:

Save & Test
После того как кластер добавится в Grafana можно будет посмотреть его статус приложений, нод и т.д. Будет в распоряжении 5 dashboards:

Протестируем работу Аlertmanager: зайдем на одну из node кластера и сделаем так, чтобы полностью закончилось место на диске. В процессе dd if=/dev/zero …. Сработал триггер, что перегружен процессор:


Бонус
Если нужно простое оповещение об изменениях состояния в кластере, отправляемые в slack, то можно использовать Kubewatch. Устанавливается так же просто через helm с файлом описания конфигурации.
helm install my-test-helm stable/kubewatch -f values-file.yaml
Файл конфигурации:
rbac:
create: true
resourcesToWatch:
deployment: true
replicationcontroller: true
replicaset: true
daemonset: true
services: true
pod: true
job: true
node: true
clusterrole: true
serviceaccount: true
persistentvolume: true
namespace: true
secret: true
configmap: true
ingress: true
slack:
channel: '#grafana'
token: 'xoxb-KEhH7LhRHF6wNWnfqnBdsCfwvq8qCwRni3lLLrBwIcjvF/Xxs9wUG2VLrLtn06VU108Xa60IUBSGcqtg6S1UVg==’
Мы можем указать в файле конфигурации информацию о каких изменениях в кластере необходимо оповещать в slack-канал. В отличие от настроек Аlertmanager, в KubeWatch используется не webhook_url_api, а бот для авторизации, с которым нужно указывать token и группу. Как итог, получаем такие сообщения в канал:

Плюсы данного метода — простая настройка, быстрое оповещение. Минус — если выбрать все resourcesToWatch:, то KubeWatch будет слать много сообщений. Как я понял, это происходит по причине того, что, например, некоторые объекты в Kubernetes могут самостоятельно обновиться, а KubeWatch это фиксирует и сразу оповещает.
В итоге мы рассмотрели установку и настройку одного метода мониторинга для визуального отображения информации о кластере Kubernetes и два метода для оповещения о возникших проблемах в кластере. Моей целью было кратко описать рабочую схему установки и настройки мониторинга. Надеюсь, я справился. Мониторинг в данном виде работает и выполняет свое предназначение. Но нет предела совершенству.
Есть мысли по небольшому дополнению/модернизации этого стека. Причина — кластеров Kubernetes становится больше и устанавливать весь стек целиком на каждый кластер стало казаться не очень хорошей идеей, так как заходить на каждый кластер в Grafana для анализа графиков становится все большей рутиной. Есть желание объединять мониторинг в одном Grafana. Рассмотренный плагин для Grafana поддерживает подключение нескольких кластеров, но пока стоит вопрос о правильной настройке со стороны безопасности. Объединять мониторинг кластеров разных сред, да и к тому же разных проектов — не самая лучшая идея.
Так же меня не совсем устраивает форма нотификаций (Prometheus Event Notification). Хочется что-то в ней улучшить, но еще не определился, что именно.В нашей следующей статье расскажем, как реализовать выкладку приложения CI/CD в Kubernetess.