Prometheus: мониторинг сети с node_exporter – метрики сети CloudWatch и Docker –net=host

Thank you for reading this post, don't forget to subscribe!

Начал обнов­лять даш­бор­ды в Grafana, и столк­нул­ся с дву­мя инте­рес­ны­ми вещами.

Пер­вое – что же на самом деле пока­зы­ва­ет­ся в CloudWatch для сети в гра­фи­ках NetworkIn/Out (Bytes), как эти дан­ные пра­виль­но интер­пре­ти­ро­вать, и как дан­ные CloudWatch кор­ре­ли­ру­ют с дан­ны­ми само­го node_exporter?

Вто­рое – поче­му node_exporter дол­жен быть запу­щен имен­но в режи­ме host network mode?

Сна­ча­ла раз­бе­рём­ся с тем, что имен­но пока­зы­ва­ет CloudWatch: запу­стим тесто­вый EC2, там в Docker запу­стим node_exporter, под­клю­чим его в Prometheus, нагру­зим сеть и посмот­рим на гра­фи­ки от node_exporter и в CloudWatch.

Метрики node_exporter и AWS CloudWatch

Запус­ка­ем инстанс, тут t2.small, уста­нав­ли­ва­ем Docker and Docker Compose:

Запуск node_exporter

Гото­вим файл Docker Compose для node_exporter:

Запус­ка­ем

root@ip-172-31-17-58:/home/ubuntu# docker-compose -f node-exporter-compose.yaml up
Pulling node_exporter (quay.io/prometheus/node-exporter:latest)…
latest: Pulling from prometheus/node-exporter

Про­ве­ря­ем, есть ли данные:

root@ip-172-31-17-58:/home/ubuntu# curl -s localhost:9100/metrics | head -5
HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0

Подключение Prometheus и Grafana

Добав­ля­ем его в Prometehus – тут у меня уже есть запу­щен­ный инстанс на нашем Dev-мониторинге:

Пере­за­пус­ка­ем, про­ве­ря­ем новый таргет:

root@monitoring-dev:/home/admin# systemctl restart prometheus
Добав­ля­ем гра­фи­ки в Grafana, используем:

Про­ве­ря­ем график:

Тестирование сети с iperf

Уста­нав­ли­ва­ем iperf на тесто­вой машине и на сер­ве­ре мониторинга:

root@monitoring-dev:/home/admin# apt -y install iperf

На тесто­вой машине запус­ка­ем iperf в режи­ме server (-s) – он будет при­ни­мать трафик:

root@ip-172-31-17-58:/home/ubuntu# iperf -s -w 2m
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size:  416 KByte (WARNING: requested 1.91 MByte)
------------------------------------------------------------
А на сер­ве­ре мони­то­рин­га – в режи­ме кли­ен­та, гоним тра­фик на тесто­вую маши­ну, запус­ка­ем на 1800 секунд:

Сна­ча­ла был спайк, потом ста­би­ли­зи­ро­ва­лось на 15 мегабайтах/секунду:

А кли­ент iperf на хосте мони­то­рин­га гово­рит нам:

[  3] 1718.0-1719.0 sec  14.6 MBytes   123 Mbits/sec
[  3] 1719.0-1720.0 sec  14.5 MBytes   122 Mbits/sec
[  3] 1720.0-1721.0 sec  14.6 MBytes   123 Mbits/sec
[  3] 1721.0-1722.0 sec  14.5 MBytes   122 Mbits/sec
[  3] 1722.0-1723.0 sec  14.6 MBytes   123 Mbits/sec
[  3] 1723.0-1724.0 sec  14.5 MBytes   122 Mbits/sec
[  3] 1724.0-1725.0 sec  14.5 MBytes   122 Mbits/sec
Пере­во­дим биты в бай­ты – и полу­ча­ем те же 15 MB/s:
echo 122/8 | bc
15

CloudWatch vs node_exporter

Теперь смот­рим в CloudWatch:

У нас есть:

  • 4.862.000.000 байт (Statistic – Sum)
  • пере­дан­ных за 5 минут (Period – 5 Minutes)

Что бы пере­ве­сти это в мегай­бай­ты в секун­ду – выполняем:

  • делим 4.862.000.000 на 300 – коли­че­ство секунд в 5 минутах
  • и резуль­тат делим на 1024 два раза – бай­ты в кило­бай­ты, потом в мегабайты

Что бы полу­чить биты в секун­ду – потом ещё раз умно­жа­ем на 8.

Счи­та­ем:

4862000000/300/1024/1024
15

Иско­мые 15 MByte/sec, или 120 Mbit/sec.

node_exporter и Docker Host Mode

И вто­рая инте­рес­ная шту­ка – поче­му node_exporter дол­жен запус­кать­ся в режи­ме сети host?

Для про­вер­ки – пере­за­пу­стим node_exporter, но убе­рём network_mode: host:

Повто­ря­ем тест с iperf, и видим… ничего:

72 байт/секунду, хотя iperf выда­ёт тот же резуль­тат в рай­оне ~120 мбит/сек.

node_exporter и netstat

Для нача­ла посмот­рим в доку­мен­та­цию node_exporter – как имен­но он сни­ма­ет дан­ные о сети?

netstat Exposes network statistics from /proc/net/netstat. This is the same information as netstat -s. Linux

Чита­ет содер­жи­мое /proc/net/netstat.

А чем у нас отли­ча­ет­ся Docker host mode от bridge mode? Чита­ем доку­мен­та­цию Docker:

container’s network stack is not isolated from the Docker host (the container shares the host’s networking namespace)

Ну и давай­те убе­дим­ся: запу­стим парал­лель­но два node_exporter – один в host mode, вто­рой – в bridge:

Нахо­дим Container ID:

Исполь­зуя CID 47b7fd130812 – кон­тей­нер с node_exporter в bridge mode – нахо­дим PID, с кото­рым он запу­щен на хосте:

root@ip-172-31-17-58:/home/ubuntu# docker inspect -f '{{.State.Pid}}' 47b7fd130812
4561

Исполь­зуя nsenter – через network namespace про­цес­са про­ве­ря­ем содер­жи­мое /proc/net/netstat:


Пусто.

Повто­ря­ем тоже самое для кон­тей­не­ра в режи­ме сети host – нахо­дим PID:

root@ip-172-31-17-58:/home/ubuntu# docker inspect -f '{{.State.Pid}}' daff8458e7bc
4505
И про­ве­ря­ем дан­ные в неймспейсе:

Повто­рим напря­мую на хост-машине:

Всё схо­дит­ся – кон­тей­нер в режи­ме host исполь­зу­ет дан­ные с хоста.