Следующая задача — настроить мониторинг Kubernetes.
Задача осложняется тем, что у нас есть целый набор ресурсов, которые требуется мониторить:
- инфраструктура — ЕС2 инстасы WokerNodes, их ЦПУ, память, сеть
- ключевые сервисы самого Kubernetes — состояние API сервера, etcd, scheduler
- состояние подов и контейнеров
- состояние деплойментов
- сбор метрик непосредственно с приложений
Для мониторинга всего этого доступны следующие сервисы:
metrics-server
— метрики использования ресурсов CPU, памяти, файл-дескрипторы, etccAdvisor
— метрики Docker-демона, мониторинг контейнеровkube-state-metrics
— состояние деплойментов, нодов, подnode-exporter
: метрики серверов (CPU, memory, network)
Что именно будем делать?
- запустим Prometheus сервер
- запустим Redis и redis-exporter и настроим сбор его метрик
- настроим ClusterRole для Prometheus
- настроим Prometheus Kubernetes Service Discovery и настроим сбор метрик с:
- посмотрим на Service Discovery роли
- запустим експортеры:
- node-exporter
- kube-state-metrics
- метрики cAdvisor
- запустим metrics-server
Как всё будет работать?
Используем Prometheus Federation:
- у нас уже есть Prometheus-Grafana стек, который занимается мониторингом существующих ресурсов — это будет наш «центральный» сервер мониторинга, который будет собирать метрики с других серверов Prometheus (все VPC сети объединены через VPC peering, и передача метрик идёт внутри сетей)
- в EKS-кластер будет отдельный Prometheus-сервер, который будет собирать метрики кластера и експортёров в нём, а потом будет отдавать их центральному серверу
helm install
В 99% всех встреченных гайдов по Prometheus и Kubernetes вся установка и настройка сводились к «helm install
«.
Helm это, конечно, круто — и шаблонизатор, и «менеджер пакетов», но проблема в том, что он слишком много делает «под капотом», а сейчас хочется посмотреть, что и как вообще выполняется для настройки мониторинга Kubernetes в Prometheus.
По сути, этот пост — продолжение постов AWS: Elastic Kubernetes Service — автоматизация создания кластера, часть 1 — CloudFormation и AWS: Elastic Kubernetes Service — автоматизация создания кластера, часть 2 — Ansible, eksctl, поэтому местами будет Ansible.
Используемые версии:
- Kubernetes: (AWS EKS): v1.15.11
- Prometheus: 2.17.1
- kubectl: v1.18.0
Содержание
kubectl
conext
При необходимости — настраиваем новый контекст:
[simterm]
$ aws --region eu-west-2 eks update-kubeconfig --name bttrm-eks-dev-2 Added new context arn:aws:eks:eu-west-2:534***385:cluster/bttrm-eks-dev-2 to /home/admin/.kube/config
[/simterm]
Или переключаем kubectl
на нужный кластер:
[simterm]
$ kubectl config get-contexts ... arn:aws:eks:eu-west-2:534****385:cluster/bttrm-eks-dev-1 ...
$ kubectl config use-context arn:aws:eks:eu-west-2:534***385:cluster/bttrm-eks-dev-2 Switched to context "arn:aws:eks:eu-west-2:534***385:cluster/bttrm-eks-dev-2".
[/simterm]
ConfigMap
Reloader
Так как мы постоянно будем вносить изменения в ConfigMap
нашего Prometheus — имеет смысл сразу добавить Reloader, что бы поды подхватывали изменения в конфиге.
Создаём для него каталог:
[simterm]
$ mkdir -p roles/reloader/tasks
[/simterm]
И одну задачу — установку самого Reloader. Используем kubectl
, вызываем просто через Ansible command
.
В roles/reloader/tasks/main.yml
добавляем:
- name: "Install Reloader" command: "kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml"
Пока таким костылём — нет времени на k8s
и его проблемы с импортом python-requests
.
Добавляем вызов в плейбук:
- hosts: - all become: true roles: - role: cloudformation tags: infra - role: eksctl tags: eks - role: reloader tags: reloader
Запускаем:
[simterm]
$ ansible-playbook eks-cluster.yml --tags reloader
[/simterm]
Проверяем:
[simterm]
$ kubectl get po NAME READY STATUS RESTARTS AGE reloader-reloader-55448df76c-9l9j7 1/1 Running 0 3m20s
[/simterm]
Запуск Prometheus сервера в Kubernetes
Сначала запустим сам Prometheus в кластере.
Файл настроек будем передавать через ConfigMap
.
Кластер уже создан, и в будущем всё будет управляться Ansible — создаём структуру каталогов:
[simterm]
$ mkdir -p roles/monitoring/{tasks,templates}
[/simterm]
Namespace
Все связанные с мониторингом ресурсы будем держать в отдельном namespace.
В каталоге roles/monitoring/templates/
создаём для него конфиг, назовём prometheus-ns.yml.j2
:
--- apiVersion: v1 kind: Namespace metadata: name: monitoring
Создаём файл roles/monitoring/tasks/main.yml
и добавляем создание namespace:
- name: "Create the Monitoring Namespace" command: "kubectl apply -f roles/monitoring/templates/prometheus-ns.yml.j2"
Добавляем вызов в плейбук:
- hosts: - all become: true roles: - role: cloudformation tags: infra - role: eksctl tags: eks - role: reloader tags: reloader - role: monitoring tags: monitoring
Запускаем для проверки:
[simterm]
$ ansible-playbook eks-cluster.yml --tags monitoring
[/simterm]
Проверяем:
[simterm]
$ kubectl get ns NAME STATUS AGE default Active 24m kube-node-lease Active 25m kube-public Active 25m kube-system Active 25m monitoring Active 32s
[/simterm]
prometheus.yml
ConfigMap
Файл настроек Prometheus будем хранить в отдельном ConfigMap
.
Создаём файл roles/monitoring/templates/prometheus-configmap.yml.j2
— это минимальный конфиг для запуска сервера:
--- apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: monitoring data: prometheus.yml: | global: scrape_interval: 15s external_labels: monitor: 'eks-dev-monitor' scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090']
Добавляем его в roles/monitoring/tasks/main.yml
:
- name: "Create the Monitoring Namespace" command: "kubectl apply -f roles/monitoring/templates/prometheus-ns.yml.j2" - name: "Create prometheus.yml ConfigMap" command: "kubectl apply -f roles/monitoring/templates/prometheus-configmap.yml.j2"
Можно ещё раз проверить — запускаем, и глянем ConfigMap
:
[simterm]
$ kubectl -n monitoring get configmap prometheus-config -o yaml apiVersion: v1 data: prometheus.yml: | global: scrape_interval: 15s external_labels: monitor: 'eks-dev-monitor' scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090'] kind: ConfigMap ...
[/simterm]
Prometheus Deployment и LoadBalancer Service
Теперь можно запускать сам Prometheus.
Создаём файл деплоймента — roles/monitoring/templates/prometheus-deployment.yml.j2
:
--- apiVersion: apps/v1 kind: Deployment metadata: name: prometheus-server labels: app: prometheus namespace: monitoring annotations: reloader.stakater.com/auto: "true" # service.beta.kubernetes.io/aws-load-balancer-internal: "true" spec: replicas: 2 selector: matchLabels: app: prometheus template: metadata: labels: app: prometheus spec: containers: - name: prometheus-server image: prom/prometheus volumeMounts: - name: prometheus-config-volume mountPath: /etc/prometheus/prometheus.yml subPath: prometheus.yml ports: - containerPort: 9090 volumes: - name: prometheus-config-volume configMap: name: prometheus-config --- kind: Service apiVersion: v1 metadata: name: prometheus-server-alb namespace: monitoring spec: selector: app: prometheus ports: - protocol: TCP port: 80 targetPort: 9090 type: LoadBalancer
Тут:
- запускаем два пода с Prometheus
- подключаем им prometheus-config
ConfigMap
- создаём
Service
типаLoadBalancer
для доступа к Prometheus на порт 9090 — создаст AWS LoadBalancer типа Classic (не Application LB) с Listener на порту 80
Анноттации:
- reloader.stakater.com/auto: «true» — используется для Reloader.
- service.beta.kubernetes.io/aws-load-balancer-internal: «true» пока комментируем —
Internal
используем позже, когда будем настраивать VPC peering и Prometheus federation, пока делаем Internet-facing.
Добавляем вызов в tasks
:
... - name: "Deploy Prometheus server and its LoadBalancer" command: "kubectl apply -f roles/monitoring/templates/prometheus-deployment.yml.j2"
Запускаем:
[simterm]
$ ansible-playbook eks-cluster.yml --tags monitoring ... TASK [monitoring : Deploy Prometheus server and its LoadBalancer] **** changed: [localhost] ...
[/simterm]
Проверяем поды:
[simterm]
$ kubectl -n monitoring get pod NAME READY STATUS RESTARTS AGE prometheus-server-85989544df-pgb8c 1/1 Running 0 38s prometheus-server-85989544df-zbrsx 1/1 Running 0 38s
[/simterm]
LoadBalancer Service:
[simterm]
$ kubectl -n monitoring get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prometheus-server-alb LoadBalancer 172.20.160.199 ac690710a9747460abc19cd999812af8-1463800400.eu-west-2.elb.amazonaws.com 80:30190/TCP 42s
[/simterm]
Он же в AWS:
Проверяем — открываем в браузере:
Если с LoadBalancer проблемы — пробуем через порт-форвад:
[simterm]
$ kubectl -n monitoring port-forward prometheus-server-85989544df-pgb8c 9090:9090 Forwarding from 127.0.0.1:9090 -> 9090 Forwarding from [::1]:9090 -> 9090
[/simterm]
И открываем через URL localhost:9090.
Настройка мониторинга
Хорошо, сам сервер для сбора метрик мы запустили, теперь надо в него собрать собственно метрики.
Начнём с самого простого — запустим сервис, к нему добавим експортёр, а потом соберём метрики приложения в Prometehus.
Redis && redis_exporter
Используем Redis server и для него — redis_exporter
.
Создадим деплоймент, например roles/monitoring/templates/tests/redis-server-and-exporter-deployment.yml.j2
:
--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: redis spec: replicas: 1 template: metadata: annotations: prometheus.io/scrape: "true" labels: app: redis spec: containers: - name: redis image: redis resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379 - name: redis-exporter image: oliver006/redis_exporter:latest resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 9121 --- kind: Service apiVersion: v1 metadata: name: redis spec: selector: app: redis ports: - name: redis protocol: TCP port: 6379 targetPort: 6379 - name: prom protocol: TCP port: 9121 targetPort: 9121
В аннотациях тут:
- prometheus.io/scrape — используется в фильтрах pod и services, см. Roles
- prometheus.io/port — если порт для сбора метрик отличается от заданного в шаблоне (
containerPort
, видимо) — то можно переопределить его тут - prometheus.io/path — если путь метрик отличается от стандартного
/metrics
— можно переопределить его тут
См. Per-pod Prometheus Annotations.
Обратите внимание, что мы не указываем namespace — и Redis, и его екпортёр будут запущены в default namespace, скоро увидим — к каким ограничениям это приведёт.
Деплоим — тут руками, задача тестовая, в мониторинге не нужна:
[simterm]
$ kubectl apply -f roles/monitoring/templates/tests/redis-server-and-exporter-deployment.yml.j2 deployment.extensions/redis created service/redis created
[/simterm]
Проверяем — должен быть под и в нём два контейнера.
В default namespace находим под:
[simterm]
$ kubectl get pod NAME READY STATUS RESTARTS AGE redis-698cd557d5-xmncv 2/2 Running 0 10s reloader-reloader-55448df76c-9l9j7 1/1 Running 0 23m
[/simterm]
В проверяем в нём контейнеры:
[simterm]
$ kubectl get pod redis-698cd557d5-xmncv -o jsonpath='{.spec.containers[*].name}' redis redis-exporter
[/simterm]
Окей.
Теперь добавим сбор метрик с этого експортёра — обновляем prometheus-configmap.yml.j2
ConfigMap — добавляем новый таргет, redis:
--- apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: monitoring data: prometheus.yml: | global: scrape_interval: 15s external_labels: monitor: 'eks-dev-monitor' scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090'] - job_name: 'redis' static_configs: - targets: ['redis:9121']
Деплоим (руками, или через Ansible), и проверяем Targets нашего Prometheus:
Окей — таргет появился, но почему ошибка «Get http://redis:9121/metrics: dial tcp: lookup redis on 172.20.0.10:53: no such host»?
Prometheus ClusterRole, ServiceAccount и ClusterRoleBinding
Как помним, наш Prometheus запущен в namespace с именем monitoring:
[simterm]
$ kubectl get ns monitoring NAME STATUS AGE monitoring Active 25m
[/simterm]
Тогда как в деплойменте Redis namespace задан не был и, соотвественно, под был создан в default namespace:
[simterm]
$ kubectl -n default get pod NAME READY STATUS RESTARTS AGE redis-698cd557d5-xmncv 2/2 Running 0 12m
[/simterm]
Или так:
[simterm]
$ kubectl get pod redis-698cd557d5-xmncv -o jsonpath='{.metadata.namespace}' default
[/simterm]
Что бы Prometheus имел доступ ко всем пространствам имён кластера — создадим ему ClusterRole
, ServiceAccount
и ClusterRoleBinding
, см. Kubernetes: знакомство, часть 5 — RBAC авторизация и примеры Role и RoleBinding.
Этот же ServiceAccount позже будем использовать для Kubernetes Service Discovery.
Добавляем файл roles/monitoring/templates/prometheus-rbac.yml.j2
:
--- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - services - endpoints - pods - nodes - nodes/proxy - nodes/metrics verbs: ["get", "list", "watch"] - apiGroups: - extensions resources: - ingresses verbs: ["get", "list", "watch"] --- apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: monitoring --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: monitoring
Добавляем его вызов после создания ConfigMap и перед деплойментом самого Prometheus-сервера:
- name: "Create the Monitoring Namespace" command: "kubectl apply -f roles/monitoring/templates/prometheus-ns.yml.j2" - name: "Create prometheus.yml ConfigMap" command: "kubectl apply -f roles/monitoring/templates/prometheus-configmap.yml.j2" - name: "Create Prometheus ClusterRole" command: "kubectl apply -f roles/monitoring/templates/prometheus-rbac.yml.j2" - name: "Deploy Prometheus server and its LoadBalancer" command: "kubectl apply -f roles/monitoring/templates/prometheus-deployment.yml.j2"
Обновляем prometheus-deployment.yml
— в spec
добавляем serviceAccountName
:
... template: metadata: labels: app: prometheus spec: serviceAccountName: prometheus containers: - name: prometheus-server image: prom/prometheus ...
Кроме того, для обращения к подам в другом namespace адрес пода надо указывать в виде полного FQDN, с указанием пространства имён, в нашем случае адрес будет redis.default.svc.cluster.local, см. DNS for Services and Pods.
Обновляем ConfigMap — меняем адрес Redis:
... scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090'] - job_name: 'redis' static_configs: - targets: ['redis.default.svc.cluster.local:9121']
Деплоим с Ansible, что бы обновилось всё:
[simterm]
$ ansible-playbook eks-cluster.yml --tags monitoring
[/simterm]
Проверяем таргеты:
Prometheus Kubernetes Service Discovery
static_configs
в Prometheus — хорошо, но что, если надо будет собирать метрики с десятков или сотен сервисов?
Решение — использовать kubernetes_sd_config
.
kubernetes_sd_config
роли
Kubernetes SD в Prometheus имеет набор «ролей», согласно которым выполняется сбор метрик.
Каждая такая роль имеет собственный набор лейблов, см. документацию:
- node: обнаружит по одному таргету на каждой WorkerNode кластера, соберёт метрики kubelet
- service: обнаружит и вернёт каждый сервис и его порт
- pod: выполнит поиск всех подов и вернёт их контейнеры как таргеты для сбора метрик
- endpoints: создаст таргеты из каждого ендпоинта каждого сервиса
- ingress: создаст таргеты каждого path в каждом ingress
Различия по сути только в том, какие лейблы будут добавлены к собираемым метрикам, и какой адрес таргета будет использоваться.
Примеры конфигов:
Кроме того, для подключения к API-серверу с использованием SSL/TLS потребуется указать CA-сертификат сервера для проверки валидности этого API-сервера, см. Accessing the API from a Pod.
А для самой авторизации на API-сервере — используем токен из файла bearer_token_file
, который смонтируется из serviceAccountName: prometheus
, который мы указали в деплойменте.
node role
Посмотрим что нам вернёт каждая такая роль, начнём с node — добавляем в scrape_configs
, можно прямо скопипастить из примера:
... - job_name: 'kubernetes-nodes' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node
Пока без релейблов — запускаем, проверяем таргеты:
Доступные лейблы и их значения — в Status > Service Discovery:
И метрики kubelet_*:
Добавим релейбл, см. relabel_config
и пост Life of a Label.
Что нам предлагают?
... relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics ...
- собираем лейблы
__meta_kubernetes_node_label_alpha_eksctl_io_cluster_name
,__meta_kubernetes_node_label_alpha_eksctl_io_nodegroup_name
и т.д., вырезаем(.+)
— получим лейблы типаalpha_eksctl_io_cluster_name
,alpha_eksctl_io_nodegroup_name
, etc - обновляем лейблу
__address__
— вносим значение kubernetes.default.svc:443 что бы сформировать адрес запроса к таргетам - получаем занчение из
__meta_kubernetes_node_name
и обновляем лейблу` __metrics_path__` — вносим в неё /api/v1/nodes/__meta_kubernetes_node_name/proxy/metrics
В результате Prometheus выстроит запрос вида kubernetes.default.svc:443/api/v1/nodes/ip-10-1-57-13.eu-west-2.compute.internal/proxy/metrics — и соберёт метрики с этой WorkerNode.
Обновляем, проверяем:
Отлично.
pod role
Оттуда же берём пример для pod:
... - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
Проверяем:
Нашлись вообще все поды, но зачем так много?
Добавим проверку аннотации prometheus.io/scrape: «true»:
... relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true ...
Которая есть в нашем Редисе:
... template: metadata: annotations: prometheus.io/scrape: "true" ...
И результат:
http://10.1.44.135:6379/metrics — сам Redis-сервер, метрик у которого нет.
Хотим вырезать и его? Добавим ещё один фильтр:
... - source_labels: [__meta_kubernetes_pod_container_name] action: keep regex: .*-exporter ...
Т.е. собираем только метрики, у которых в лейбле __meta_kubernetes_pod_container_name
есть «-exporter«.
Проверяем:
В целом тут вроде разобрались.
Что осталось?
- node-exporter
- kube-state-metrics
- cAdvisor
- metrics-server
node-exporter metrics
Добавим node_exporter
, что бы собирать метрики с ЕС2-инстансов.
Так как pod с екпортёром надо разместить на каждой WorkerNode — используем тип DaemonSet
.
Создаём файл roles/monitoring/templates/prometheus-node-exporter.yml.j2
— запуcкаем по одному поду на каждой WorkerNode, в monitoring namespace, и к ним добавляем Service, что бы Prometheus смог собрать метрики с ендпоинтов:
--- apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: node-exporter labels: name: node-exporter namespace: monitoring spec: template: metadata: labels: name: node-exporter app: node-exporter annotations: prometheus.io/scrape: "true" spec: hostPID: true hostIPC: true hostNetwork: true containers: - ports: - containerPort: 9100 protocol: TCP resources: requests: cpu: 0.15 securityContext: privileged: true image: prom/node-exporter args: - --path.procfs - /host/proc - --path.sysfs - /host/sys - --collector.filesystem.ignored-mount-points - '"^/(sys|proc|dev|host|etc)($|/)"' name: node-exporter volumeMounts: - name: dev mountPath: /host/dev - name: proc mountPath: /host/proc - name: sys mountPath: /host/sys - name: rootfs mountPath: /rootfs volumes: - name: proc hostPath: path: /proc - name: dev hostPath: path: /dev - name: sys hostPath: path: /sys - name: rootfs hostPath: path: / --- kind: Service apiVersion: v1 metadata: name: node-exporter namespace: monitoring spec: selector: app: node-exporter ports: - name: node-exporter protocol: TCP port: 9100 targetPort: 9100
В roles/monitoring/tasks/main.yml
добавляем вызов:
... - name: "Deploy node-exporter to WorkerNodes" command: "kubectl apply -f roles/monitoring/templates/prometheus-node-exporter.yml.j2"
И подумаем — как собирать метрики.
Первое — какую роль использовать? Нам надо указать порт 9100 — значит роль node
отпадает — у неё нет порта:
[simterm]
$ kubectl -n monitoring get node NAME STATUS ROLES AGE VERSION ip-10-1-47-175.eu-west-2.compute.internal Ready <none> 3h36m v1.15.10-eks-bac369 ip-10-1-57-13.eu-west-2.compute.internal Ready <none> 3h37m v1.15.10-eks-bac369
[/simterm]
Service?
The address will be set to the Kubernetes DNS name of the service and respective service port
Посмотрим, что там:
[simterm]
$ kubectl -n monitoring get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE node-exporter ClusterIP 172.20.242.99 <none> 9100/TCP 37m
[/simterm]
Смотрим, какие мета-лейблы есть у роли service
— всё хорошо, но нет лейбл под Worker Nodes кластера — а нам надо собрать метрики с каждого node_exporter
на каждой WorkerNode.
Смотрим дальше — endpoints
:
[simterm]
$ kubectl -n monitoring get endpoints NAME ENDPOINTS AGE node-exporter 10.1.47.175:9100,10.1.57.13:9100 44m prometheus-server-alb 10.1.45.231:9090,10.1.53.46:9090 3h24m
[/simterm]
10.1.47.175:9100,10.1.57.13:9100 — ага, вот эти ребята!
Значит — можем использовать endpoints
, кроме того — у этой роли будет лейбла __meta_kubernetes_endpoint_node_name
.
Пробуем:
... - job_name: 'node-exporter' kubernetes_sd_configs: - role: endpoints relabel_configs: - source_labels: [__meta_kubernetes_endpoints_name] regex: 'node-exporter' action: keep
Проверяем таргеты:
И метрики:
Примеры запросов для графиков с
node_exporter
есть в посте Grafana: создание dashboard.
kube-state-metrics
Для сбора метрик о ресурсах самого Kubernetes используем kube-state-metrics
.
В roles/monitoring/tasks/main.yml
добавляем его установку:
... - git: repo: 'https://github.com/kubernetes/kube-state-metrics.git' dest: /tmp/kube-state-metrics - name: "Install kube-state-metrics" command: "kubectl apply -f /tmp/kube-state-metrics/examples/standard/"
Сам деплоймент можно помотреть в файле https://github.com/kubernetes/kube-state-metrics/blob/master/examples/standard/deployment.yaml.
Тут Service Discovery не обязателен, т.к. у нас будет только один сервис kube-state-metrics
.
Используем static_configs
:
... - job_name: 'kube-state-metrics' static_configs: - targets: ['kube-state-metrics.kube-system.svc.cluster.local:8080']
Проверяем таргеты:
И метрики, например — kube_deployment_status_replicas_available
:
cAdvisor
Сам cAdvisor
, думаю, в представлении не особо нуждается — одна из наиболее используемых систем для сбора метрик контейнеров.
Он уже встроен в Kubernetes, поэтому експортёр не нужен — только добавить сбор метрик. Пример можно взять в том же https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml#L102.
Обновляем roles/monitoring/templates/prometheus-configmap.yml.j2
:
... - job_name: 'cAdvisor' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
Деплоим, проверяем:
У нас две Kubernetes WorkerNode, с каждой собираем метрики контейнеров — отлично.
Сами метрики:
metrics-server
Для него есть екпортеры — но сейчас нам его метрики не важны, просто добавим его установку, что бы работали лимиты с kubectl top
.
Раньше установка была немного сложнее, см. Kubernetes: запуск metrics-server в AWS EKS для Kubernetes Pod AutoScaler — надо было вносить правки в деплоймент, но сейчас на EKS завелось из коробки.
Обновляем roles/monitoring/tasks/main.yml
:
... - git: repo: "https://github.com/kubernetes-sigs/metrics-server.git" dest: "/tmp/metrics-server" - name: "Install metrics-server" command: "kubectl apply -f /tmp/metrics-server/deploy/kubernetes/" ...
Деплоим, проверяем поды в kube-system
namespace:
[simterm]
$ kubectl -n kube-system get pod NAME READY STATUS RESTARTS AGE aws-node-s7pvq 1/1 Running 0 4h42m ... kube-proxy-v9lmh 1/1 Running 0 4h42m kube-state-metrics-6c4d4dd64-78bpb 1/1 Running 0 31m metrics-server-7668599459-nt4pf 1/1 Running 0 44s
[/simterm]
Под metrics-server
появлися — окей.
Через пару минут можно пробовать top node
:
[simterm]
$ kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% ip-10-1-47-175.eu-west-2.compute.internal 47m 2% 536Mi 14% ip-10-1-57-13.eu-west-2.compute.internal 58m 2% 581Mi 15%
[/simterm]
И поды:
[simterm]
$ kubectl top pod NAME CPU(cores) MEMORY(bytes) redis-6d9cf9d8cb-dfnn6 2m 5Mi reloader-reloader-55448df76c-wsrfv 1m 7Mi
[/simterm]
В целом вроде всё.
Можно приводить в порядок, и допиливать по ходу дела.
Ссылки по теме
- Kubernetes Monitoring with Prometheus -The ultimate guide
- Monitoring multiple federated clusters with Prometheus — the secure way
- Monitoring Your Kubernetes Infrastructure with Prometheus
- Volume Monitoring in Kubernetes with Prometheus
- Trying Prometheus Operator with Helm + Minikube
- How to monitor your Kubernetes cluster with Prometheus and Grafana
- Monitoring Redis with builtin Prometheus
- Kubernetes in Production: The Ultimate Guide to Monitoring Resource Metrics with Prometheus
- How To Monitor Kubernetes With Prometheus
- Using Prometheus + grafana + node-exporter
- Running Prometheus on Kubernetes
- Prometheus Self Discovery on Kubernetes
- Kubernetes – Endpoints
Configs
- doks-monitoring/manifest/prometheus-configmap.yaml
- prometheus/documentation/examples/prometheus-kubernetes.yml
- charts/stable/prometheus/templates/server-configmap.yaml