Al final de la lección anterior tenías un clúster arrancado y verificado con un par de comandos prestados. Ahora vamos a por la herramienta en sí. kubectl es el cliente oficial de la API de Kubernetes y va a ser, con diferencia, el programa que más uses en este curso y en tu vida profesional con Kubernetes: crear, consultar, inspeccionar, depurar y borrar pasan todos por él. La buena noticia es que kubectl es extraordinariamente regular: una vez entiendes su gramática, sabes usarlo con cualquier tipo de objeto, incluidos los que aún no existen. Esta lección te enseña esa gramática, el fichero de configuración que decide con qué clúster hablas, los verbos que usarás a diario sobre los componentes de Rutas Norte, los formatos de salida que convierten kubectl en una herramienta de consulta seria, y los ajustes de productividad que separan a quien pelea con el clúster de quien trabaja con soltura.
Contenido
- Qué es kubectl e instalación
- El fichero kubeconfig: clústeres, usuarios y contextos
- Anatomía de un comando kubectl
- Los verbos del día a día
- Formatos de salida y consultas
- Selección por etiquetas y observación en vivo
- Imperativo frente a declarativo
- Productividad: alias, autocompletado, explain y plugins
- Qué es kubectl e instalación
kubectl no tiene inteligencia propia: traduce tus comandos a peticiones HTTPS contra el kube-apiserver. Todo lo que puede hacer kubectl lo podría hacer curl con el certificado adecuado; lo que aporta es comodidad, formato y validación local.
Consecuencia práctica: cualquier cosa que kubectl no te deje hacer, te la está prohibiendo el servidor (RBAC), no la herramienta.
Instalación
Linux:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
rm kubectlmacOS:
Windows (PowerShell):
Verificación:
Client Version: v1.30.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.0Regla de compatibilidad (version skew): kubectl admite una diferencia de una versión menor arriba o abajo respecto al servidor. Un cliente 1.30 funciona con servidores 1.29, 1.30 y 1.31. Con diferencias mayores pueden fallar comandos concretos de forma poco evidente, así que mantén el cliente cerca del servidor.
- El fichero kubeconfig: clústeres, usuarios y contextos
Cuando en la lección anterior minikube dijo "kubectl is now configured to use rutas-norte", lo que hizo fue escribir en ~/.kube/config. Ese fichero responde a tres preguntas: ¿a qué servidor hablo?, ¿con qué credenciales? y ¿en qué namespace por defecto?
# ~/.kube/config (simplificado)
apiVersion: v1
kind: Config
clusters: # A QUÉ servidor
- name: rutas-norte
cluster:
server: https://192.168.49.2:8443
certificate-authority: /home/usuario/.minikube/ca.crt
users: # CON QUÉ credenciales
- name: rutas-norte
user:
client-certificate: /home/usuario/.minikube/profiles/rutas-norte/client.crt
client-key: /home/usuario/.minikube/profiles/rutas-norte/client.key
contexts: # LA COMBINACIÓN de ambos + namespace
- name: rutas-norte
context:
cluster: rutas-norte
user: rutas-norte
namespace: default
current-context: rutas-norte # cuál está activo ahoraLa idea clave: un contexto es una terna (clúster, usuario, namespace). Cambiar de contexto es cambiar de clúster o de identidad con un solo comando. En un entorno profesional tendrás contextos como rutas-norte-dev, rutas-norte-pre y rutas-norte-pro, y equivocarte de contexto es la forma más rápida de provocar un incidente.
Comandos de gestión de contexto
# Ver todos los contextos disponibles; el activo lleva asterisco
kubectl config get-contexts
# Cambiar de contexto
kubectl config use-context rutas-norte
# Ver solo el nombre del contexto activo
kubectl config current-context
# Fijar el namespace por defecto del contexto activo
kubectl config set-context --current --namespace=rutas-norte-devCURRENT NAME CLUSTER AUTHINFO NAMESPACE
* rutas-norte rutas-norte rutas-norte rutas-norte-dev
docker-desktop docker-desktop docker-desktopEse último comando —fijar el namespace por defecto— te ahorrará escribir -n rutas-norte-dev cientos de veces durante el curso. Hazlo en cuanto crees el namespace en la lección 01-07.
Variable KUBECONFIG: puedes tener varios ficheros y combinarlos. Es lo habitual cuando trabajas con varios clientes o entornos:
Consejo de seguridad: el kubeconfig contiene credenciales. Trátalo como una clave privada: permisos
600, nunca en Git, nunca por chat.
- Anatomía de un comando kubectl
Toda la CLI sigue esta gramática:
kubectl [verbo] [tipo] [nombre] [banderas]
│ │ │ │
│ │ │ └── -n, -o, -l, --dry-run, --watch...
│ │ └─────────── nombre del objeto (opcional: si falta, todos)
│ └────────────────── pod, deployment, service, pvc, node...
└────────────────────────── get, describe, apply, delete, logs, exec...Ejemplos leídos en voz alta:
kubectl get pods # dame todos los pods del namespace actual
kubectl get pod api-reservas -n rutas-norte-dev # dame ese pod concreto de ese namespace
kubectl describe deployment tienda-web # explícame en detalle ese Deployment
kubectl delete pod api-reservas # borra ese podNombres, plurales y abreviaturas
Kubernetes acepta singular, plural y abreviatura indistintamente. kubectl get po, kubectl get pod y kubectl get pods son idénticos. Las abreviaturas que más ahorran:
| Tipo | Abreviatura | Tipo | Abreviatura |
|---|---|---|---|
pods |
po |
services |
svc |
deployments |
deploy |
namespaces |
ns |
replicasets |
rs |
configmaps |
cm |
statefulsets |
sts |
persistentvolumeclaims |
pvc |
daemonsets |
ds |
persistentvolumes |
pv |
ingresses |
ing |
serviceaccounts |
sa |
La lista completa y autoritativa de tu clúster, con abreviaturas, grupo de API y si el recurso vive en un namespace:
NAME SHORTNAMES APIVERSION NAMESPACED KIND
configmaps cm v1 true ConfigMap
pods po v1 true Pod
services svc v1 true Service
nodes no v1 false Node
deployments deploy apps/v1 true Deployment
ingresses ing networking.k8s.io/v1 true IngressLa columna NAMESPACED es importante: explica por qué kubectl get nodes -n rutas-norte-dev ignora el namespace (los nodos son de ámbito de clúster).
El namespace, siempre presente
kubectl get pods # namespace del contexto actual
kubectl get pods -n rutas-norte-pre # un namespace concreto
kubectl get pods -A # todos los namespaces (--all-namespaces)Olvidar el namespace es la causa número uno de "mi pod ha desaparecido".
- Los verbos del día a día
Trabajaremos sobre un escenario de Rutas Norte con la tienda web y la API ya desplegadas en rutas-norte-dev.
4.1. get — inventario rápido
NAME READY STATUS RESTARTS AGE
api-reservas-6c8d7f9b45-2xk9p 1/1 Running 0 12m
api-reservas-6c8d7f9b45-hn4vq 1/1 Running 0 12m
tienda-web-7d4f8c6b9-lq2mn 1/1 Running 0 18m
worker-notificaciones-59c7d8f 0/1 CrashLoopBackOff 5 (48s ago) 9mCómo leer cada columna:
- READY
1/1: contenedores listos / contenedores totales del pod.0/1significa que el contenedor existe pero no ha superado su sonda de disponibilidad. - STATUS:
Runninges lo normal;Pending(el scheduler no encuentra hueco),ContainerCreating,ImagePullBackOff(no puede descargar la imagen),CrashLoopBackOff(arranca y muere en bucle),Completed(tareas terminadas). - RESTARTS: reinicios. Un número que crece es la señal más clara de un problema.
- AGE: desde la creación del objeto.
En esa salida, worker-notificaciones está claramente roto. Los tres verbos siguientes son cómo se investiga.
4.2. describe — el diagnóstico
Name: worker-notificaciones-59c7d8f
Namespace: rutas-norte-dev
Node: rutas-norte/192.168.49.2
Labels: app=worker-notificaciones
app.kubernetes.io/part-of=rutas-norte
entorno=dev
Status: Running
Containers:
worker:
Image: registry.rutasnorte.example/worker-notificaciones:1.2.0
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1
Restart Count: 5
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 9m default-scheduler Successfully assigned ...
Normal Pulled 8m (x4 over 9m) kubelet Container image already present
Warning BackOff 45s (x22 over 8m) kubelet Back-off restarting failed containerLa sección Events es lo primero que hay que leer siempre. Es el diario de lo que el clúster ha intentado hacer con ese objeto y por qué ha fallado. Aquí nos dice que el contenedor termina con código 1 y el kubelet lo reintenta con espera creciente. También vemos que el scheduler sí lo asignó (luego no es un problema de recursos) y que la imagen se descargó bien (luego no es un problema de registro): el fallo está dentro de la aplicación.
describe funciona con cualquier tipo: kubectl describe node rutas-norte, kubectl describe svc api-reservas, kubectl describe pvc datos-postgres.
4.3. logs — la voz de la aplicación
# Últimas líneas del pod
kubectl logs worker-notificaciones-59c7d8f -n rutas-norte-dev
# Los logs de la ejecución ANTERIOR: imprescindible en CrashLoopBackOff
kubectl logs worker-notificaciones-59c7d8f -n rutas-norte-dev --previous
# Seguir en vivo, últimas 50 líneas, con marcas de tiempo
kubectl logs -f --tail=50 --timestamps api-reservas-6c8d7f9b45-2xk9p -n rutas-norte-dev
# Logs agregados de TODAS las réplicas seleccionadas por etiqueta
kubectl logs -l app=api-reservas -n rutas-norte-dev --tail=20
# Un contenedor concreto de un pod multicontenedor
kubectl logs mi-pod -c sidecar-metricas[2026-08-05T02:14:07Z] worker-notificaciones v1.2.0 arrancando
[2026-08-05T02:14:07Z] conectando a redis-cache:6379
[2026-08-05T02:14:12Z] ERROR: dial tcp: lookup redis-cache: no such host
[2026-08-05T02:14:12Z] proceso terminado con codigo 1Ahí está la causa: el worker no encuentra redis-cache por DNS, probablemente porque el Service aún no existe. --previous es la bandera que más se olvida y la más útil: sin ella, en un CrashLoopBackOff verás los logs de un contenedor que acaba de arrancar y aún no ha fallado.
4.4. exec — entrar en el contenedor
# Un comando puntual
kubectl exec api-reservas-6c8d7f9b45-2xk9p -n rutas-norte-dev -- env | grep DB_
# Sesión interactiva
kubectl exec -it api-reservas-6c8d7f9b45-2xk9p -n rutas-norte-dev -- shEl -- separa las banderas de kubectl del comando a ejecutar dentro; olvidarlo es un error clásico. -it significa interactivo con terminal, igual que en Docker.
Nota profesional: muchas imágenes bien construidas son distroless y no tienen ni sh ni herramientas de red. Para esos casos existe kubectl debug, que inyecta un contenedor efímero con utilidades; lo veremos en el módulo 7.
4.5. apply y delete — cambiar el estado deseado
kubectl apply -f k8s/base/api-reservas.yaml # un fichero
kubectl apply -f k8s/base/ # todos los del directorio
kubectl apply -f k8s/base/ --recursive # incluyendo subdirectorios
kubectl delete -f k8s/base/api-reservas.yaml # borrar lo que declara el fichero
kubectl delete pod api-reservas-6c8d7f9b45-2xk9p # borrar un objeto concreto
kubectl delete pods -l app=api-reservas # borrar por etiquetaapply es el corazón del modelo declarativo y lo estudiaremos a fondo en la próxima lección, Objetos, Manifiestos YAML y el Modelo Declarativo.
Sobre delete: recuerda que el borrado es asíncrono y que borrar un pod gestionado por un controlador no lo elimina, solo provoca que se cree uno nuevo. Para eliminarlo de verdad hay que borrar el controlador.
4.6. edit — modificación puntual en caliente
Abre el objeto en tu editor ($EDITOR) y al guardar aplica los cambios. Es cómodo para experimentar y peligroso en producción: el cambio no queda en Git, así que el siguiente apply desde el repositorio lo revertirá silenciosamente. Úsalo para explorar; nunca como forma de desplegar.
4.7. port-forward — acceso local sin exponer nada
Ahora http://localhost:8080 llega a ese pod. El formato es puerto-local:puerto-del-contenedor. También funciona contra un Service (svc/api-reservas 8081:80). Es la forma más rápida de comprobar que algo funciona antes de tener Ingress, y es exactamente lo que usarás en la lección 01-07 para ver la tienda de Rutas Norte en tu navegador. El proceso queda en primer plano: se corta con Ctrl+C.
4.8. explain — la documentación offline
KIND: Pod
VERSION: v1
FIELD: resources <ResourceRequirements>
DESCRIPTION:
Compute Resources required by this container. Cannot be updated.
FIELDS:
limits <map[string]Quantity>
Limits describes the maximum amount of compute resources allowed.
requests <map[string]Quantity>
Requests describes the minimum amount of compute resources required.Este comando merece un párrafo aparte porque es el que más rentabilidad tiene a largo plazo. Consulta el esquema de tu propio clúster, incluidos los CRDs instalados, así que nunca te da información desactualizada ni de otra versión. Funciona a cualquier profundidad y con --recursive muestra el árbol completo de campos:
En la certificación CKA/CKAD, donde solo se permite consultar la documentación oficial, kubectl explain es el atajo que ahorra minutos.
- Formatos de salida y consultas
La bandera -o transforma kubectl de visor en herramienta de consulta.
| Formato | Para qué sirve |
|---|---|
| (por defecto) | Tabla resumida legible |
-o wide |
Añade columnas: IP del pod, nodo, imagen |
-o yaml |
El objeto completo tal como está en la API, con su status |
-o json |
Igual, en JSON, para procesar con jq |
-o name |
Solo tipo/nombre, ideal para encadenar comandos |
-o jsonpath='...' |
Extrae campos concretos |
-o custom-columns=... |
Tabla a medida |
NAME READY STATUS IP NODE NOMINATED NODE
api-reservas-6c8d7f9b45-2xk9p 1/1 Running 10.244.0.17 rutas-norte <none>
tienda-web-7d4f8c6b9-lq2mn 1/1 Running 10.244.0.14 rutas-norte <none># El objeto completo, incluyendo lo que ha escrito el sistema
kubectl get pod api-reservas-6c8d7f9b45-2xk9p -n rutas-norte-dev -o yaml | head -25
# Extraer campos concretos con jsonpath
kubectl get pods -n rutas-norte-dev \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
# Tabla a medida: nombre, imagen y nodo
kubectl get pods -n rutas-norte-dev \
-o custom-columns='POD:.metadata.name,IMAGEN:.spec.containers[0].image,NODO:.spec.nodeName'
# Ordenar: los pods que más han reiniciado, primero
kubectl get pods -A --sort-by=.status.containerStatuses[0].restartCount
# Ordenar por antigüedad
kubectl get pods -n rutas-norte-dev --sort-by=.metadata.creationTimestampPOD IMAGEN NODO
api-reservas-6c8d7f9b45-2xk9p registry.rutasnorte.example/api-reservas:2.4.0 rutas-norte
tienda-web-7d4f8c6b9-lq2mn registry.rutasnorte.example/tienda-web:1.8.0 rutas-nortecustom-columns y jsonpath son las dos herramientas que convierten a kubectl en algo apto para auditorías rápidas: "dame todas las imágenes en uso en producción", "dime qué pods no tienen límites de memoria".
- Selección por etiquetas y observación en vivo
Recuerda de la lección Conceptos y Terminología Clave que las etiquetas son el mecanismo de acoplamiento del sistema. La bandera -l te da acceso a ese mismo mecanismo desde la CLI:
# Igualdad
kubectl get pods -l app=api-reservas -n rutas-norte-dev
# Varias condiciones (AND)
kubectl get pods -l app=api-reservas,entorno=dev -n rutas-norte-dev
# Desigualdad
kubectl get pods -l 'entorno!=pro' -A
# Conjuntos
kubectl get pods -l 'app in (api-reservas,tienda-web)' -n rutas-norte-dev
kubectl get pods -l 'app notin (informes-ocupacion)' -n rutas-norte-dev
# Existencia de la clave, con cualquier valor
kubectl get pods -l app.kubernetes.io/part-of -A
# Toda la plataforma Rutas Norte, de cualquier tipo, de una sola vez
kubectl get all -l app.kubernetes.io/part-of=rutas-norte -AEsa última consulta es la razón por la que merece la pena ser disciplinado con el esquema de etiquetas del proyecto: te permite ver, borrar o inspeccionar la plataforma entera con un solo comando.
Observación en vivo con --watch (o -w): el comando no termina y va imprimiendo los cambios conforme ocurren. Es la mejor forma de ver el bucle de reconciliación en acción:
NAME READY STATUS RESTARTS AGE
api-reservas-6c8d7f9b45-2xk9p 1/1 Running 0 12m
api-reservas-6c8d7f9b45-2xk9p 1/1 Terminating 0 14m
api-reservas-6c8d7f9b45-wq7rt 0/1 Pending 0 0s
api-reservas-6c8d7f9b45-wq7rt 0/1 ContainerCreating 0 1s
api-reservas-6c8d7f9b45-wq7rt 1/1 Running 0 4sReconoces esa secuencia: es exactamente el recorrido de la lección Arquitectura de Kubernetes —Pending mientras el scheduler decide, ContainerCreating mientras el kubelet trabaja, Running cuando el contenedor vive— ocurriendo ante tus ojos porque el ReplicaSet ha repuesto un pod borrado.
Comandos hermanos que también esperan:
kubectl wait --for=condition=Ready pod -l app=api-reservas -n rutas-norte-dev --timeout=60s
kubectl get events -n rutas-norte-dev --watch
- Imperativo frente a declarativo
kubectl admite los dos estilos y conviene tener criterio sobre cuándo usar cada uno.
| Aspecto | Imperativo | Declarativo |
|---|---|---|
| Comando típico | kubectl create deployment ..., kubectl scale, kubectl expose |
kubectl apply -f k8s/ |
| Fuente de verdad | El historial de tu terminal | Los ficheros del repositorio |
| Reproducible | No | Sí |
| Revisable en un pull request | No | Sí |
| Velocidad para algo puntual | Muy alta | Media |
| Uso recomendado | Aprender, pruebas rápidas, exámenes cronometrados | Todo lo que llegue a un entorno real |
# Imperativo: rápido, pero no queda rastro en ningún fichero
kubectl create deployment api-reservas --image=registry.rutasnorte.example/api-reservas:2.4.0
kubectl scale deployment api-reservas --replicas=4
kubectl expose deployment api-reservas --port=80 --target-port=3000
# Declarativo: el estado deseado vive en Git
kubectl apply -f k8s/base/api-reservas.yamlEl punto intermedio, y probablemente el truco más útil de toda la lección: generar el manifiesto con un comando imperativo y guardarlo, usando --dry-run=client -o yaml.
kubectl create deployment api-reservas \
--image=registry.rutasnorte.example/api-reservas:2.4.0 \
--dry-run=client -o yaml > k8s/base/api-reservas.yamlEsto no crea nada en el clúster: solo imprime el YAML que kubectl habría enviado. Lo editas, lo versionas y lo aplicas. Es la forma habitual de no escribir manifiestos desde cero, y en la CKAD es prácticamente obligatorio para llegar a tiempo. La próxima lección profundiza en --dry-run, kubectl diff y la mecánica interna de apply.
- Productividad: alias, autocompletado, explain y plugins
Añade esto a tu ~/.bashrc o ~/.zshrc. La diferencia de comodidad es enorme:
# Autocompletado (bash)
source <(kubectl completion bash)
# Alias corto y autocompletado también para el alias
alias k=kubectl
complete -o default -F __start_kubectl k
# Atajos habituales
alias kgp='kubectl get pods'
alias kgpw='kubectl get pods -o wide'
alias kd='kubectl describe'
alias kl='kubectl logs'
alias kaf='kubectl apply -f'
alias kns='kubectl config set-context --current --namespace'Para zsh, sustituye completion bash por completion zsh. Con esto, k get po -n <TAB> te completa incluso los nombres de los namespaces existentes, porque el autocompletado consulta la API.
Otras herramientas que conviene conocer, aunque no las usemos aún:
| Herramienta | Qué aporta |
|---|---|
| krew | Gestor de plugins de kubectl (kubectl krew install ...) |
kubectl ctx / kubectl ns (plugins ctx y ns) |
Cambiar de contexto y namespace de forma interactiva |
kubectl tree |
Ver la jerarquía Deployment → ReplicaSet → Pod |
kubectl neat |
Limpia un -o yaml de campos generados por el sistema |
stern |
Logs agregados y coloreados de muchos pods a la vez |
k9s |
Interfaz de terminal para navegar el clúster |
Instalar krew y un plugin, a modo de ejemplo:
Nada de esto es imprescindible, pero en un día de trabajo real ahorra horas. Lo esencial es lo anterior: alias, autocompletado y kubectl explain.
Errores Comunes y Consejos
- Trabajar en el contexto equivocado. El error más caro de todos. Antes de cualquier comando destructivo,
kubectl config current-context. Configura tu prompt para mostrar contexto y namespace (kube-ps1, starship, oh-my-zsh) y trátalo como innegociable en cuanto tengas acceso a un entorno de producción. - Olvidar el namespace. Si un objeto "no existe", pruébalo con
-Aantes de concluir nada. Fija el namespace por defecto conkubectl config set-context --current --namespace=.... - Leer
logssin--previousen unCrashLoopBackOff. Verás el arranque del contenedor actual, no el error que mató al anterior. - Omitir el
--enkubectl exec. Sin él, kubectl interpreta las banderas de tu comando como suyas y falla de forma confusa. - Usar
kubectl editcomo método de despliegue. El cambio no queda en ningún sitio y se pierde en el siguienteapply. Sirve para investigar, no para operar. - Creer que
kubectl delete podelimina la aplicación. Si hay un controlador detrás, el pod vuelve. Hay que borrar el Deployment, o mejor, el manifiesto conkubectl delete -f. - Ignorar
kubectl explain. Es documentación exacta de tu versión, sin conexión a internet y sin cambiar de ventana. Acostúmbrate a usarlo antes que a buscar en la web. - Consejo: memoriza este trío de diagnóstico y aplícalo siempre en este orden —
kubectl get(¿existe y en qué estado?),kubectl describe(¿qué ha intentado el clúster y qué dicen los eventos?),kubectl logs(¿qué dice la aplicación?). Resuelve la gran mayoría de las incidencias.
Ejercicios
Ejercicio 1: Contexto, namespace y exploración
Sobre tu clúster rutas-norte:
- Muestra el contexto activo y comprueba que es el correcto.
- Crea el namespace
rutas-norte-devy fíjalo como namespace por defecto del contexto. - Lista todos los pods del clúster, de todos los namespaces, mostrando el nodo y la IP.
- Averigua, sin salir de la terminal y sin buscar en internet, qué significa el campo
spec.restartPolicyde un pod y qué valores admite. - Muestra los pods de
kube-systemordenados por antigüedad, del más antiguo al más reciente.
Ejercicio 2: Consultas avanzadas de auditoría
El equipo de seguridad de Rutas Norte pide un inventario. Escribe los comandos que responden a:
- Todas las imágenes en uso en el clúster, con el pod y el namespace al que pertenecen, en formato de tabla.
- Los pods de todo el clúster ordenados por número de reinicios, para localizar los inestables.
- Solo los nombres de los pods que tengan la etiqueta
app.kubernetes.io/part-of=rutas-norte, en formato apto para encadenar con otro comando. - Todos los recursos del clúster que no viven en un namespace.
Ejercicio 3: Del imperativo al declarativo
Sin crear nada en el clúster, genera el manifiesto YAML de un pod llamado tienda-web con la imagen registry.rutasnorte.example/tienda-web:1.8.0, guárdalo en k8s/base/tienda-web-pod.yaml, y después explica qué diferencia hay entre ejecutar ese comando con --dry-run=client y sin él. Como comprobación adicional, averigua con kubectl si el recurso Pod pertenece al grupo de API core o a apps.
Soluciones
Solución 1
# 1
kubectl config current-context # -> rutas-norte
# 2
kubectl create namespace rutas-norte-dev
kubectl config set-context --current --namespace=rutas-norte-dev
# 3
kubectl get pods -A -o wide
# 4
kubectl explain pod.spec.restartPolicyFIELD: restartPolicy <string>
DESCRIPTION:
Restart policy for all containers within the pod. One of Always, OnFailure,
Never. Default to Always.Solución 2
# 1
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,POD:.metadata.name,IMAGEN:.spec.containers[*].image'
# 2
kubectl get pods -A --sort-by=.status.containerStatuses[0].restartCount
# 3
kubectl get pods -A -l app.kubernetes.io/part-of=rutas-norte -o name
# 4
kubectl api-resources --namespaced=falseEl punto 3 devuelve líneas del tipo pod/api-reservas-6c8d7f9b45-2xk9p, que pueden pasarse directamente a kubectl delete o kubectl describe. El punto 4 lista nodes, namespaces, persistentvolumes, storageclasses, clusterroles, entre otros: los recursos de ámbito de clúster que vimos en la lección de conceptos.
Solución 3
kubectl run tienda-web \
--image=registry.rutasnorte.example/tienda-web:1.8.0 \
--dry-run=client -o yaml > k8s/base/tienda-web-pod.yamlDiferencia: con --dry-run=client, kubectl construye el objeto localmente y lo imprime, sin enviar nada al servidor; no se crea ningún pod y no hace falta ni que el clúster esté arrancado. Sin esa bandera, la petición se envía al apiserver, pasa autenticación, autorización y admisión, se escribe en etcd y el pod se crea de verdad. Existe además --dry-run=server, que sí envía la petición pero le indica al servidor que no persista: valida contra los webhooks de admisión reales sin crear nada. Lo veremos en la próxima lección.
Para el grupo de API:
La columna APIVERSION muestra v1 a secas, sin barra ni prefijo de grupo: eso significa que Pod pertenece al grupo core (o "legacy"), a diferencia de Deployment, que aparece como apps/v1.
Conclusión
kubectl es un cliente HTTP con una gramática muy regular: verbo, tipo, nombre y banderas. Dominarlo consiste en interiorizar esa gramática, saber siempre en qué contexto y namespace estás trabajando, manejar con soltura el trío de diagnóstico get → describe → logs, y aprovechar los formatos de salida y la selección por etiquetas para convertir la CLI en una herramienta de consulta real. Con kubectl explain tienes además documentación exacta de tu propio clúster sin salir de la terminal, y con los alias y el autocompletado el trabajo diario deja de ser tecleo.
En esta lección hemos usado apply sin explicar del todo qué hace por dentro, y hemos visto manifiestos YAML sin desmenuzar su estructura. Esa deuda la salda la siguiente lección, Objetos, Manifiestos YAML y el Modelo Declarativo: anatomía campo a campo de un objeto, grupos y versiones de la API, el YAML que hace falta saber, la diferencia real entre apply, create y replace, las herramientas de validación previa y cómo organizar los manifiestos de Rutas Norte en el directorio k8s/.
Curso de Kubernetes
Módulo 1: Introducción a Kubernetes
- ¿Qué es Kubernetes?
- Arquitectura de Kubernetes
- Conceptos y Terminología Clave
- Configuración de un Clúster de Kubernetes
- La CLI de Kubernetes: kubectl
- Objetos, Manifiestos YAML y el Modelo Declarativo
- El Proyecto del Curso: la Plataforma Rutas Norte
Módulo 2: Componentes Principales de Kubernetes
- Pods
- ReplicaSets
- Deployments
- Actualizaciones, Rollbacks y Estrategias de Despliegue
- Servicios
- Namespaces
- Etiquetas, Selectores y Anotaciones
Módulo 3: Gestión de Configuración y Secretos
- ConfigMaps
- Secrets
- Variables de Entorno
- Cuotas y Límites de Recursos
- LimitRanges y Clases de Calidad de Servicio (QoS)
- ServiceAccounts y Acceso a la API desde los Pods
Módulo 4: Redes en Kubernetes
- Redes de Clúster
- Tipos de Servicios
- DNS Interno y Descubrimiento de Servicios
- Controladores de Ingress
- TLS y Gestión de Certificados con cert-manager
- Políticas de Red
Módulo 5: Almacenamiento en Kubernetes
- Volúmenes
- Volúmenes Persistentes
- Reclamaciones de Volúmenes Persistentes
- Clases de Almacenamiento
- Aprovisionamiento Dinámico, Expansión y Snapshots
- Copias de Seguridad y Restauración de Datos
Módulo 6: Conceptos Avanzados de Kubernetes
- StatefulSets
- DaemonSets
- Trabajos y CronJobs
- Init Containers, Sidecars y Patrones Multi-Contenedor
- Planificación: Afinidad, Taints y Tolerations
- Definiciones de Recursos Personalizados (CRDs)
- Operadores y el Patrón Controlador
Módulo 7: Monitoreo y Registro
- Verificaciones de Salud y Sondas
- Servidor de Métricas y kubectl top
- Monitoreo con Prometheus
- Visualización y Alertas con Grafana y Alertmanager
- Registro Centralizado con Elasticsearch, Fluentd y Kibana (EFK)
- Depuración de Aplicaciones y Eventos del Clúster
Módulo 8: Seguridad en Kubernetes
- Control de Acceso Basado en Roles (RBAC)
- Contextos de Seguridad y Endurecimiento del Contenedor
- Políticas de Seguridad de Pods y Pod Security Standards
- Seguridad de Red
- Seguridad de Imágenes
- Auditoría, Escaneo y Gestión de Vulnerabilidades
Módulo 9: Escalado y Rendimiento
- Autoescalado Horizontal de Pods
- Autoescalado Vertical de Pods
- Autoescalado de Clúster
- Escalado por Eventos y Métricas Personalizadas con KEDA
- Alta Disponibilidad: PodDisruptionBudgets y Topología
- Ajuste de Rendimiento
Módulo 10: Ecosistema y Herramientas de Kubernetes
- Minikube y Entornos Locales con kind
- Kubeadm
- Helm
- Kustomize
- GitOps con Argo CD y Flux
- Kubernetes Gestionado: EKS, AKS y GKE
Módulo 11: Estudios de Caso y Aplicaciones del Mundo Real
- Despliegue de una Aplicación Web
- Ejecución de Aplicaciones con Estado
- CI/CD con Kubernetes
- Estrategias de Despliegue: Blue-Green y Canary
- Gestión Multi-Clúster
- Operación en Producción: Incidencias, Runbooks y Costes
