feat(monitoring): экспортер метрик по контейнерам поверх Docker Engine API
Разбивка по контейнерам (CPU/память/сеть) — то, что не смог дать
cAdvisor из-за несовместимости с containerd-снапшоттером сервера 1gb
(убран в 7f5c888). Свой минимальный сервис container-exporter (Python/
aiohttp/prometheus_client) опрашивает Docker Engine API параллельно в
фоновой задаче, не завязываясь на scrape-интервал Prometheus.
Доступ к докер-сокету изолирован через docker-socket-proxy: экспортеру
разрешены только GET /containers/json и /containers/*/stats, любые
изменяющие запросы блокируются на уровне прокси (POST=0) — полная
компрометация экспортера не даёт управлять Docker. Ни один из двух
сервисов не публикует портов наружу.
В host.json возвращены панели «Топ контейнеров по CPU/памяти» на новых
метриках vidconf_container_* (в 0.0.9 их убрали вместе с cAdvisor).
This commit is contained in:
@@ -734,17 +734,60 @@ services:
|
||||
profiles: ["monitoring"]
|
||||
logging: *default-logging
|
||||
|
||||
# cAdvisor сознательно НЕ используется: несовместим с Docker Engine на
|
||||
# сервере `1gb` (containerd-снапшоттер вместо классического overlay2 —
|
||||
# `docker info` показывает `driver-type: io.containerd.snapshotter.v1`).
|
||||
# cAdvisor (проверено на v0.49.2 и v0.52.1) не может определить
|
||||
# read-write layer контейнеров через ни docker.sock, ни напрямую через
|
||||
# `--containerd`/`--containerd-namespace=moby` — падает с
|
||||
# «failed to identify the read-write layer ID», отдаёт метрики только по
|
||||
# корневому cgroup, без разбивки по контейнерам. Открытая проблема
|
||||
# совместимости cAdvisor с containerd image store, не чинится флагами —
|
||||
# см. `.forcc/JOURNAL.md` за детали и альтернативы. node-exporter
|
||||
# (сервис выше) метрики хоста при этом покрывает полностью.
|
||||
# Метрики по контейнерам (CPU/память/сеть каждого отдельно) — замена
|
||||
# cAdvisor, который на сервере `1gb` несовместим с Docker Engine
|
||||
# (containerd-снапшоттер вместо classic overlay2 — подробности и
|
||||
# перепробованные варианты см. `.forcc/JOURNAL.md`, раздел релиза 0.0.9).
|
||||
# Вместо интроспекции graph-driver'а — Docker Engine API напрямую
|
||||
# (`GET /containers/json` + `/stats`), он не зависит от storage-driver.
|
||||
#
|
||||
# Доступ к докер-сокету равносилен root на хосте (`:ro` при монтировании
|
||||
# ограничивает права на файл-ноду, а не на протокол — через сокет можно
|
||||
# поднять привилегированный контейнер и получить хост). Поэтому сокет
|
||||
# монтируется СЮДА, в доверенный прокси-образ, а НЕ в наш собственный
|
||||
# `container-exporter` ниже — прокси разрешает ему только
|
||||
# `GET /containers/json` и `GET /containers/*/stats` (`CONTAINERS=1`),
|
||||
# любые изменяющие запросы заблокированы (`POST=0`). Полная компрометация
|
||||
# `container-exporter` не даёт управлять Docker. Обоснование и разбор —
|
||||
# `docs/deploy/monitoring.md`.
|
||||
docker-socket-proxy:
|
||||
image: tecnativa/docker-socket-proxy:v0.5.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
CONTAINERS: 1
|
||||
# POST=0 — дефолт образа; выписан явно, потому что от него зависит
|
||||
# безопасность всей схемы (полагаться на невыписанный дефолт для
|
||||
# критичного флага не стоит).
|
||||
POST: 0
|
||||
EVENTS: 0
|
||||
# Не публикуем порт наружу вообще — container-exporter достаёт API
|
||||
# по имени сервиса во внутренней сети compose, тот же принцип, что и
|
||||
# у node-exporter/postgres-exporter выше.
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1:2375/_ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 10s
|
||||
profiles: ["monitoring"]
|
||||
logging: *default-logging
|
||||
|
||||
container-exporter:
|
||||
build:
|
||||
context: ./monitoring/container-exporter
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DOCKER_API_BASE: "http://docker-socket-proxy:2375"
|
||||
depends_on:
|
||||
docker-socket-proxy:
|
||||
condition: service_healthy
|
||||
# Без ports — тот же принцип, что и у прокси выше; healthcheck
|
||||
# прописан в самом Dockerfile экспортера (как у backend/worker).
|
||||
profiles: ["monitoring"]
|
||||
logging: *default-logging
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:13.1.0
|
||||
|
||||
Reference in New Issue
Block a user