Dia 09 - Crear un Job Countdown en Kubernetes
Problema / Desafio
Crear un Job en Kubernetes llamado countdown-devops que ejecute un contenedor con Ubuntu y realice un sleep 5 antes de finalizar. A diferencia de un CronJob (dia 08), un Job se ejecuta una sola vez y termina.
Conceptos clave
Job vs CronJob
| Job | CronJob | |
|---|---|---|
| Ejecucion | Una sola vez | Periodica segun schedule |
| Caso de uso | Tarea puntual | Tarea recurrente |
| Se completa | Cuando el Pod termina exitosamente | Nunca (sigue creando Jobs) |
Un Job es el recurso base. Un CronJob simplemente automatiza la creacion de Jobs segun un horario.
restartPolicy en Jobs
En un Job, restartPolicy solo acepta OnFailure o Never:
| Politica | Comportamiento |
|---|---|
Never |
Si el contenedor falla, se crea un nuevo Pod (no se reinicia el existente) |
OnFailure |
El contenedor se reinicia dentro del mismo Pod si falla |
Para este ejercicio usamos Never: si el comando falla, Kubernetes no reintenta en el mismo Pod.
Ciclo de vida de un Job
- Se crea el Job con
kubectl applyokubectl create - El Job crea un Pod que ejecuta el comando definido
- El Pod corre el comando (
sleep 5en este caso) - Al completarse, el Pod pasa a estado
Completed - El Job registra
1/1 COMPLETIONS
Configuraciones importantes para produccion
backoffLimit
Controla cuantas veces Kubernetes reintenta un Job fallido antes de marcarlo como Failed:
Kubernetes aplica backoff exponencial entre reintentos: 10s, 20s, 40s, etc.
activeDeadlineSeconds
Establece un timeout maximo para el Job. Si no termina en ese tiempo, Kubernetes lo mata:
- Tiene prioridad sobre
backoffLimit— si se alcanza el deadline, el Job se detiene sin importar cuantos reintentos quedan - Util para evitar Jobs que se quedan colgados indefinidamente
ttlSecondsAfterFinished
Limpia automaticamente el Job y sus Pods despues de completarse o fallar:
- Sin esto, los Jobs en estado
Completedse acumulan y hay que borrarlos manualmente conkubectl delete job - Aplica tanto a Jobs exitosos como fallidos
completions y parallelism
Permiten ejecutar multiples Pods como parte del mismo Job:
spec:
completions: 5 # Necesita 5 Pods exitosos para completarse
parallelism: 2 # Ejecuta 2 Pods en simultaneo
- Por defecto ambos son
1(un solo Pod, secuencial) - Util para procesar lotes de trabajo en paralelo
- Con
completions: 5yparallelism: 2, Kubernetes ejecuta 2 Pods a la vez hasta alcanzar 5 completados
suspend
Permite crear un Job sin ejecutarlo inmediatamente:
# Suspender un Job activo
kubectl patch job countdown-devops -p '{"spec":{"suspend":true}}'
# Reanudar
kubectl patch job countdown-devops -p '{"spec":{"suspend":false}}'
Ejemplo completo con todas las configuraciones
apiVersion: batch/v1
kind: Job
metadata:
name: countdown-devops
spec:
backoffLimit: 3
activeDeadlineSeconds: 60
ttlSecondsAfterFinished: 120
template:
metadata:
name: countdown-devops
spec:
containers:
- name: container-countdown-devops
image: ubuntu:latest
command: ["sleep", "5"]
restartPolicy: Never
Pasos
- Crear el manifiesto YAML del Job
- Aplicar el manifiesto con
kubectl apply - Verificar que el Job y el Pod se crearon correctamente
- Esperar a que el Pod termine y validar el estado
Completed
Comandos / Codigo
Manifiesto del Job
apiVersion: batch/v1
kind: Job
metadata:
name: countdown-devops
spec:
template:
metadata:
name: countdown-devops
spec:
containers:
- name: container-countdown-devops
image: ubuntu:latest
command: ["sleep", "5"]
restartPolicy: Never
Puntos importantes del manifiesto:
apiVersion: batch/v1— los Jobs pertenecen al grupobatch, no aappsni al corecommandejecuta directamente el binariosleepcon argumento5restartPolicy: Neverva a nivel despec.template.spec, al mismo nivel quecontainers- A diferencia de un CronJob, no hay
jobTemplatenischedule— el Job se ejecuta inmediatamente
Estructura del manifiesto explicada
Job
└── metadata.name: countdown-devops # Nombre del Job
└── spec.template # Plantilla del Pod
├── metadata.name: countdown-devops # Nombre del Pod template
└── spec
├── containers
│ └── container-countdown-devops # Nombre del contenedor
│ ├── image: ubuntu:latest
│ └── command: ["sleep", "5"]
└── restartPolicy: Never
Aplicar el manifiesto
Verificar el Job
Despues de ~5 segundos:
Verificar el Pod
El estado Completed indica que el comando sleep 5 termino exitosamente.
Ver detalle del Job
Inspeccionar Jobs fallidos
# Ver por que fallo
kubectl describe job countdown-devops
# Ver logs del Pod que fallo
kubectl logs job/countdown-devops
# Ver todos los Pods del Job (incluyendo fallidos)
kubectl get pods --selector=job-name=countdown-devops
Crear el Job de forma imperativa (alternativa)
Para generar el YAML sin aplicar (dry-run):
kubectl create job countdown-devops \
--image=ubuntu:latest \
--restart=Never \
--dry-run=client -o yaml \
-- sleep 5
Nota: el metodo imperativo no permite definir metadata.name en el template del Pod. Para eso se necesita el manifiesto YAML declarativo.
Diferencia entre command y args
| Campo | Equivalente en Docker | Uso |
|---|---|---|
command |
ENTRYPOINT |
Sobreescribe el punto de entrada del contenedor |
args |
CMD |
Argumentos que se pasan al command o al ENTRYPOINT por defecto |
En este caso usamos command: ["sleep", "5"] que ejecuta directamente el binario. Alternativa equivalente:
Troubleshooting
| Problema | Solucion |
|---|---|
Pod en ErrImagePull o ImagePullBackOff |
Verificar que la imagen ubuntu:latest es accesible desde el cluster. En clusters sin acceso a internet, usar un registry interno |
Pod queda en Error |
Revisar logs con kubectl logs <pod-name>. Verificar que el comando es valido |
Job no aparece en kubectl get jobs |
Verificar que el apiVersion es batch/v1 y el kind es Job |
restartPolicy: Always causa error |
En Jobs solo se permite Never o OnFailure |
| Pod se crea pero nunca completa | Verificar que el comando termina. Un sleep sin argumento o un proceso infinito no completara |