Tema representativo de entrevista

Entrevista de diseño de sistemas: ¿Cómo diseñarías un controlador de redimensionamiento a nivel de Pod en Kubernetes?

Diseño de sistemasDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Diseña un controlador que ajuste el presupuesto de CPU y memoria de un Pod a partir de métricas de latencia y cola, gestionando al mismo tiempo actualizaciones concurrentes, solicitudes inviables, políticas de reinicio, reintentos y reversión (rollback).

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

  1. ¿El clúster admite el redimensionamiento a nivel de Pod y qué feature gates y versión de kubectl están instalados?
  2. ¿El controlador modifica CPU, memoria o ambos recursos a nivel de Pod y de contenedor?
  3. ¿Qué contenedores pueden reiniciarse y cuáles tienen conexiones o estado no interrumpibles?
  4. ¿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:

yaml
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 resizePolicy del 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.

Fuentes públicas

Preguntas relacionadas

Herramienta de entrevista relacionada

Usa Resolver para una respuesta de diseño de sistemas

Aclara primero los requisitos y luego avanza a través de la escala, la arquitectura, la elección de componentes y las compensaciones (trade-offs).

Ver la herramienta