📝 Kubernetes

Health Checks: liveness и readiness в Kubernetes

P
Автор
Pyland
📅
Опубликовано
30.06.2026
⏱️
Время чтения
3 мин
👁️
Просмотров
98
🌳
Уровень
Продвинутый
🐦 💼 ✈️

Контейнер запущен — не значит, что приложение работает. Может быть дедлок, переполнение памяти или медленная инициализация. Probes — механизм K8s для проверки здоровья приложения.

Зачем нужны probes

Без probes K8s считает Pod живым, пока процесс внутри не завершится. Проблема:

  • Приложение запущено, но не отвечает на запросы (дедлок, зависание)
  • Приложение ещё не готово принимать трафик (загружает данные, устанавливает соединения)
  • Приложение медленно стартует и K8s убивает его, не дождавшись

Три типа probes решают три разные задачи.

livenessProbe: перезапустить если умер

liveness проверяет: «Приложение живо?» Если проверка упала N раз подряд — K8s перезапускает контейнер.

Используй когда: приложение может зависнуть (дедлок, бесконечный цикл) и нужен автоматический рестарт.

readinessProbe: не слать трафик если не готов

readiness проверяет: «Приложение готово принимать запросы?» Если нет — Pod убирается из балансировки Service, трафик не идёт.

Pod остаётся Running, но не получает трафик. Как только проверка пройдёт — возвращается в ротацию.

Используй когда: приложение инициализируется (подключение к БД, прогрев кэша, загрузка конфигов).

startupProbe: для медленного запуска

startup даёт приложению время на инициализацию. Пока startupProbe не пройдёт, liveness и readiness не запускаются. После успеха — startupProbe отключается.

Используй когда: приложение долго стартует (legacy-системы, JVM, большие ML-модели).

Три типа проверок

HTTP проверка (наиболее распространена)

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
    httpHeaders:
      - name: X-Health-Check
        value: "true"
  initialDelaySeconds: 10
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3
  successThreshold: 1

K8s отправляет GET-запрос на /healthz. HTTP 2xx/3xx = успех, остальное = провал.

TCP проверка

livenessProbe:
  tcpSocket:
    port: 5432
  initialDelaySeconds: 15
  periodSeconds: 10

Проверяет, что порт принимает TCP-соединения. Удобно для баз данных и других non-HTTP сервисов.

Exec проверка (команда в контейнере)

livenessProbe:
  exec:
    command:
      - sh
      - -c
      - "redis-cli ping | grep -q PONG"
  initialDelaySeconds: 10
  periodSeconds: 5

Выполняет команду внутри контейнера. Exit code 0 = успех.

Параметры probes

Параметр Значение По умолчанию
initialDelaySeconds Ждать N секунд после старта контейнера 0
periodSeconds Как часто проверять 10
timeoutSeconds Таймаут одной проверки 1
failureThreshold Сколько провалов подряд считать критичным 3
successThreshold Сколько успехов нужно для recovery 1

Практический пример: FastAPI приложение

# main.py — эндпоинты для health checks
from fastapi import FastAPI
import asyncpg
import os

app = FastAPI()
db_pool = None

@app.on_event("startup")
async def startup():
    global db_pool
    db_pool = await asyncpg.create_pool(os.getenv("DATABASE_URL"))

@app.get("/healthz")
async def liveness():
    """Приложение живо — процесс работает"""
    return {"status": "ok"}

@app.get("/readyz")
async def readiness():
    """Приложение готово — БД подключена"""
    try:
        async with db_pool.acquire() as conn:
            await conn.fetchval("SELECT 1")
        return {"status": "ready"}
    except Exception:
        from fastapi import HTTPException
        raise HTTPException(status_code=503, detail="Database unavailable")
# deployment-with-probes.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: fastapi-app
  template:
    metadata:
      labels:
        app: fastapi-app
    spec:
      containers:
        - name: app
          image: fastapi-app:1.0
          ports:
            - containerPort: 8000
          resources:
            requests:
              cpu: "200m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"

          # Даём время на подключение к БД
          startupProbe:
            httpGet:
              path: /readyz
              port: 8000
            failureThreshold: 30    # 30 * 5s = 150 секунд максимум
            periodSeconds: 5

          # Проверяем, что приложение живо
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8000
            initialDelaySeconds: 0
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 3

          # Проверяем готовность принимать трафик
          readinessProbe:
            httpGet:
              path: /readyz
              port: 8000
            initialDelaySeconds: 0
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
            successThreshold: 1

Пример для nginx и PostgreSQL

# nginx: liveness через TCP
livenessProbe:
  tcpSocket:
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 5
# PostgreSQL: проверка через pg_isready
livenessProbe:
  exec:
    command:
      - pg_isready
      - -U
      - postgres
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 6

readinessProbe:
  exec:
    command:
      - pg_isready
      - -U
      - postgres
  initialDelaySeconds: 5
  periodSeconds: 5
  timeoutSeconds: 3

Отладка проблем с probes

# Посмотреть события пода (причины рестартов)
kubectl describe pod my-app-abc123
# Events:
#   Warning  Unhealthy  Liveness probe failed: HTTP probe failed...
#   Warning  BackOff    Back-off restarting failed container

# Количество рестартов
kubectl get pods
# NAME              READY   STATUS    RESTARTS   AGE
# my-app-abc123     0/1     Running   5          10m  ← проблема

# Логи предыдущего (упавшего) контейнера
kubectl logs my-app-abc123 --previous

Типичные ошибки:

  • initialDelaySeconds слишком мал — probe запускается до готовности приложения
  • timeoutSeconds слишком мал — медленный эндпоинт не успевает ответить
  • liveness и readiness на один и тот же медленный эндпоинт — K8s убивает нагруженный под
  • Нет startupProbe для медленного приложения — liveness убивает его при старте

Ваша реакция на статью

💬 Комментарии (0)

🔐 Войдите в систему, чтобы оставить комментарий
🚪 Войти
💭

Комментариев пока нет

Станьте первым, кто поделится мнением об этой статье!

🔗 Похожие

Похожие статьи

Продолжите изучение с этими материалами

📝

Resource Limits и Requests в Kubernetes

Без ограничений ресурсов один «жадный» контейнер может съесть всю память узла и убить остальные поды....

📅 30.06.2026 👁️ 83
📝

Что такое Kubernetes и зачем он нужен

Docker упакует приложение в контейнер. Но что делать, когда контейнеров сотни, они падают, нагрузка скачет,...

📅 30.06.2026 👁️ 90
📝

ConfigMap и Secret: конфигурация в Kubernetes

Конфигурация не должна быть зашита в Docker-образ. Разные окружения (dev, staging, production) требуют разных значений....

📅 30.06.2026 👁️ 93

Понравилась статья?

Подпишитесь на наши обновления и получайте новые статьи первыми. Развивайтесь вместе с PyLand!