Planteamiento y contexto
Un Pod multicontenedor cuenta con un proxy de API, un sidecar de caché y un worker por lotes. El equipo desea ajustar los presupuestos de CPU y memoria a nivel de Pod a partir de la latencia y la longitud de la cola sin eliminar el Pod. Diseña el controlador, incluyendo la observación, las decisiones, las escrituras en /resize, el seguimiento del estado, la protección de concurrencia, las solicitudes inviables y la reversión.
Qué evalúa el entrevistador
- Si distingues entre recursos deseados, recursos reales y la política de reinicio de contenedores.
- Si diseñas una reconciliación idempotente, condiciones de estado y reintentos diferidos/inviables.
- Si los presupuestos del Pod y las solicitudes de los contenedores tienen límites explícitos y mecanismos de seguridad.
- Si las métricas, los permisos, la recuperación y el despliegue progresivo forman parte del diseño.
Preguntas para clarificar
- ¿El clúster admite el redimensionamiento a nivel de Pod y qué feature gates y versión de kubectl están instalados?
- ¿El controlador modifica CPU, memoria o ambos recursos a nivel de Pod y de contenedor?
- ¿Qué contenedores pueden reiniciarse y cuáles tienen conexiones o estado no interrumpibles?
- ¿El objetivo es la reducción de costos, un SLO o absorber una cola con ráfagas de tráfico?
Respuesta en 30 segundos
Construiría un reconciliador idempotente orientado a eventos: lee las métricas y el estado del Pod, calcula un objetivo dentro de los presupuestos, SLOs, capacidad del nodo y un período de enfriamiento (cooldown), y luego envía un cambio pequeño a través del subrecurso /resize. El estado registra observedGeneration, PodResizePending, PodResizeInProgress y los motivos de Infeasible o Deferred; los reintentos utilizan backoff, prioridad y un conteo máximo. La CPU y la memoria se evalúan por separado, se respeta el resizePolicy del contenedor y se restaura el último presupuesto verificado ante riesgo de memoria o regresión del SLO. Cada escritura tiene un propietario, registro de auditoría y límites de RBAC.
Análisis detallado paso a paso
Definir el modelo de recursos y el límite de seguridad
El spec.resources a nivel de Pod es un presupuesto agregado; los requests y limits de los contenedores siguen afectando las garantías y el comportamiento de reinicio. Mantén límites de seguridad (guardrails) por carga de trabajo de mínimo, máximo, tamaño de paso (step), enfriamiento y SLO, rechazando solicitudes que superen la cuota del namespace o la capacidad del nodo.
Recopilar métricas y calcular un objetivo
Utiliza la latencia, la longitud de la cola, el estrangulamiento (throttling) de CPU, el working set y los eventos de OOM. Aplica ventanas de tiempo e histéresis para evitar reaccionar a un solo pico; el objetivo debe satisfacer tanto el presupuesto del Pod como la restricción de la suma de requests de los contenedores.
Enviar una actualización idempotente al subrecurso resize
El controlador actualiza el estado deseado con una versión de recurso (resourceVersion) y un propietario. Solicitud de ejemplo:
spec:
resources:
requests:
cpu: "300m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"Llama al subrecurso /resize y verifica resourceVersion. En caso de conflicto, vuelve a leer y reconciliar en lugar de sobrescribir a un usuario u otro controlador.
Rastrear condiciones y prioridad de reintentos
Lee condiciones como PodResizePending y PodResizeInProgress además de observedGeneration. Infeasible significa que las restricciones actuales no pueden satisfacer la solicitud; Deferred significa que se ha pospuesto. Persiste el motivo, el siguiente intento y el conteo. Programa los reintentos según la prioridad de la carga de trabajo, la QoS y el tiempo de espera para que el trabajo de baja prioridad no sufra inanición indefinida.
Gestionar la política de reinicio de contenedores
Los cambios a nivel de Pod pueden desencadenar un resizePolicy a nivel de contenedor. La CPU puede aplicarse sin reinicio, mientras que la memoria puede requerir uno; inspecciona la política, las conexiones y el estado de cada contenedor. Coloca las solicitudes no reiniciables detrás de una cola de seguridad y nunca reportes continuidad del negocio basándote únicamente en el éxito a nivel de Pod.
Observar, revertir y mantener alta disponibilidad
Registra valores objetivo y reales, transiciones de condiciones, conteo de reinicios, SLO de latencia, pico de memoria y motivo de falla. Ejecuta réplicas del controlador con elección de líder y deduplica la cola mediante la clave del Pod. Ante un presupuesto incorrecto, OOM o regresión del SLO, restaura el último objetivo estable y pausa la automatización para revisión humana.
Respuesta modelo
Construiría un reconciliador idempotente que lea métricas de latencia, cola, estrangulamiento, working set y OOM, y luego calcule un objetivo dentro de presupuestos mínimos/máximos, paso, enfriamiento, capacidad del nodo y cuota del namespace. Envía pequeños cambios con control de versión de recurso a través de /resize; vuelve a leer en caso de conflictos. Registra observedGeneration, Pending, InProgress, Infeasible, motivo de Deferred y tiempo de reintento, programando los reintentos por prioridad y espera. Inspecciona la política de redimensionamiento de cada contenedor antes de que un cambio de memoria pueda reiniciarlo. Utiliza elección de líder, métricas y registros de auditoría; restaura el último presupuesto estable y pausa la automatización ante regresión del SLO u OOM.
Errores comunes
- Editar el Pod spec directamente y asumir que kubelet lo aplica, ignorando el subrecurso
/resize. - Leer únicamente los recursos deseados e ignorar los recursos reales y las condiciones.
- Omitir el enfriamiento y la histéresis, provocando oscilaciones y reinicios frecuentes.
- Descartar solicitudes Deferred indefinidamente o reintentar solicitudes Infeasible sin un límite.
- Ignorar el
resizePolicydel contenedor y el riesgo de reinicio por memoria. - Carecer de resourceVersion, propietario y RBAC, permitiendo que los controladores se sobrescriban entre sí.
Preguntas de seguimiento
¿Cómo evitas que dos controladores se sobrescriban mutuamente?
Utiliza propiedad explícita, resourceVersion, field management y un único propietario de escritura; vuelve a leer y fusiona la intención en caso de conflictos en lugar de realizar una sobrescritura incondicional.
¿Cómo distingues Infeasible de Deferred?
Infeasible significa que las restricciones actuales no pueden satisfacer el objetivo y requieren un nuevo objetivo o capacidad; Deferred es temporal y debe reintentarse conservando su motivo y prioridad.
¿Cuándo debe pausarse la automatización?
Pausa ante OOM, regresión sostenida del SLO, condiciones sin cambios, reinicios excesivos u observaciones no válidas, manteniendo al mismo tiempo una vía de recuperación manual.
¿Cómo demuestras que no hubo interrupciones?
Correlaciona las condiciones de redimensionamiento, el restartCount del contenedor, los errores de conexión, la latencia y las métricas de cola por política; que la fase del Pod permanezca en Running es insuficiente.