4. Мониторинг инфраструктуры
Четыре золотых сигнала, Prometheus, cAdvisor и метрики Go-рантайма
В предыдущих главах мы детально настраивали деплой, горизонтальное масштабирование и сетевую маршрутизацию. Однако слепая вера в то, что развернутый кластер работает идеально только потому, что HTTP-запросы возвращают код 200, — самый короткий путь к ночным дежурствам и катастрофическим инцидентам в продакшене.
Мониторинг инфраструктуры — это не просто набор красочных графиков в Grafana для успокоения менеджмента. Это Mechanical Sympathy (механическое сочувствие к машине) в чистом инженерном выражении: способность видеть сквозь абстракции контейнеризации и понимать, как ядро Linux, подсистема Cgroups, планировщик Kubernetes и рантайм Go делят между собой физические такты процессора, страницы оперативной памяти и очереди дисковых накопителей.
1. Концепция: The Four Golden Signals
Прежде чем бросаться собирать терабайты метрик, необходимо определить метрический фундамент. В классической библии надежности Google SRE Book сформулирована концепция четырех золотых сигналов (The Four Golden Signals), позволяющая мгновенно оценить состояние любой распределенной системы:
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph GoldenSignals["The Four Golden Signals (Google SRE)"]
L["1. Latency (Задержка)\nВремя обслуживания запроса.\nВажно отделять латентность успехов от задержек медленных ошибок!"]
T["2. Traffic (Трафик)\nМера входящей нагрузки:\nRPS (Requests Per Second) для HTTP, MPS для брокеров и gRPC."]
E["3. Errors (Ошибки)\nЧастота сбоев: явные HTTP 500/502/504\nили неявные 'тихие' бизнес-ошибки."]
S["4. Saturation (Насыщение)\nСтепень исчерпания ресурсов:\nCPU throttle, RAM, сокеты, пулы коннектов к БД."]
end
- Latency (Задержка): Время, затраченное на обработку запроса. Инженеры часто совершают ошибку, усредняя латентность. Важно измерять перцентили (p95, p99) и строго разделять задержку успешных ответов и задержку ошибок. Медленно падающий с таймаутом запрос гораздо опаснее быстрого ответа
500 Internal Server Error. - Traffic (Трафик): Количественная мера спроса на систему. Для HTTP-бэкенда это RPS (Requests Per Second), для gRPC или брокеров очередей — MPS (Messages Per Second) или байты в секунду.
- Errors (Ошибки): Интенсивность отказов. Сюда входят как явные системные ошибки (HTTP 500/502/503/504, сетевые сбросы соединений), так и коварные неявные сбои (когда сервис возвращает статус
200 OK, но с пустым или битым JSON внутри). - Saturation (Насыщение): Насколько система близка к своему физическому пределу (утилизация очередей ядра, пула потоков, памяти, дискового IO). Насыщение предсказывает проблемы задолго до того, как они ударят по Latency и вызовут Errors.
2. Архитектура наблюдаемости в Kubernetes: Трехуровневый пирог
Невозможно поставить один универсальный агент и собрать исчерпывающую телеметрию. Мониторинг кластера Kubernetes строится как многослойный пирог из трех независимых источников данных:
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph Host["Физический сервер / Worker Node"]
NE["Node Exporter\n(Метрики ядра Linux: /proc, /sys)"]
cAdv["cAdvisor (внутри Kubelet)\n(Метрики Cgroups контейнеров)"]
GoPod["Go Application Pod\n(/metrics endpoint)"]
end
subgraph ControlPlane["Kubernetes Control Plane"]
KSM["Kube-state-metrics\n(Состояние объектов: Pods, Deployments, PVC)"]
end
subgraph MonitoringStack["Подсистема мониторинга"]
Prom["Prometheus Server\n(Pull-модель: HTTP Scrape каждые 15с)"]
Grafana["Grafana Дашборды"]:::process
Alert["Alertmanager (Алерты в Slack / PagerDuty)"]
Prom --> Grafana
Prom --> Alert
end
NE -->|"Scrape :9100"| Prom
cAdv -->|"Scrape :10250"| Prom
GoPod -->|"Scrape :2112"| Prom
KSM -->|"Scrape :8080"| Prom
Каждый слой решает строго определенную задачу и смотрит на мир под своим углом.
3. Слой 1: Нода (Node Exporter)
Node Exporter — это специализированный демон (DaemonSet в K8s), написанный на Go. Он ничего не знает о концепциях Kubernetes, подах или контейнерах. Его цель — раскрыть физическое состояние операционной системы Linux и аппаратного сервера.
Node Exporter добывает метрики путем прямого парсинга псевдо-файловых систем ядра:
/proc/stat— тики процессорного времени, прерывания (interrupts), переключения контекста (context switches)./proc/meminfo— детальная раскладка RAM: анонимная память, Swap, Page Cache, буферы и slabs ядра./sys/class/block/— глубина дисковых очередей, время операций чтения/записи (IOPS, iostat)./proc/net/dev— сетевой трафик, отброшенные пакеты (drops), ошибки контроллера (errors).
Mechanical Sympathy: Анализ iowait и steal
При исследовании метрик процессора опытный инженер смотрит глубже базовых процентов user и system:
iowait: Процент процессорного времени, в течение которого ядра бездействовали в ожидании ответа от медленных накопителей (SSD/HDD). Высокийiowaitсигнализирует, что потоки Go-приложения заблокированы в ядре на блокирующих системных вызовахread/write(как мы выяснили в 3. Файловая система Linux), и рантайм вынужден создавать новые потокиM.steal: Процент процессорных квантов времени, физически «украденных» гипервизором облачного провайдера в пользу других виртуальных машин. Если метрикаstealпревышает 3–5%, ваш сервис страдает от проблемы шумных соседей (Noisy Neighbors). Единственное решение — миграция виртуальной машины или аренда Dedicated/Bare-metal инстансов.
4. Слой 2: Контейнер (cAdvisor)
Откуда Kubernetes узнает, сколько памяти или процессора потребил конкретный Docker-контейнер? Он опрашивает контроллер cAdvisor (Container Advisor), встроенный прямо в демон kubelet. cAdvisor также написан на Go и считывает сырые данные из виртуальной файловой системы Cgroups (/sys/fs/cgroup).
flowchart LR
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
Cgroup["/sys/fs/cgroup/cpu,memory\n(Ядро Linux)"]:::system --> cAdv["cAdvisor (Go daemon)"]
cAdv -->|"Prometheus Format"| Kubelet["Kubelet API (:10250/metrics/cadvisor)"]
Kubelet --> Prom["Prometheus Server"]
5. Слой 3: Объекты Kubernetes (Kube-state-metrics)
Демон Kube-state-metrics не измеряет байты и герцы. Он подключается к K8s API Server через библиотеку client-go и транслирует в метрики Prometheus само декларативное состояние объектов кластера:
- Запрошенное количество реплик Deployment против реально доступных (
kube_deployment_status_replicas_available). - Поды, застрявшие в циклах перезапусков (
CrashLoopBackOffилиOOMKilled). - Дисковые тома PersistentVolumeClaim, зависшие в статусе
Pending. - Статус готовности нод кластера (
kube_node_status_condition).
6. Prometheus: Архитектура Pull-модели и Service Discovery
Индустриальным стандартом сбора метрик в облачной инфраструктуре является Prometheus. В отличие от классических систем с Push-моделью (StatsD, Graphite, Datadog), где приложения сами обязаны отправлять метрики на центральный сервер, Prometheus реализует Pull-модель (Scrape): он сам периодически приходит по HTTP на порт каждого инстанса.
Почему Pull-модель идеальна для инфраструктуры?
- Надежное обнаружение отказов (Deadlock Detection): В push-системе, если Go-приложение намертво зависло в дедлоке или упало вместе с нодой, оно просто перестает слать пакеты. Push-сервер видит пустоту и считает: «Нет ошибок — значит, всё спокойно». Prometheus же при очередном опросе не получает HTTP 200 и немедленно генерирует системный алерт
TargetDown. - Динамический Service Discovery: Prometheus тесно интегрирован с API Kubernetes. Ему не нужно прописывать статические IP-адреса: он автоматически обнаруживает новые поды по аннотациям (например,
prometheus.io/scrape: "true") и меткам селекторов, удаляя исчезнувшие инстансы из списка опроса.
7. Интеграция Go: Метрики рантайма под микроскопом
Официальный SDK github.com/prometheus/client_golang при вызове стандартного хэндлера promhttp.Handler() автоматически подключает коллектор collectors.NewGoCollector(). Он раскрывает глубокие внутренности среды исполнения Go без написания единой строчки прикладного кода!
package main
import (
"log"
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// Стандартный эндпоинт, отдающий метрики рантайма Go и кастомные метрики
http.Handle("/metrics", promhttp.Handler())
log.Println("Сервер метрик Prometheus слушает на порту :2112...")
if err := http.ListenAndServe(":2112", nil); err != nil {
log.Fatalf("ошибка запуска метрик: %v", err)
}
}
Критически важные runtime-метрики Go:
go_goroutines: Текущее количество активных горутин в памяти. Рост графика горутин при стабильном входящем RPS — классический симптом утечки горутин (goroutine leak), зависших на незакрытых каналах или сокетах.go_gc_duration_seconds: Гистограмма длительности фаз сборки мусора (Stop-The-World и Concurrent phases). Всплески длительности сигнализируют о сильной фрагментации кучи или нехватке памяти.go_memstats_heap_inuse_bytes: Объем оперативной памяти, занятый живыми объектами в куче. В здоровом сервисе график имеет строгий пилообразный вид (рост аллокаций сменяется резким обрывом после прохода GC). Монотонный непрерывный рост без падений — стопроцентный признак утечки памяти (Memory Leak).
Резюме
- Four Golden Signals: Дашборды и системы оповещения должны строиться вокруг задержки (Latency), нагрузки (Traffic), сбоев (Errors) и степени насыщения (Saturation).
- Node Exporter: Читает
/procи/sys. Следите за количеством переключений контекста (context switches), блокировками на диске (iowait) и украденными тактами гипервизора (steal). - cAdvisor: Извлекает метрики Cgroups. Рост
container_cpu_cfs_throttled_periods_totalуказывает на опасный троттлинг процессора ядром Linux. - Kube-state-metrics: Мониторит жизненный цикл и расхождения между желаемым и реальным состоянием кластера K8s (
CrashLoopBackOff,Pending). - Pull-модель Prometheus: Позволяет обнаруживать зависшие сервисы с помощью алертов
TargetDownи обеспечивает нативный Service Discovery подов. - Go Runtime: Автоматический коллектор
collectors.NewGoCollector()дает прозрачный контроль за утечками горутин (go_goroutines), здоровьем сборщика мусора (go_gc_duration_seconds) и размером кучи.
Метрики дают точный ответ на вопросы: «Где сломалось?» и «Когда сломалось?». Однако они бессильны объяснить глубинную причину: «Что именно произошло?». Чтобы восстановить детальный контекст инцидента, необходима вторая опора наблюдаемости — централизованное логирование. В следующей главе мы разберем сбор логов инфраструктуры: 5. Логи инфраструктуры.