kubectl imperativo
Inspeccionar y depurar
Llevas todo el curso escribiendo YAML, y está bien: lo declarativo es la forma correcta de definir sistemas. Pero cuando algo arde a las tres de la mañana, nadie abre el editor: se abre una terminal y se interroga al clúster. Este módulo entrena esa otra mitad del oficio, y lo hace en formato misión: el namespace tienda de este playground esconde datos que solo encontrarás usando los comandos adecuados.
El escenario: un Deployment api con historia (cuatro revisiones y contando), un Service, un Secret con credenciales, y un Pod llamado worker-legacy del que nadie se fía. Trabaja desde la pestaña dev-machine.
El arsenal de inspección
Las preguntas de siempre y el comando que las responde, directamente del libro:
¿Cómo veo de un vistazo los recursos principales de un Namespace?
kubectl get all -n tienda
Ojo con la mentira piadosa del nombre: get all no incluye ConfigMaps, Secrets, Ingress ni PersistentVolumeClaims. Compruébalo: el Secret que verás más adelante no aparece.
¿Cómo listo los Pods con el nodo asignado y más detalle?
kubectl get pods -n tienda -o wide
¿Cómo busco Pods por etiqueta en todos los Namespaces?
kubectl get pods -A -l app=api
Las etiquetas admiten combinaciones (-l app=api,env=prod). Es el mismo mecanismo de selección que usan los Services y los Deployments, ahora al servicio de tus dedos.
¿Cómo veo qué imagen está usando cada Pod?
kubectl get pods -n tienda -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
El formato jsonpath parece críptico la primera vez y se vuelve adictivo la tercera: extrae exactamente el campo que quieres, sin ruido.
¿Cómo listo los recursos ordenados por fecha de creación?
kubectl get all -n tienda --sort-by=.metadata.creationTimestamp
Misión 1: la ejecución anterior de worker-legacy
El Pod worker-legacy aparece Running y con cara de inocente, pero fíjate en su columna RESTARTS: se ha caído al menos una vez. El equipo quiere saber el código del fallo con el que terminó en su primer arranque.
El truco está en que kubectl logs tiene memoria corta: muestra el contenedor actual. Para escuchar a la ejecución anterior:
¿Cómo veo los logs del contenedor anterior cuando el Pod se ha caído?
kubectl logs worker-legacy -n tienda --previous
Compáralo con los logs sin --previous: el contenedor actual no ha dicho ni palabra. Otras variantes de la familia que conviene tener a mano:
kubectl logs -n tienda deploy/api | grep ERROR
kubectl logs -f -l app=api -n tienda --all-containers=true
La primera filtra por texto (y acepta el nombre del Deployment directamente, sin buscar el Pod); la segunda sigue en tiempo real los logs de todos los Pods de una etiqueta.
Misión 2: la variable plantada
Los Pods del Deployment api llevan una variable de entorno DATABASE_URL que nadie documentó. Necesitas su valor exacto.
Las variables de un proceso se consultan desde dentro del proceso, y para eso está exec:
¿Cómo ejecuto un comando puntual sin entrar en shell?
kubectl exec -n tienda deploy/api -- printenv DATABASE_URL
¿Cómo abro una shell dentro de un Pod, para explorar con calma?
kubectl exec -it <pod> -n tienda -- /bin/sh
Y las dos herramientas que completan el kit de diagnóstico de cualquier Pod, que ya conoces del curso pero ahora con sus variantes finas:
kubectl describe pod <pod> -n tienda
kubectl get events -n tienda --field-selector involvedObject.name=<pod> --sort-by='.lastTimestamp'
La segunda extrae los eventos de un objeto concreto, ordenados: oro cuando el describe se queda corto porque los eventos ya rotaron.
El kit de red, para cuando toque
Tres comandos de depuración de red que no necesitan misión pero sí sitio en tu memoria:
kubectl port-forward svc/api 8080:80 -n tienda
kubectl cp tienda/<pod>:/ruta/al/fichero ./fichero-local
kubectl run debug --image=ghcr.io/iximiuz/labs/nginx:alpine -it --rm -- /bin/sh
El primero redirige un puerto local al Service (también funciona con pod/<nombre>); pruébalo y verás nginx en curl localhost:8080 desde otra terminal mientras el túnel viva. El segundo copia ficheros entre un Pod y tu máquina. El tercero levanta un Pod temporal (--rm lo borra al salir) para husmear la red desde dentro del clúster; el libro usa la imagen nicolaka/netshoot, la navaja suiza de red, cuando el registro lo permite.
En la siguiente unidad pasas de mirar a tocar: escalado, rollbacks quirúrgicos y el contenido de ese Secret.
Actuar sobre el clúster
Inspeccionar era la mitad del trabajo. La otra mitad es intervenir: escalar, revertir, reiniciar, leer secretos. Mismo escenario, misiones nuevas.
Misión 3: la contraseña del Secret
Alguien necesita la contraseña guardada en el Secret db-credentials del namespace tienda, y la necesita ya. Recuerda dos cosas del módulo de configuración: los Secrets guardan sus valores en base64, y base64 no es cifrado.
¿Cómo extraigo un Secret y lo decodifico en una sola línea?
kubectl get secret db-credentials -n tienda -o jsonpath='{.data.password}' | base64 --decode
La pareja de esta pregunta, para configuración no sensible:
¿Cómo edito un ConfigMap directamente en el clúster?
kubectl edit configmap <nombre> -n tienda
kubectl edit abre el objeto vivo en tu editor y aplica al guardar. Potente y peligroso a partes iguales: el cambio no queda en ningún fichero tuyo. En la siguiente lección verás la alternativa civilizada.
Misión 4: pico de tráfico
Marketing acaba de lanzar una campaña sin avisar (como siempre) y el Deployment api necesita pasar de 3 a 5 réplicas ahora mismo.
¿Cómo escalo un Deployment?
kubectl scale deployment/api --replicas=5 -n tienda
Y las herramientas para vigilar que el clúster aguanta el cambio:
kubectl top pods -n tienda --sort-by=memory
kubectl top nodes
kubectl get pods -A --field-selector spec.nodeName=<nodo>
Las dos primeras ya las conoces de la lección del HPA; la tercera responde una pregunta que tarde o temprano harás: qué Pods corren en un nodo concreto (útil antes de un mantenimiento).
Misión 5: la revisión buena era otra
Llega un mensaje del equipo: la versión actual de api (con APP_MODE=estable) tiene un bug sutil, y la anterior versión buena conocida es la que llevaba APP_MODE=beta. Hay que volver exactamente a esa, y no vale adivinar: hay que consultarlo.
¿Cómo veo el historial de versiones de un Deployment?
kubectl rollout history deployment/api -n tienda
kubectl rollout history deployment/api -n tienda --revision=2
La segunda forma muestra la plantilla de una revisión concreta: así identificas cuál llevaba qué antes de saltar.
¿Cómo revierto a una revisión concreta?
kubectl rollout undo deployment/api --to-revision=<n> -n tienda
¿Y cómo vigilo que la vuelta atrás converge?
kubectl rollout status deployment/api -n tienda
Completa la familia rollout un comando que no revierte nada pero salva días enteros:
kubectl rollout restart deployment/api -n tienda
Reinicia todos los Pods del Deployment de forma gradual, sin downtime. Es el "apaga y enciende" elegante de Kubernetes: imprescindible cuando cambias un ConfigMap montado y quieres que los Pods relean su configuración.
El toque final: los alias
Ningún operador de Kubernetes escribe kubectl get pods letra a letra doscientas veces al día. En tu ~/.bashrc o ~/.zshrc:
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgpa='kubectl get pods -A'
alias kl='kubectl logs -f'
alias kx='kubectl exec -it'
export do='--dry-run=client -o yaml'
💡 Ese último export es el puente hacia la próxima lección: k create deploy api --image=nginx $do > deploy.yaml genera el manifiesto sin crear nada. El modo imperativo escribiendo YAML para el modo declarativo: lo mejor de los dos mundos.
Resumen
- Inspección:
get(con-o wide,-l,-A,jsonpath,--sort-by),describe,events --field-selector. - Depuración:
logs(con--previous,-f,-l,deploy/),exec,port-forward,cp, Pods temporales con--rm. - Acción:
scale, la familiarolloutcompleta (status, history, undo,--to-revision, restart),edit. - Y la salida elegante:
--dry-run=client -o yaml, que convierte todo lo imperativo en ficheros declarativos.
- Previous lesson
- Dispositivos y Dynamic Resource Allocation
- Next lesson
- kubectl declarativo