253741748224
container_fs_limit_bytes{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",container="POD",container_name="POD",device="/dev/vda1",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod5a815a40_f2de_11ea_88d2_0242ac110032.slice/docker-76711789af076c8f2331d8212dad4c044d263c5cc3fa333347921bd6de7950a4.scope",image="k8s.gcr.io/pause:3.1",instance="controlplane",job="kubernetes-cadvisor",kubernetes_io_arch="amd64",kubernetes_io_hostname="controlplane",kubernetes_io_os="linux",name="k8s_POD_kube-proxy-nhzhn_kube-system_5a815a40-f2de-11ea-88d2-0242ac110032_0",namespace="kube-system",pod="kube-proxy-nhzhn",pod_name="kube-proxy-nhzhn"}
253741748224
В нём присутствую метрики оперативной памяти через его устройство: "container_fs_limit_bytes{device="tmpfs"} / 1000 / 1000 / 1000"
{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",device="tmpfs",id="/",instance="controlplane",job="kubernetes-cadvisor",kubernetes_io_arch="amd64",kubernetes_io_hostname="controlplane",kubernetes_io_os="linux"} 0.209702912
{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",device="tmpfs",id="/",instance="node01",job="kubernetes-cadvisor",kubernetes_io_arch="amd64",kubernetes_io_hostname="node01",kubernetes_io_os="linux"} 0.409296896
Если мы хотим получить минимальный диск, то нам нужно из списка убрать устройство оперативной памяти: "min(container_fs_limit_bytes{device!="tmpfs"} / 1000 / 1000 / 1000)"
{} 253.74174822400002
Кроме метрик, указывающие само значение метрики, есть метрики счётчики. Их название, обычно, заканчиваются на "_total". Если их посмотреть, то мы увидим возрастающую линию. Чтобы получить значение, нам нужно получить разницу (с помощью функции rate) за период времени (указывается в квадратных скобках), примерно так rate(name_metric_total)[time]. Время, обычно ведётся в секундах или минутах. Для обозначения секунд используются приставка "s", например, 40s, 60s. Для минут "m", например, 2m, 5m. Важно заметить, что нельзя устанавливать время, меньшее времени опроса exporter, иначе метрика не будет отображаться.
А посмотреть имена метрик, которые смог записать можно по пути /metrics:
controlplane $ curl https://2886795314-9090-ollie08.environments.katacoda.com/metrics 2>/dev/null | head
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 3.536e-05
go_gc_duration_seconds{quantile="0.25"} 7.5348e-05
go_gc_duration_seconds{quantile="0.5"} 0.000163193
go_gc_duration_seconds{quantile="0.75"} 0.001391603
go_gc_duration_seconds{quantile="1"} 0.246707852
go_gc_duration_seconds_sum 0.388611299
go_gc_duration_seconds_count 74
# HELP go_goroutines Number of goroutines that currently exist.
Поднятие связки Prometheus и Graphana
Мы рассмотрели метрики в уже настроенном Prometheus, теперь поднимем Prometheus и настроим его сами:
essh@kubernetes-master:~$ docker run -d net=host name prometheus prom/prometheus
09416fc74bf8b54a35609a1954236e686f8f6dfc598f7e05fa12234f287070ab
essh@kubernetes-master:~$ docker ps -f name=prometheus
CONTAINER ID IMAGE NAMES
09416fc74bf8 prom/prometheus prometheus
UI с графиками по отображению метрик:
essh@kubernetes-master:~$ firefox localhost:9090
Добавим метрику go_gc_duration_seconds{quantile="0"} из списка:
essh@kubernetes-master:~$ curl localhost:9090/metrics 2>/dev/null | head -n 4
# 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.0097e-05
go_gc_duration_seconds{quantile="0.25"} 1.7841e-05
Зайдя в UI по адресу localhost:9090 в меню выберем Graph. Добавим в дашборд с графиком: выбираем метрику с помощью списка insert metrics at cursor. Здесь мы видим те же метрики, что и в списке localhost:9090/metrics, но агрегированные по параметрам, например, просто go_gc_duration_seconds. Мы выбираем метрику go_gc_duration_seconds и покажем её по кнопке Execute. Во вкладке console дашборда видим метрики:
go_gc_duration_seconds{instance="localhost:9090",JOB="prometheus",quantile="0"} 0.000009186 go_gc_duration_seconds{instance="localhost:9090",JOB="prometheus",quantile="0.25"} 0.000012056 go_gc_duration_seconds{instance="localhost:9090",JOB="prometheus",quantile="0.5"} 0.000023256 go_gc_duration_seconds{instance="localhost:9090",JOB="prometheus",quantile="0.75"} 0.000068848 go_gc_duration_seconds{instance="localhost:9090",JOB="prometheus",quantile="1"} 0.00021869
, перейдя во кладку Graph графическое их представление.
Сейчас Prometheus собирает метрики с текущей ноды: go_*, net_*, process_*, prometheus_*, promhttp_*, scrape_* и up. Для сбора метрик с Docker кажем ему писать его метрики в Prometheus по порту 9323:
eSSH@Kubernetes-master:~$ curl http://localhost:9323/metrics 2>/dev/null | head -n 20
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
builder_builds_failed_total{reason="build_canceled"} 0
builder_builds_failed_total{reason="build_target_not_reachable_error"} 0
builder_builds_failed_total{reason="command_not_supported_error"} 0
builder_builds_failed_total{reason="Dockerfile_empty_error"} 0
builder_builds_failed_total{reason="Dockerfile_syntax_error"} 0
builder_builds_failed_total{reason="error_processing_commands_error"} 0
builder_builds_failed_total{reason="missing_onbuild_arguments_error"} 0
builder_builds_failed_total{reason="unknown_instruction_error"} 0
# HELP builder_builds_triggered_total Number of triggered image builds
# TYPE builder_builds_triggered_total counter
builder_builds_triggered_total 0
# HELP engine_daemon_container_actions_seconds The number of seconds it takes to process each container action
# TYPE engine_daemon_container_actions_seconds histogram
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.005"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.01"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.025"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
Чтобы демон докера применил параметры, его нужно перезапустить, что приведёт к падению всех контейнеров, а при старте демона контейнера будут подняты в соответствии с их политикой:
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
Чтобы демон докера применил параметры, его нужно перезапустить, что приведёт к падению всех контейнеров, а при старте демона контейнера будут подняты в соответствии с их политикой:
essh@kubernetes-master:~$ sudo chmod a+w /etc/docker/daemon.json
essh@kubernetes-master:~$ echo '{ "metrics-addr" : "127.0.0.1:9323", "experimental" : true }' | jq -M -f /dev/null > /etc/docker/daemon.json
essh@kubernetes-master:~$ cat /etc/docker/daemon.json
{
"metrics-addr": "127.0.0.1:9323",
"experimental": true
}
essh@kubernetes-master:~$ systemctl restart docker
Prometheus только отреагирует метрики на одном сервере от разных источников. Для того, чтобы мы могли собирать метрики с разных нод и видеть агрегированный результат, на каждую ноду нужно поставить агента, собирающего метрики:
essh@kubernetes-master:~$ docker run -d \
v "/proc:/host/proc" \
v "/sys:/host/sys" \
v "/:/rootfs" \
-net="host" \
-name=explorer \
quay.io/prometheus/node-exporter:v0.13.0 \
collector.procfs /host/proc \
collector.sysfs /host/sys \
collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"
1faf800c878447e6110f26aa3c61718f5e7276f93023ab4ed5bc1e782bf39d56
и прописать слушать адрес ноды, а пока у нас всё локально, localhost:9100. Теперь сообщим Prometheus слушать агента и докера:
essh@kubernetes-master:~$ mkdir prometheus && cd $_
essh@kubernetes-master:~/prometheus$ cat << EOF > ./prometheus.yml
global:
scrape_interval: 1s
evaluation_interval: 1s
scrape_configs:
job_name: 'prometheus'
static_configs:
targets: ['127.0.0.1:9090', '127.0.0.1:9100', '127.0.0.1:9323']
labels:
group: 'prometheus'
EOF
essh@kubernetes-master:~/prometheus$ docker rm -f prometheus
prometheus
essh@kubernetes-master:~/prometheus$ docker run \
d \
-net=host \
-restart always \
-name prometheus \
v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml
prom/prometheus
7dd991397d43597ded6be388f73583386dab3d527f5278b7e16403e7ea633eef
essh@kubernetes-master:~/prometheus$ docker ps \
f name=prometheus
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7dd991397d43 prom/prometheus "/bin/prometheus c" 53 seconds ago Up 53 seconds prometheus
Теперь доступно 1702 метрики хоста:
essh@kubernetes-master:~/prometheus$ curl http://localhost:9100/metrics | grep -v '#' | wc -l
1702
из всего разнообразия сложно искать нужные для повседневных задач, например, используемое количество памяти node_memory_Active. Для этого есть агрегаторы метрик:
http://localhost:9090/consoles/node.html
http://localhost:9090/consoles/node-cpu.html
Но лучше использовать Grafana. Установим и её, пример можно посмотреть:
essh@kubernetes-master:~/prometheus$ docker run \
d \
-name=grafana \
-net=host
grafana/grafana
Unable to find image 'grafana/grafana:latest' locally
latest: Pulling from grafana/grafana
9d48c3bd43c5: Already exists
df58635243b1: Pull complete
09b2e1de003c: Pull complete
f21b6d64aaf0: Pull complete
719d3f6b4656: Pull complete
d18fca935678: Pull complete
7c7f1ccbce63: Pull complete
Digest: sha256:a10521576058f40427306fcb5be48138c77ea7c55ede24327381211e653f478a
Status: Downloaded newer image for grafana/grafana:latest
6f9ca05c7efb2f5cd8437ddcb4c708515707dbed12eaa417c2dca111d7cb17dc
essh@kubernetes-master:~/prometheus$ firefox localhost:3000
Введем логин admin и пароль admin, после чего нам предложат изменить пароль. Далее нужно выполнить последующую настройку.
В Grafana первоначальный вход по логину admin и такому паролю. Сперва на предлагается выбрать источник выбираем Prometheus, вводим localhost:9090, выбираем подключение не как к серверу, а как к браузеру (то есть по сети) и выбираем, что аутентификация у нас базовая все нажимаем Save and Test и Prometheus подключен.
Понятно, что всем раздавать пароль и логин от админских прав не стоит. Для этого нужно будет завести пользователей или интегрировать их внешней базой данных пользователей, такой как Microsoft Active Directory.
Я выберу во вкладке Dashboard активирую все три перенастроенных дашборда. Из списка New Dashboard верхнего меню выберу дашборд Prometheus 2.0 Stats. Но, данных нет:
Кликну на пункт меню "+" и выберу "Dashboard", предлагается создать дашборд. Дашборд может содержать несколько виджетов, например графики, которые можно располагать и настраивать, поэтому нажимаем на кнопку добавления графика и выбираем его тип. На самом графике выбираем редактировать, выбрав размер, нажимаем редактировать, и тут самое главное выбор демонстрируемой метрики. Выбираем Prometheus
Полная сборка доступна:
essh@kubernetes-master:~/prometheus$ wget \
https://raw.githubusercontent.com/grafana/grafana/master/devenv/docker/ha_test/docker-compose.yaml
--2019-10-30 07:29:52 https://raw.githubusercontent.com/grafana/grafana/master/devenv/docker/ha_test/docker-compose.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com) 151.101.112.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.112.133|:443 connected.
HTTP request sent, awaiting response 200 OK
Length: 2996 (2,9K) [text/plain]
Saving to: docker-compose.yaml
docker-compose.yaml 100%[=========>] 2,93K .-KB/s in 0s
2019-10-30 07:29:52 (23,4 MB/s) docker-compose.yaml saved [2996/2996]
Получение прикладных метрик приложения
До этого момента мы рассматривали случай, когда Prometheus опрашивал стандартный накопитель метрик, получая стандартные метрики. Теперь попробуем создать приложение и отдавать свои метрики. Для начала возьмём сервер NodeJS и напишем под него приложение. Для этого, создадим проект NodeJS: