Learning Platform
Глоссарий Troubleshooting
Урок 17.02 · 25 мин
Средний
ObservabilityMonitoringSLOAlertsDashboardsCheckpoint

Observability checklist для production Flink

В предыдущем модуле мы видели, как включить Prometheus и какие метрики ключевые. Этот урок — про систему наблюдения как чек-лист: что должно быть настроено для каждого production Flink-джоба ДО того, как он попадёт в боевой контур. Без этого вы будете узнавать о проблемах от пользователей в Slack, а не от Prometheus alert-а.


Зачем нужен полноценный observability stack

В production Flink-джоб умирает не “потому что код плохой” — а потому что:

  1. Что-то медленно растёт (state, lag) и достигает порога.
  2. Что-то внешнее (Kafka, S3, downstream sink) на минуту замедляется.
  3. Deploy внёс регрессию, которая стала видна не сразу.

Без observability вы видите проблему постфактум, когда она уже стала критичной. С observability — заранее, ещё в фазе деградации, есть время отреагировать.

Полный observability stack для Flink покрывает 4 слоя:

Kubernetes observability: Prometheus operator, ServiceMonitor, Grafana
Observability layers
Слой 1: MetricsTime-series: checkpoint duration, throughput, lag, restart count. Prometheus + Grafana. Реактивный сигнал (что-то отклонилось от нормы).
Слой 2: LogsJSON-структурированные логи: WARN/ERROR от Flink, custom log от вашего кода. Loki / ELK для агрегации и поиска.
Слой 3: TracesОпционально для крупных систем: OpenTelemetry от Kafka до Flink до downstream. Видеть path события через распределённую систему.
Слой 4: AlertsРеакция на метрики и логи. PagerDuty / Slack. SLO-based alerts (не на симптомы, а на нарушение SLO).

Для большинства команд достаточно слоёв 1, 2 и 4 — Prometheus, Loki, alerts. Tracing — для зрелых стэков с микросервисной архитектурой.


Чек-лист: метрики, которые ДОЛЖНЫ быть на dashboard

Каждый production-джоб должен иметь dashboard, который за 30 секунд отвечает на вопрос: “всё ок или есть проблема?”.

Группа 1: Job health (наверху dashboard-а)

МетрикаЧто показываетАлерт
flink_jobmanager_job_uptimeСколько секунд джоб running< 60s для 1 мин = critical
flink_jobmanager_job_numRestartsCounter рестартовrate > 0 за 10 мин = warning
flink_jobmanager_numRegisteredTaskManagersСколько TM подключено< expected = warning

Visualize: stat-панели с current value, цвет (зелёный/жёлтый/красный).

Группа 2: Checkpoint health

МетрикаЧто показываетАлерт
flink_jobmanager_job_lastCheckpointDurationмс на последний checkpoint> 60s = warning
flink_jobmanager_job_lastCheckpointSizeбайтыgrowing > 1MB/час = warning
flink_jobmanager_job_numFailedCheckpointscounter упавшихrate > 0 = critical
flink_jobmanager_job_lastCheckpointRestoreTimestamptimestamp последнего successfulдля подсчёта lag между checkpoints

Visualize: time-series панели за последние 1h, 6h, 24h. Полезно overlay графика fail timestamps как vertical lines.

Группа 3: Backpressure heatmap

flink_taskmanager_job_task_backPressuredTimeMsPerSecond

Группировка по task_name. Visualize как heatmap: rows = операторы, columns = time, color = backpressure level. Сразу видно, какой оператор задыхается.

Алерт: > 500 ms/s на любом операторе 10+ минут.

Группа 4: Source lag (Kafka)

# Внешний экспортер kafka-exporter
kafka_consumergroup_lag{consumergroup=~"flink-.*"}

# Или встроенная Flink-метрика для KafkaSource
flink_taskmanager_job_task_operator_currentEmitEventTimeLag

Visualize: time-series, по partition. Если одна partition лагает сильно больше других — это data skew, не общая проблема.

Группа 5: Throughput

sum by (task_name) (
  flink_taskmanager_job_task_numRecordsOutPerSecond
)

Visualize: time-series per operator. Должно быть стабильно при стабильной нагрузке. Резкий drop — что-то изменилось.

Группа 6: Resource usage

# JM/TM heap usage
flink_jobmanager_Status_JVM_Memory_Heap_Used
flink_taskmanager_Status_JVM_Memory_Heap_Used

# CPU per TM container
container_cpu_usage_seconds_total{pod=~".*taskmanager.*"}

Если heap > 80% постоянно — пора увеличивать ресурсы.


Логи: структурированный JSON, не stack-trace dump

По умолчанию Flink логирует в plain text через log4j. В production переключите на JSON через log4j2 layout:

<!-- log4j2.xml в conf/ -->
<Configuration>
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <JsonLayout complete="false" compact="true" eventEol="true">
        <KeyValuePair key="service" value="flink" />
        <KeyValuePair key="job" value="${env:JOB_NAME}" />
      </JsonLayout>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="org.apache.flink" level="INFO" />
    <Root level="WARN">
      <AppenderRef ref="Console" />
    </Root>
  </Loggers>
