Контейнер запущен — не значит, что приложение работает. Может быть дедлок, переполнение памяти или медленная инициализация. 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)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!