Salud y Preparación
Los puntos finales de salud indican a los orquestadores si un proceso Python está activo (liveness) y si puede aceptar tráfico (readiness). Divídelos para que los picos de dependencia drenen el tráfico sin reiniciar los pods.
Receta
from fastapi import FastAPI, Response, status
app = FastAPI()
@app.get("/health/live")
def live():
return {"status": "ok"}
@app.get("/health/ready")
def ready():
if not db_ping():
return Response(content='{"status":"down"}', status_code=503, media_type="application/json")
return {"status": "ok"}Cuándo usar esto:
- Comprobaciones de salud del balanceador de carga de Kubernetes/ECS.
- Despliegues continuos que dirigen el tráfico solo a pods listos.
- Fallos de dependencia que eliminan temporalmente la instancia de la rotación.
- Monitorización sintética comprobaciones externas de tiempo de actividad (generalmente solo
/health/livepúblico).
Ejemplo de Trabajo
Preparación de FastAPI con verificación de base de datos limitada por tiempo de espera e inicialización perezosa compatible con la sonda de inicio.
import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI, Response, status
class HealthState:
def __init__(self) -> None:
self.db_ready = False
async def check_db(self) -> bool:
try:
await asyncio.wait_for(fake_db_ping(), timeout=0.5)
self.db_ready = True
return True
except Exception:
self.db_ready = False
return False
async def fake_db_ping() -> None:
await asyncio.sleep(0.01)
state = HealthState()
@asynccontextmanager
async def lifespan(app: FastAPI):
await state.check_db()
yield
app = FastAPI(lifespan=lifespan)
@app.get("/health/live")
async def live():
return {"status": "ok"}
@app.get("/health/ready")
async def ready():
ok = await state.check_db()
body = {"status": "ok" if ok else "degraded", "db": ok}
if not ok:
return Response(content=str(body), status_code=status.HTTP_503_SERVICE_UNAVAILABLE)
return bodyLo que esto demuestra:
- Liveness siempre 200 si el bucle de eventos se ejecuta.
- Readiness devuelve 503 cuando falla la comprobación de la base de datos; el balanceador de carga deja de enrutar.
- Tiempo de espera corto en la comprobación de dependencias para evitar sondas colgadas.
Análisis Profundo
Mapeo de Sondas
| Punto final | Sonda K8s | Falla cuando |
|---|---|---|
/health/live | liveness | interbloqueo (raro) |
/health/ready | readiness | dependencias no disponibles |
/health/startup | startup | inicialización lenta |
Alcance de la Comprobación
- Readiness: pool de base de datos, caché, indicadores de funciones requeridos cargados.
- Liveness: evitar llamadas externas; el reinicio de kubelet es costoso.
Notas de Python
startupProbe:
httpGet:
path: /health/ready
port: 8000
failureThreshold: 30
periodSeconds: 10Errores Comunes
- Comprobación de DB en liveness: la interrupción de la DB mata todos los pods. Solución: readiness solo para dependencias.
- Readiness lenta siempre: el despliegue nunca termina. Solución: startupProbe para inicialización lenta, readiness rápida después.
- Readiness fluctuante: estampida de rebaño en la recuperación de la DB. Solución: histéresis o resultado de comprobación en caché corto (TTL de 1-2 s).
- Readiness pública expone internos: fuga de información
{"db": false}. Solución: cuerpo genérico externamente, detalles en logs/métricas. - Salud en puerto incorrecto: la sonda golpea el puerto de métricas. Solución: documentar el puerto de la aplicación 8000 en Deployment.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
| Sonda de socket TCP | Servicio no HTTP | Aplicaciones HTTP de FastAPI/Django |
| Sonda Exec | Comprobación de script personalizado | Simple HTTP suficiente |
| Salud de Mesh | Istio/Linkerd | Servicio K8s simple |
Preguntas Frecuentes
¿Un punto final o dos?
Mínimo dos rutas para la semántica de liveness frente a readiness; los operadores y la documentación de K8s asumen la división.
¿Debería readiness comprobar S3?
Solo si cada solicitud requiere S3; de lo contrario, la dependencia opcional pertenece a un indicador de función degradado, no a un 503.
¿Salud de Django?
Aplicación django-health-check o vista ligera que consulta la conexión de base de datos predeterminada.
¿Qué código HTTP?
200 listo, 503 no listo; algunos balanceadores de carga solo aceptan 200 como saludables; verificar la plataforma.
¿Autenticación en salud?
Generalmente sin autenticación en la red interna; proteger las métricas de administración por separado.
¿Cómo afectan las migraciones a la preparación?
Durante el trabajo de migración, los pods antiguos permanecen listos; los pods nuevos esperan hasta que las migraciones se completen y la conexión del pool se establezca.
¿Procesos de trabajo?
Los trabajadores de Celery exponen salud separada a través de la inspección ping o un sidecar HTTP personalizado.
¿Período de gracia del balanceador de carga?
Alinear con preStop y el umbral de fallo de readiness para que el tráfico se drene limpiamente.
¿Sintéticos externos?
Monitorizar /health/live desde el exterior; alertar sobre fallos regionales independientes de kubelet.
¿Métricas en fallos de sonda?
El contador readiness_check_failures_total ayuda a depurar dependencias inestables sin leer los logs de la sonda.
Relacionado
- Conceptos Básicos de Despliegue - introducción a la salud
- Kubernetes para Aplicaciones Python - YAML de sondas
- Despliegues sin Tiempo de Inactividad - comportamiento de drenaje
- Métricas - contadores de fallos de sonda
- Mejores Prácticas de Observabilidad - lista de verificación de sondas
Versiones de la pila: Esta página se escribió para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ y uv 0.6+.