</Configuration>

После этого каждая строка лога — JSON: {"timestamp":...,"level":"INFO","logger":"...","message":"...","service":"flink","job":"orders-pipeline"}.

Loki/ELK подхватывают такой формат, и можно искать:

{service="flink", job="orders-pipeline"} |= "checkpoint" | json | level="WARN"

Что обязательно логировать в WARN/ERROR

  • Checkpoint failures — Flink сам логирует, но добавьте контекст: какой job, какой operator failed.
  • Source/sink errors — Kafka connection lost, S3 throttle, JDBC timeout.
  • Watermark idle warnings — Flink логирует, когда source долго без watermark.
  • Custom business errors — например, неожиданная схема события, превышение лимита.

Что НЕ логировать

  • Каждое событие (миллион записей/сек × лог = терабайты).
  • Здоровые checkpoint завершения (это метрика).
  • Heartbeat-ы.

Логи — для аномалий. Метрики — для нормы.


Alerts: SLO-based, не симптом-based

Самая частая ошибка в alerting — алертить на каждый симптом. Backpressure высокий -> алерт. State growth -> алерт. Checkpoint duration высокий -> алерт. Через неделю в Slack 100 алертов в день, никто их не смотрит.

Лучший подход — SLO-based alerting. Определите Service Level Objective для каждого джоба (например, “99% времени lag меньше 5 минут”). Алертите только когда SLO нарушается.

# SLO: 99% времени Kafka lag должен быть < 1M записей
# Алерт если за 1 час реально SLO < 99%

- alert: FlinkOrdersSLOBreach
  expr: |
    (
      sum_over_time(
        (kafka_consumergroup_lag{consumergroup="flink-orders"} < 1000000)[1h:1m]
      )
      /
      60   # минут в часе
    ) < 0.99
  for: 0m
  labels:
    severity: critical
  annotations:
    summary: "Flink orders pipeline breached SLO (lag < 1M for 99% of time)"

Симптомы (high backpressure, growing state) — это warning в чате команды, не paging. Они интересны для дебага, но не для будильника.

Минимальный набор production alerts

# Critical (пейджит дежурного):
- FlinkJobNotRunning (uptime == 0 for 1m)
- FlinkSLOBreach (lag > threshold > 99% времени за час)
- FlinkCheckpointsFailing (rate of fails > 0 for 2m)
- FlinkTaskManagerOOM (OOMKilled containers)

# Warning (ticket в очередь):
- FlinkCheckpointDurationHigh (> 60s for 5m)
- FlinkBackpressureSustained (> 500ms/s for 30m)
- FlinkStateSizeGrowing (>1MB/час за 24h)
- FlinkRestartLoop (> 3 restarts in 10m)
- FlinkKafkaLagGrowing (rate of lag growth > 0 for 1h)

Critical = немедленная реакция. Warning = посмотреть на следующий рабочий день.


Runbook: что делать при каждом алерте

Алерт без runbook бесполезен. К каждому alert rule должна быть привязана внутренняя страница (Confluence / Notion / GitOps) с инструкцией:

# FlinkCheckpointsFailing

## Что это значит
Checkpoint-ы джоба <name> падают. Без работающих checkpoint-ов потеря recovery garanties.

## Шаги диагностики
1. Открыть Flink Web UI: <url>
2. Tab "Checkpoints" -> найти последний failed
3. Кликнуть для деталей -> видно операторы и причину
4. Самые частые причины:
   - S3 throttling -> "TimeoutException" в trace. Решение: уменьшить frequency или увеличить s3.upload.max.concurrent.uploads
   - Backpressure -> "Checkpoint declined" в operator. Решение: включить unaligned checkpoints
   - OOM TaskManager -> "Connection lost" в trace. Решение: увеличить memory TM
5. kubectl logs jobmanager-pod-name | grep -i checkpoint | tail -50

## Когда эскалировать
- Failure rate > 50% за 30 минут -> page on-call (sev1)
- Otherwise -> внутренняя коммуникация в #flink-team, разбираться workday

Команды без runbook теряют часы при каждом алерте — каждый раз разбираясь с нуля.


Dashboards: 3 уровня

Делайте 3 уровня dashboards:

Уровень 1: Executive overview (для PM / SRE manager-ов)

  • Список всех джобов
  • Цветной статус (зелёный/жёлтый/красный) по SLO
  • Total throughput всех джобов
  • Total state size в кластере

Уровень 2: Job dashboard (для on-call инженера)

  • 6 групп метрик из чек-листа выше
  • Текущие алерты для этого джоба
  • Last 24h trend

Уровень 3: Deep dive (для дебага)

  • Per-operator metrics
  • RocksDB internals (если используется)
  • JVM GC, heap detail
  • Network I/O per TM

Большинство времени инженер смотрит на уровень 2. Уровень 3 — только при инциденте, поэтому может быть менее polished.


Tracing: когда нужно (опционально)

Для большинства Flink-джобов tracing избыточен. Метрики и логи покрывают 95% дебаг-нужд. Tracing полезен если:

  • У вас множество источников (Kafka + REST API + DB lookup), и нужно понять, где задержка в каждом конкретном event.
  • Downstream системы тоже трэйсятся, и нужна end-to-end видимость.
  • Бизнес-критичные транзакции с SLA-требованием по latency.

Setup: OpenTelemetry Java agent в Flink-образе, экспорт в Jaeger / Tempo. Trace context propagation через Kafka headers и REST headers.

# В Dockerfile Flink
ENV JAVA_TOOL_OPTIONS="-javaagent:/opt/opentelemetry-javaagent.jar"
ENV OTEL_SERVICE_NAME=flink-orders
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4318

Это не маленький проект. Делайте только если есть конкретная боль, которую tracing решит.


Чек-лист перед деплоем в production

Конкретный чек-лист, который нужно пройти ДО первого production-deploy джоба:

  • PrometheusServiceMonitor / scrape config в кластере подхватывает метрики Flink.
  • Dashboard в Grafana создан (хотя бы из 14911 template).
  • PrometheusRule с 8 базовыми alerts задеплоен.
  • Алерты идут в правильный канал (Slack для warnings, PagerDuty для critical).
  • Runbook для каждого алерта написан и доступен через annotation runbook_url.
  • Логи структурированы в JSON, агрегируются в Loki/ELK.
  • SLO определён, alert на breach настроен.
  • dashboard URL в README репозитория джоба.
  • on-call rotation знает про этот джоб (added to PagerDuty service).

Без этого чек-листа джоб запущенный в проде — это запуск без приборной панели.


Ключевые выводы

  1. Observability — 4 слоя: metrics (Prometheus), logs (Loki), alerts, опционально traces. Для большинства Flink-команд хватает первых трёх.

  2. 6 групп метрик на dashboard: job health, checkpoint, backpressure (heatmap), source lag, throughput, resources.

  3. Логи — JSON через log4j2 layout, агрегируются в Loki. Логировать аномалии, не нормальную работу.

  4. SLO-based alerts вместо симптом-based: алертить когда нарушается бизнес-обещание, не каждый раз когда что-то отклонилось.

  5. Минимум 4 critical + 5 warning alerts покрывает 90% production-нужд.

  6. Runbook для каждого алерта — без него инженер заново разбирается каждый раз.

  7. 3 уровня dashboard-ов: executive overview, job dashboard, deep dive. On-call смотрит на уровень 2 чаще всего.

  8. Чек-лист перед production-деплоем обеспечивает, что джоб не уйдёт в прод без приборной панели.

Проверка знанийKnowledge check
У вас на проде 12 Flink-джобов с SLA 99.9% по uptime, общий on-call ротации. Команда жалуется: "слишком много алертов в Slack, перестали обращать внимание". Что не так с alerting и как переделать?
ОтветAnswer
Это классический симптом alert fatigue. Главная причина - симптом-based вместо SLO-based alerting. Что не так: 1. Алерты на симптомы (backpressure, checkpoint duration, state growth) - они срабатывают часто, но не всегда означают реальную проблему для бизнеса. Например, backpressure 30 минут в неделю при regular high-load - норма, не алерт. 2. Все алерты в один канал - смешаны warnings и criticals. 3. Возможно нет runbook-ов - инженер на 5-ом алерте за день перестаёт даже открывать. 4. Возможно нет severity-fan-out: всё критично = ничего не критично. Переделать: 1. Определить SLO для каждого джоба: - 99.9% времени lag меньше threshold - 99.9% времени checkpoint duration меньше threshold - Uptime 99.95% (примерно 4 часа downtime в год) 2. Алерты разделить: - SLO breach alerts -> PagerDuty (critical, page on-call). За 30 дней может быть 0-2 paging-а на джоб - это терпимо. - Симптомы (backpressure high, state growing, checkpoint slow) -> Slack thread в команд-канал, без paging. Это для дебага, не для будильника. 3. К каждому critical alert привязать runbook URL в annotation. Инженер при пейджинге сразу открывает runbook, не разбирается с нуля. 4. Burn rate alerts для SLO: алертить, когда SLO сгорает быстро (например, 14.4x normal burn rate = error budget сгорит за 2 дня). Это даёт время отреагировать, не дожидаясь нарушения. 5. Tooling: - Прометей рекомендуемые правила: https://sre.google/workbook/alerting-on-slos/ - Alertmanager grouping/silencing/inhibit rules для подавления связанных алертов (например, если JobNotRunning - не алертить SLOBreach для того же джоба). 6. Periodic review: раз в квартал смотреть, какие алерты срабатывали без actionable response. Удалять или повышать threshold. Ожидаемый результат: 1-3 critical alerts в неделю на on-call вместо 10/день. Команда снова доверяет алертам.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Команда оборудовала Flink-кластер alerts: на каждый раз когда backpressure > 200 ms/s, checkpoint duration > 30s, lag > 100k - алерт в Slack. Через 2 недели команда жалуется, что 'не обращают внимания на алерты'. Что не так и как переделать?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5