Introducción
Los registros (logs), eventos, la ejecución de comandos y el reenvío de puertos (port-forwarding) te ayudan a inspeccionar una aplicación. Las sondas (probes) permiten que Kubernetes inspeccione la aplicación de forma continua. Una sonda de readiness (disponibilidad) responde a la pregunta: "¿Debería este Pod recibir tráfico?". Una sonda de liveness (actividad) responde a: "¿Debería reiniciarse este contenedor?".
En este laboratorio, configurarás la disponibilidad y la actividad por separado. Primero, crearás una aplicación que solo se marca como "Ready" después de crear un endpoint /ready. Luego, crearás otra aplicación con una sonda de liveness, eliminarás su archivo de salud mediante kubectl exec y observarás cómo Kubernetes reinicia el contenedor.
Preparar un namespace para practicar con sondas
En este paso, prepararás un namespace limpio para practicar con las sondas.
Comienza en /home/labex/project. Mantendrás los manifiestos de las sondas 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...
Espera hasta que el Pod de red del clúster esté listo. Las sondas y los Services dependen de una red de Pods saludable.
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-probes y establécelo como el namespace actual:
kubectl create namespace ckad-prep-probes
kubectl config set-context --current --namespace=ckad-prep-probes
Confirma el namespace actual:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Salida esperada:
ckad-prep-probes
Configurar una sonda de Readiness
En este paso, configurarás una sonda de readiness y observarás que el Service solo utiliza Pods que están listos.
El contenedor inicia un servidor HTTP inmediatamente, pero crea /www/ready unos segundos después. La sonda de readiness verifica GET /ready en el puerto 8080. Hasta que esa ruta exista, el Pod puede estar en estado "Running" pero no "Ready", y el Service no debería enviarle tráfico.
Crea readiness-web.yaml:
cat > readiness-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: readiness-web
spec:
replicas: 2
selector:
matchLabels:
app: readiness-web
template:
metadata:
labels:
app: readiness-web
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- |
mkdir -p /www
echo readiness-ok > /www/index.html
(sleep 12; echo ready > /www/ready) &
httpd -f -p 8080 -h /www
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 1
---
apiVersion: v1
kind: Service
metadata:
name: readiness-web
spec:
selector:
app: readiness-web
ports:
- port: 80
targetPort: 8080
EOF
Aplica el manifiesto y observa los Pods poco después de la creación:
kubectl apply -f readiness-web.yaml
sleep 3
kubectl get pods -l app=readiness-web
La salida esperada puede mostrar Pods que están en ejecución (Running) pero aún no listos (Ready):
NAME READY STATUS RESTARTS AGE
readiness-web-... 0/1 Running 0 ...
Espera a que el Deployment esté disponible:
kubectl rollout status deployment/readiness-web --timeout=120s
Salida esperada:
deployment "readiness-web" successfully rolled out
Inspecciona los endpoints del Service a través de EndpointSlice. Después de que la sonda de readiness pase, el Service debería tener dos endpoints listos.
kubectl get endpointslice -l kubernetes.io/service-name=readiness-web
La salida esperada incluye:
NAME ADDRESSTYPE PORTS ENDPOINTS
readiness-web-... IPv4 8080 ... + 1 more...
Crea un Pod cliente y prueba el Service:
kubectl run probe-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/probe-client --timeout=120s
kubectl exec probe-client -- wget -qO- http://readiness-web
Salida esperada:
readiness-ok
Configurar una sonda de Liveness
En este paso, configurarás una sonda de liveness que verifica un archivo de salud.
Una sonda de liveness decide si Kubernetes debe reiniciar un contenedor. Este ejemplo utiliza una sonda de tipo exec que ejecuta test -f /tmp/healthy dentro del contenedor. El contenedor crea ese archivo al iniciarse, por lo que comienza en un estado saludable.
Crea liveness-web.yaml:
cat > liveness-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: liveness-web
spec:
replicas: 1
selector:
matchLabels:
app: liveness-web
template:
metadata:
labels:
app: liveness-web
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- |
touch /tmp/healthy
mkdir -p /www
echo liveness-ok > /www/index.html
httpd -f -p 8080 -h /www
ports:
- containerPort: 8080
livenessProbe:
exec:
command:
- test
- -f
- /tmp/healthy
initialDelaySeconds: 3
periodSeconds: 3
failureThreshold: 1
EOF
Aplica el manifiesto y espera al Deployment:
kubectl apply -f liveness-web.yaml
kubectl rollout status deployment/liveness-web --timeout=120s
La salida esperada incluye:
deployment.apps/liveness-web created
deployment "liveness-web" successfully rolled out
Almacena el nombre del Pod y confirma que el archivo de salud existe:
LIVE_POD="$(kubectl get pods -l app=liveness-web -o jsonpath='{.items[0].metadata.name}')"
echo "$LIVE_POD"
kubectl exec "$LIVE_POD" -- test -f /tmp/healthy
echo "health file exists"
La salida esperada incluye el nombre del Pod y:
health file exists
Describe el Pod y busca la configuración de la sonda de liveness:
kubectl describe pod "$LIVE_POD" | grep -A3 'Liveness:'
La salida esperada incluye:
Liveness: exec [test -f /tmp/healthy] delay=3s timeout=1s period=3s
Provocar un reinicio por Liveness
En este paso, eliminarás el archivo de salud y observarás cómo la sonda de liveness reinicia el contenedor.
El objeto Pod puede permanecer igual mientras el contenedor en su interior se reinicia. Por eso observarás el contador de reinicios del contenedor en lugar de esperar un nuevo nombre de Pod.
Almacena el nombre del Pod actual:
LIVE_POD="$(kubectl get pods -l app=liveness-web -o jsonpath='{.items[0].metadata.name}')"
echo "$LIVE_POD"
Elimina el archivo de salud desde dentro del contenedor:
kubectl exec "$LIVE_POD" -- rm /tmp/healthy
Observa el contador de reinicios hasta que sea mayor que cero. La sonda de liveness se ejecuta cada tres segundos, por lo que esto puede tomar un momento.
for i in $(seq 1 20); do
RESTARTS="$(kubectl get pod "$LIVE_POD" -o jsonpath='{.status.containerStatuses[0].restartCount}')"
echo "restart-count=$RESTARTS"
if [ "$RESTARTS" != "0" ]; then
break
fi
sleep 3
done
La salida esperada eventualmente incluye:
restart-count=1
Después de que el contenedor se reinicia, el comando de inicio crea /tmp/healthy nuevamente. Confirma que el archivo ha vuelto:
kubectl exec "$LIVE_POD" -- test -f /tmp/healthy
echo "health file recreated"
Salida esperada:
health file recreated
Lee los eventos del Pod y busca el fallo de la sonda de liveness:
kubectl describe pod "$LIVE_POD" | sed -n '/Events:/,$p'
La salida esperada incluye:
Warning Unhealthy ... Liveness probe failed
Normal Killing ... Container web failed liveness probe
Resumen
Has configurado ambas sondas principales de la aplicación. La sonda de readiness controló cuándo los Pods se unían a los endpoints del Service, mientras que la sonda de liveness reinició un contenedor después de que su archivo de salud fuera eliminado. También inspeccionaste EndpointSlices, descripciones de Pods, contadores de reinicios y eventos para conectar la configuración de las sondas con el comportamiento visible de Kubernetes.


