Начал обновлять дашборды в 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
:
--- version: '3.8' services: node_exporter: image: quay.io/prometheus/node-exporter:latest container_name: node_exporter command: - '--path.rootfs=/host' network_mode: host pid: host restart: unless-stopped volumes: - '/:/host:ro,rslave'
Запускаем:
Проверяем, есть ли данные:
Подключение Prometheus и Grafana
Добавляем его в Prometehus – тут у меня уже есть запущенный инстанс на нашем Dev-мониторинге:
... - job_name: 'node-exporter' metrics_path: '/metrics' static_configs: - targets: - '18.117.88.151:9100' # test node ... metric_relabel_configs: # test node - source_labels: [instance] regex: '18.117.88.151:9100' target_label: host replacement: 'test-node-exporter' ...
Перезапускаем, проверяем новый таргет:

Добавляем графики в Grafana, используем:
rate(node_network_receive_bytes_total{host="test-node-exporter", device="eth0"}[5m]) rate(node_network_transmit_bytes_total{host="test-node-exporter", device="eth0"}[5m]) rate(node_network_receive_packets_total{host="test-node-exporter", device="eth0"}[5m]) rate(node_network_transmit_packets_total{host="test-node-exporter", device="eth0"}[5m])
Проверяем график:
Тестирование сети с iperf
Устанавливаем iperf
на тестовой машине и на сервере мониторинга:
На тестовой машине запускаем iperf
в режиме server (-s
) – он будет принимать трафик:
А на сервере мониторинга – в режиме клиента, гоним трафик на тестовую машину, запускаем на 1800 секунд:
Сначала был спайк, потом стабилизировалось на 15 мегабайтах/секунду:
А клиент iperf
на хосте мониторинга говорит нам:
Переводим биты в байты – и получаем те же 15 MB/s:
CloudWatch vs node_exporter
Теперь смотрим в CloudWatch:
У нас есть:
- 4.862.000.000 байт (Statistic – Sum)
- переданных за 5 минут (Period – 5 Minutes)
Что бы перевести это в мегайбайты в секунду – выполняем:
- делим 4.862.000.000 на 300 – количество секунд в 5 минутах
- и результат делим на 1024 два раза – байты в килобайты, потом в мегабайты
Что бы получить биты в секунду – потом ещё раз умножаем на 8.
Считаем:
Искомые 15 MByte/sec, или 120 Mbit/sec.
node_exporter
и Docker Host Mode
И вторая интересная штука – почему node_exporter
должен запускаться в режиме сети host?
Для проверки – перезапустим node_exporter
, но уберём network_mode: host
:
--- version: '3.8' services: node_exporter: image: quay.io/prometheus/node-exporter:latest container_name: node_exporter command: - '--path.rootfs=/host' pid: host restart: unless-stopped volumes: - '/:/host:ro,rslave'
Повторяем тест с 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:
--- version: '3.8' services: node_exporter_1: image: quay.io/prometheus/node-exporter:latest container_name: node_exporter_host command: - '--path.rootfs=/host' network_mode: host pid: host restart: unless-stopped volumes: - '/:/host:ro,rslave' node_exporter_2: image: quay.io/prometheus/node-exporter:latest container_name: node_exporter_bridge command: - '--path.rootfs=/host' pid: host restart: unless-stopped volumes: - '/:/host:ro,rslave'
Находим Container ID:
Используя CID 47b7fd130812 – контейнер с node_exporter
в bridge mode – находим PID, с которым он запущен на хосте:
Используя nsenter
– через network namespace процесса проверяем содержимое /proc/net/netstat
:
Пусто.
Повторяем тоже самое для контейнера в режиме сети host – находим PID:
И проверяем данные в неймспейсе:
Повторим напрямую на хост-машине:
Всё сходится – контейнер в режиме host использует данные с хоста.