Tema representativo de entrevista

Entrevista de backend: ¿Cómo usarías los sidecars nativos de Kubernetes para el ciclo de vida de un Job?

BackendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

El contenedor principal de un Job de Kubernetes finaliza el procesamiento por lotes (batch), pero su sidecar de registro sigue ejecutándose y el Job nunca se completa. ¿Cómo lo migrarías a un sidecar nativo? Explica el orden de inicio, la propagación de señales, el manejo de fallas, la compatibilidad con clústeres antiguos y las métricas de aceptación.

Prompt y alcance

Un Pod de Job contiene un contenedor batch, un contenedor de reenvío de logs y un contenedor de sincronización de configuración. El contenedor batch finaliza, pero el contenedor de logs continúa ejecutándose y el Job permanece incompleto; el contenedor de sincronización también debe preparar la configuración antes de que comience el lote. Explica cómo la semántica de sidecars nativos de Kubernetes resuelve el inicio, la terminación y la finalización del Job evitando la pérdida de logs finales (tail logs) y comportamientos dependientes de la versión.

Los componentes y tiempos son supuestos de entrevista, no valores predeterminados para todos los clústeres. Esta pregunta encaja en roles de plataforma backend, runtime nativo de la nube y SRE. Su habilidad central es la confiabilidad del ciclo de vida del Pod, por lo que pertenece a backend.

Lo que evalúan los entrevistadores

Primero, ¿puedes distinguir entre containers ordinarios, initContainers y sidecars nativos? Un sidecar nativo se expresa en la sección de contenedores init con una política de reinicio que le permite continuar después de la inicialización.

Segundo, ¿puedes explicar la finalización del Job? Un sidecar nativo se finaliza después de que los contenedores regulares se completan y no mantiene un Job abierto como lo hace un sidecar convencional de ejecución continua.

Tercero, ¿puedes manejar dependencias y señales? El sidecar de sincronización debe reportar su estado de listo (readiness) antes de que el contenedor principal inicie; durante la terminación debe recibir una señal después del contenedor principal y tener una ruta de parada forzada acotada.

Cuarto, ¿puedes manejar fallas? La falla en el inicio del sidecar, los bucles de reinicio, un backend de logs no disponible y una falla temprana del contenedor principal necesitan reglas explícitas de reintento, degradación y observabilidad.

Quinto, ¿puedes planificar la compatibilidad? Un clúster que no comprenda la semántica de sidecars nativos puede rechazar el manifiesto o ejecutar el comportamiento antiguo. Utiliza feature gates de capacidad, verificaciones de versión y un manifiesto de respaldo (fallback).

Preguntas para aclarar primero

  • ¿Qué versión de Kubernetes y qué política de admisión admiten sidecars nativos?
  • ¿La sincronización de configuración es una inicialización de una sola vez o una actualización continua durante el job?
  • ¿A dónde deben entregarse los logs y cuánta pérdida de logs finales es aceptable?
  • ¿Cómo se definen los códigos de salida del contenedor principal, del sidecar y de reintento del Job?
  • ¿El Pod utiliza restartPolicy: Never o OnFailure?
  • ¿Existen dependencias de orden o contención de volúmenes compartidos entre los sidecars?

Estructura de respuesta en 30 segundos

“Colocaría los contenedores que deben iniciar temprano y permanecer activos en initContainers, establecería la política de reinicio del sidecar y haría que el proceso de sincronización señale cuando la configuración validada esté lista. Después de que el contenedor principal se complete, el controlador finaliza el sidecar nativo para que el Job pueda terminar; el sidecar de registro maneja SIGTERM deteniendo la entrada y vaciando los búferes antes de un timeout forzado. Los clústeres más antiguos utilizan detección de versiones y un fallback con contenedores convencionales. Verificaría el orden, los códigos de salida, la integridad de los logs finales, los reintentos y la latencia de finalización del Job.”

Respuesta paso a paso

