Introducción
Un init container se ejecuta antes que los contenedores de aplicación principales en un Pod. Cada init container debe finalizar correctamente antes de que Kubernetes inicie el siguiente init container o cualquier contenedor regular. Esto hace que los init containers sean útiles para preparar archivos, verificar dependencias o realizar pequeñas tareas de configuración que no necesitan permanecer en ejecución junto a la aplicación.
En este laboratorio, añadirás un init container que escribe un archivo de inicio en un volumen compartido emptyDir, confirmarás que el contenedor de la aplicación puede leer el archivo, inspeccionarás el estado de finalización y los registros del init container, y luego utilizarás el mismo patrón en una plantilla de Deployment.
Preparar un Namespace para Init Containers
En este paso, prepararás un namespace limpio para practicar con init containers.
Comienza en /home/labex/project. Escribirás los manifiestos de Pod y Deployment en este directorio.
mkdir -p /home/labex/project
cd /home/labex/project
Verifica que el servidor de la API de Kubernetes sea accesible. Si la máquina virtual acaba de iniciarse y el nodo aún no está listo, espera unos segundos y vuelve a ejecutar el comando.
kubectl get nodes --request-timeout=5s
La salida esperada incluye:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Los init containers se ejecutan dentro de los Pods, así que espera hasta que el Pod de red del clúster esté listo (Ready) antes de crear cargas de trabajo.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Salida esperada:
pod/calico-node-... condition met
Crea un namespace llamado ckad-prep-init:
kubectl create namespace ckad-prep-init
Establece este namespace como el namespace del contexto actual:
kubectl config set-context --current --namespace=ckad-prep-init
Confirma el namespace actual:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Salida esperada:
ckad-prep-init
Preparar datos compartidos antes de iniciar la aplicación
En este paso, crearás un Pod donde un init container prepara un archivo antes de que se inicie el contenedor de la aplicación.
El volumen emptyDir se crea cuando el Pod se asigna a un nodo y es compartido por los contenedores dentro del mismo Pod. Tanto el init container como el contenedor de la aplicación montan este volumen en /work. El init container escribe /work/startup.txt y luego termina. Solo después de que finaliza con éxito, Kubernetes inicia el contenedor de la aplicación.
Crea init-file-pod.yaml:
cat > init-file-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: init-file-demo
labels:
app: init-file-demo
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: shared-work
emptyDir: {}
initContainers:
- name: prepare-startup-file
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo init-started; echo prepared-by-init > /work/startup.txt; echo init-finished'
volumeMounts:
- name: shared-work
mountPath: /work
containers:
- name: app
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo app-started; cat /work/startup.txt; sleep 3600'
volumeMounts:
- name: shared-work
mountPath: /work
EOF
Aplica el manifiesto:
kubectl apply -f init-file-pod.yaml
Salida esperada:
pod/init-file-demo created
Espera hasta que el Pod esté listo:
kubectl wait --for=condition=Ready pod/init-file-demo --timeout=120s
Salida esperada:
pod/init-file-demo condition met
Lee el archivo desde dentro del contenedor de la aplicación. Esto demuestra que el init container preparó los datos en el volumen compartido antes de que la aplicación comenzara.
kubectl exec init-file-demo -c app -- cat /work/startup.txt
Salida esperada:
prepared-by-init
Inspeccionar el estado y los registros del Init Container
En este paso, inspeccionarás la evidencia de que el init container se completó antes de que el contenedor de la aplicación comenzara a ejecutarse.
Los init containers aparecen bajo .status.initContainerStatuses, mientras que los contenedores regulares aparecen bajo .status.containerStatuses. El init container debería tener un motivo (reason) de Completed porque terminó con éxito.
kubectl get pod init-file-demo -o 'jsonpath={.status.initContainerStatuses[0].name}{" "}{.status.initContainerStatuses[0].state.terminated.reason}{"\n"}'
Salida esperada:
prepare-startup-file Completed
Ahora inspecciona el estado del contenedor de aplicación regular. Debería estar listo y en ejecución.
kubectl get pod init-file-demo -o 'jsonpath={.status.containerStatuses[0].name}{" "}{.status.containerStatuses[0].ready}{" "}{.status.containerStatuses[0].state.running.startedAt}{"\n"}'
La salida esperada incluye:
app true ...
Lee los registros del init container. Aunque el init container haya terminado, sus registros permanecen disponibles a través de kubectl logs -c.
kubectl logs init-file-demo -c prepare-startup-file
Salida esperada:
init-started
init-finished
Lee los registros del contenedor de la aplicación. La aplicación comienza después de que el init container escribe el archivo, por lo que sus registros incluyen el valor preparado.
kubectl logs init-file-demo -c app
La salida esperada incluye:
app-started
prepared-by-init
Añadir un Init Container a un Deployment
En este paso, utilizarás el mismo patrón de init container dentro de una plantilla de Deployment.
Para cargas de trabajo de aplicación, normalmente colocas los init containers en la plantilla de Pod de un controlador en lugar de crear Pods independientes. Cuando el Deployment crea un Pod, Kubernetes ejecuta el init container primero para cada Pod creado a partir de esa plantilla.
Crea init-deployment.yaml:
cat > init-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: init-web
spec:
replicas: 1
selector:
matchLabels:
app: init-web
template:
metadata:
labels:
app: init-web
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: web-content
emptyDir: {}
initContainers:
- name: render-index
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo deployment-init > /site/index.txt'
volumeMounts:
- name: web-content
mountPath: /site
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- 'cat /site/index.txt; sleep 3600'
volumeMounts:
- name: web-content
mountPath: /site
EOF
Aplica el Deployment:
kubectl apply -f init-deployment.yaml
Salida esperada:
deployment.apps/init-web created
Espera hasta que el Deployment esté disponible:
kubectl wait --for=condition=Available deployment/init-web --timeout=120s
Salida esperada:
deployment.apps/init-web condition met
Encuentra el Pod creado por el Deployment:
web_pod="$(kubectl get pods -l app=init-web -o 'jsonpath={.items[0].metadata.name}')"
echo "$web_pod"
La salida esperada muestra un nombre de Pod generado:
init-web-...
Lee los registros del contenedor de la aplicación desde ese Pod:
kubectl logs "$web_pod" -c web
Salida esperada:
deployment-init
Inspecciona el estado de finalización del init container dentro del Pod creado por el Deployment:
kubectl get pod "$web_pod" -o 'jsonpath={.status.initContainerStatuses[0].name}{" "}{.status.initContainerStatuses[0].state.terminated.reason}{"\n"}'
Salida esperada:
render-index Completed
Resumen
Has añadido init containers a un Pod y a una plantilla de Deployment. Utilizaste un volumen emptyDir para compartir archivos preparados con el contenedor de la aplicación, inspeccionaste el estado de finalización del init container, leíste los registros tanto del init container como de la aplicación, y confirmaste que el mismo patrón funciona para Pods de aplicación gestionados por controladores.