Paso 1: Verificar el soporte de sidecars nativos

Kubernetes expresa los sidecars nativos en initContainers con un restartPolicy: Always a nivel de contenedor, permitiéndoles continuar después de la inicialización. Verifica la versión del API server, feature gates, admission controllers y herramientas de despliegue; una versión de cliente kubectl por sí sola es insuficiente.

Paso 2: Expresar el orden de inicio

Los contenedores init inician en orden; un sidecar nativo puede permanecer en ejecución tras iniciarse mientras la inicialización posterior y el contenedor principal proceden. El sidecar de sincronización debe hacer que 'archivo escrito, permisos correctos, versión validada' sea su condición de readiness. El contenedor principal debe verificar esa condición antes de leer el volumen compartido.

yaml
initContainers:
- name: config-sync
  image: example/config-sync:v2
  restartPolicy: Always
  readinessProbe:
    exec:
      command: ["/bin/sh", "-c", "test -f /work/config.ready"]
- name: migrate
  image: example/migrate:v4
  command: ["/bin/sh", "-c", "./migrate && touch /work/migrate.done"]
containers:
- name: batch
  image: example/batch:v7

Paso 3: Diseñar la terminación y el vaciado de logs

Después de que el contenedor principal finaliza, el sidecar de registro recibe la terminación y debe enviar los logs en búfer dentro de una ventana acotada. Debe manejar SIGTERM, dejar de aceptar entradas, vaciar, confirmar la entrega y salir. Configura terminationGracePeriodSeconds para cubrir el vaciado más largo; un SIGKILL posterior puede perder logs finales, así que registra y alerta sobre esa condición.

Paso 4: Definir fallas y reintentos

Si el sidecar de sincronización se reinicia, el contenedor principal no debe leer una configuración parcial. La preparación (readiness), las fallas de sondeo (probes) y el reemplazo atómico en el volumen compartido funcionan en conjunto. Cuando el contenedor principal falla, el controlador del Job aplica backoffLimit; el reinicio de un sidecar no debe contabilizarse como un nuevo intento de negocio. Registra el código de salida principal, la fase del Pod, las condiciones del Job y el estado del sidecar por separado.

Paso 5: Manejar la semántica de finalización del Job

Los sidecars nativos se terminan después de que todos los contenedores regulares se completan, por lo que el Job no permanece abierto como puede suceder con un sidecar residente ordinario. Si un sidecar falla tempranamente, verifica el comportamiento real del clúster en cuanto a readiness, reinicios y condiciones del Job mediante una prueba de integración en lugar de confiar en un diagrama.

Paso 6: Soportar clústeres antiguos

Usa una compuerta de versión: los clústeres no compatibles reciben un manifiesto convencional de containers, y un wrapper le indica al proceso de logging que salga cuando el contenedor principal termine. Mantén los manifiestos mutuamente excluyentes. Durante la migración, observa el tiempo de finalización del Job, los motivos de falla y la integridad de los logs finales.

Paso 7: Verificar recursos y seguridad

Los sidecars comparten la red del Pod, los volúmenes y la cuota de recursos. Asigna a los contenedores de sincronización y de logs requests y limits independientes para que una ráfaga de logs no deje sin recursos al lote; otorga únicamente los permisos de ServiceAccount necesarios para leer la configuración o escribir logs. Los probes no deben exponer credenciales y los archivos temporales necesitan permisos restrictivos.

Respuesta modelo

“Primero confirmaría el soporte de sidecars nativos en el API server y la cadena de admisión. El proceso de sincronización se ubica en initContainers con restartPolicy: Always; valida una versión y escribe atómicamente la configuración antes de que el contenedor principal proceda. Una migración de ejecución única sigue siendo un contenedor init normal. El sidecar de logging maneja la terminación después del contenedor principal, detiene la entrada, vacía y confirma la entrega dentro de un período de gracia acotado, y luego alerta si ocurre una terminación forzada.

Registraría por separado los códigos de salida principales, reinicios de sidecars, condiciones del Pod, backoff del Job y pérdida de logs finales. Los clústeres más antiguos seleccionan un manifiesto de fallback con contenedores convencionales, con un wrapper que envía una señal al registrador para salir. Un despliegue canary verifica el orden, la latencia de finalización del Job, los reintentos, la configuración atómica, los límites de recursos y la integridad de los logs.”

Errores comunes

  • Usar un sidecar ordinario en containers el Job puede esperar indefinidamente → usa semántica nativa o coordinación explícita de salida.
  • Hacer que un proceso de sincronización continua sea un init de una sola vez → no puede actualizarse durante el job → define primero los requisitos del ciclo de vida.
  • Usar readiness sin escrituras atómicas → el proceso principal lee un estado parcial → valida un archivo temporal y luego renómbralo.
  • Ignorar la ventana de vaciado (flush) → SIGKILL pierde logs finales → asigna tiempo de terminación ordenada para el peor escenario de entrega.
  • Contar la falla del sidecar como falla del negocio → las métricas de reintento se vuelven engañosas → separa el estado del contenedor y del Job.
  • Asumir que todos los clústeres admiten el campo → versiones antiguas lo rechazan o cambian el comportamiento → usa compuertas de versión y manifiestos de respaldo.
  • Dejar los recursos del sidecar sin límites → las ráfagas de logs asfixian el trabajo por lotes → establece requests, limits y alertas independientes.
  • Dar permisos excesivos al volumen compartido → la configuración o los logs pueden ser alterados → usa identidad de mínimo privilegio y modos de archivo restrictivos.

Preguntas de seguimiento

Pregunta de seguimiento 1: ¿Por qué los sidecars nativos se expresan en initContainers?

Esto preserva el orden de inicialización mientras que una política de reinicio a nivel de contenedor permite que el sidecar permanezca activo tras el inicio. Los contenedores posteriores esperan las condiciones de inicialización requeridas y el controlador maneja la terminación del sidecar al completarse el Job.

Pregunta de seguimiento 2: ¿Puede un sidecar terminar siempre de enviar los logs?

No. Fallas de red, estrangulamiento (throttling) o un período de gracia corto pueden causar pérdida de datos. Usa vaciado acotado, búfer persistente o reintentos, y mide la integridad de los logs finales junto con alertas de pérdida.

Pregunta de seguimiento 3: ¿Debe continuar la sincronización después de que falla el contenedor principal?

Depende de la semántica de reintento. Si la configuración es inmutable para un intento, detén nuevas escrituras y preserva los diagnósticos. Si cada reintento necesita una versión nueva, permite que un nuevo Pod o una política de versión explícita gestione esa actualización; no cambies silenciosamente un intento en curso.

Pregunta de seguimiento 4: ¿Cómo pruebas el orden de inicio?

Demora el proceso de sincronización, escribe un estado parcial y fuerza una falla de validación; verifica que el contenedor principal no inicie. Luego escribe un marcador de finalización y verifica que lea una versión completa. Prueba reinicios, visibilidad del volumen compartido y condiciones de carrera en los probes.

Pregunta de seguimiento 5: ¿Cómo mantienes consistente el respaldo para clústeres antiguos?

Coloca la selección de versiones en el pipeline de entrega, genera manifiestos mutuamente excluyentes y ejecuta las mismas pruebas de contrato de Job en ambos. La aplicación no debería adivinar la versión de Kubernetes en tiempo de ejecución.

Pregunta de seguimiento 6: ¿Cómo sabes si el Job realmente se completó?

Verifica en conjunto las condiciones del Job, el código de salida principal, la fase del Pod, el motivo de terminación del sidecar y un marcador de confirmación de entrega de logs. Un Pod en estado Succeeded por sí solo puede ocultar la pérdida de logs finales o una falla de sincronización.

Fuentes públicas

Preguntas relacionadas