kubectl es la herramienta de línea de comandos oficial para hablar con la API de un clúster de Kubernetes: con ella consultas recursos, aplicas manifiestos, lees logs y depuras pods. En este tutorial instalarás kubectl en Ubuntu 24.04, lo conectarás a un clúster y recorrerás los comandos que se usan a diario con un ejemplo real: un Deployment de Nginx que crearás, expondrás, escalarás, actualizarás y depurarás.

Requisitos previos

  • Una máquina con Ubuntu 24.04 LTS desde la que administrar el clúster (tu equipo o un VPS de CubePath) y un usuario con privilegios sudo.
  • Acceso a un clúster de Kubernetes y su archivo kubeconfig. Sirve un clúster gestionado, uno creado con kubeadm o un clúster de pruebas con k3s.
  • Permisos en el clúster para crear recursos en un namespace (los ejemplos usan uno propio llamado demo).

La sintaxis general de kubectl es siempre la misma:

kubectl <verbo> <tipo> [nombre] [opciones]

Por ejemplo, kubectl get pods -n demo o kubectl describe deployment web. Si dudas de un comando, kubectl <verbo> --help muestra todas sus opciones con ejemplos.

Paso 1: Instalar kubectl

Instala kubectl desde el repositorio oficial de Kubernetes (pkgs.k8s.io). Cada versión menor tiene su propio repositorio; elige la misma versión menor que tu clúster o una adyacente, porque kubectl solo está soportado con una diferencia de una versión menor respecto al servidor. Los ejemplos usan v1.34: cámbiala por la de tu clúster.

Instala las dependencias y descarga la clave del repositorio:

sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg

Añade el repositorio e instala el paquete:

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubectl

Comprueba la versión instalada:

kubectl version --client
Client Version: v1.34.1
Kustomize Version: v5.7.1

Paso 2: Configurar el acceso al clúster con kubeconfig

kubectl lee la configuración de conexión (servidor de la API, certificados y credenciales) de ~/.kube/config. Copia ahí el kubeconfig que te haya dado tu proveedor o el de tu clúster, y restringe sus permisos porque contiene credenciales:

mkdir -p ~/.kube
cp /ruta/a/tu-kubeconfig.yaml ~/.kube/config
chmod 600 ~/.kube/config

Verifica que llegas a la API y que los nodos están listos:

kubectl cluster-info
kubectl get nodes
NAME       STATUS   ROLES           AGE   VERSION
node-1     Ready    control-plane   12d   v1.34.1
node-2     Ready    <none>          12d   v1.34.1

Trabajar con varios clústeres y contextos

Un contexto combina un clúster, un usuario y un namespace por defecto. Estos comandos cubren casi todo lo que necesitarás:

kubectl config get-contexts
kubectl config current-context
kubectl config use-context nombre-del-contexto

Si tienes varios kubeconfig, puedes indicar el archivo en cada comando con --kubeconfig=/ruta/archivo o combinarlos con la variable KUBECONFIG:

export KUBECONFIG=~/.kube/config:~/.kube/config-staging
kubectl config get-contexts

Para fusionarlos en un solo archivo de forma permanente, genera uno nuevo con --flatten, revísalo y sustituye el original:

kubectl config view --flatten > ~/.kube/config-merged
chmod 600 ~/.kube/config-merged

Paso 3: Crear un namespace de trabajo

Los namespaces separan recursos dentro de un mismo clúster. Crea uno para los ejemplos y fíjalo como namespace por defecto del contexto actual, así no tendrás que escribir -n demo en cada comando:

kubectl create namespace demo
kubectl config set-context --current --namespace=demo

Comprueba que el cambio se ha aplicado:

kubectl config view --minify -o jsonpath='{..namespace}'
demo

Paso 4: Crear recursos con apply y dry-run

Hay dos formas de crear recursos: imperativa (kubectl create deployment ...) y declarativa (kubectl apply -f archivo.yaml). La declarativa es la que conviene usar en el día a día porque el YAML queda versionado y puedes volver a aplicarlo tras cada cambio.

Un truco útil es generar el YAML inicial con un comando imperativo en modo --dry-run=client, que no crea nada en el clúster:

kubectl create deployment web --image=nginx:1.27 --replicas=2 --dry-run=client -o yaml > web.yaml

Revisa el archivo generado y aplícalo:

kubectl apply -f web.yaml
deployment.apps/web created

Expón el Deployment con un Service de tipo ClusterIP en el puerto 80:

kubectl expose deployment web --port=80 --target-port=80

Antes de aplicar cambios futuros sobre web.yaml, kubectl diff muestra qué va a cambiar en el clúster respecto a lo que hay desplegado:

kubectl diff -f web.yaml

Si no hay diferencias, el comando no imprime nada.

Paso 5: Consultar recursos con get, describe y explain

kubectl get lista recursos. Algunas variantes que usarás continuamente:

kubectl get pods
kubectl get pods -o wide
kubectl get deploy,svc,pods
kubectl get pods -A
kubectl get pods -l app=web
kubectl get pods --watch
NAME                   READY   STATUS    RESTARTS   AGE
web-7c5b8d6f4d-9xkzq   1/1     Running   0          40s
web-7c5b8d6f4d-tq2lm   1/1     Running   0          40s

-o wide añade la IP del pod y el nodo, -A consulta todos los namespaces, -l filtra por etiqueta y --watch se queda mostrando cambios hasta que pulses Ctrl+C. También puedes filtrar por campos del objeto:

kubectl get pods -A --field-selector=status.phase!=Running

kubectl describe muestra el detalle de un recurso e incluye, al final, los eventos recientes. Es el primer sitio donde mirar cuando algo no arranca:

kubectl describe deployment web
kubectl describe pod web-7c5b8d6f4d-9xkzq

kubectl explain documenta cualquier campo de la API sin salir de la terminal, útil al escribir manifiestos:

kubectl explain deployment.spec.strategy

Para ver los tipos de recursos disponibles en el clúster y sus nombres cortos (po, svc, deploy, cm...):

kubectl api-resources

Paso 6: Depurar pods con logs, exec y port-forward

Lee los logs de un pod, o de todos los pods de un Deployment, con kubectl logs:

kubectl logs deployment/web
kubectl logs -f web-7c5b8d6f4d-9xkzq --tail=50
kubectl logs web-7c5b8d6f4d-9xkzq --previous

-f sigue el log en tiempo real, --tail limita las líneas y --previous muestra el log del contenedor anterior, imprescindible cuando un pod está en CrashLoopBackOff. Si el pod tiene varios contenedores, añade -c nombre-contenedor.

Para abrir una shell dentro de un contenedor:

kubectl exec -it deployment/web -- sh

Dentro, comprueba por ejemplo la configuración de Nginx con nginx -t y sal con exit.

Para probar un Service desde tu máquina sin exponerlo a Internet, redirige un puerto local:

kubectl port-forward service/web 8080:80

En otra terminal:

curl -sI http://127.0.0.1:8080
HTTP/1.1 200 OK
Server: nginx/1.27.5

Para probar la conectividad desde dentro del clúster, lanza un pod temporal con curl que se borra al terminar:

kubectl run tmp-curl --rm -it --restart=Never --image=curlimages/curl -- curl -s http://web

Los eventos del namespace suelen explicar fallos de programación, de descarga de imagen o de montaje de volúmenes:

kubectl get events --sort-by=.metadata.creationTimestamp

kubectl top muestra el consumo de CPU y memoria, pero requiere que el clúster tenga instalado metrics-server:

kubectl top nodes
kubectl top pods

Paso 7: Escalar, actualizar y revertir Deployments

Cambia el número de réplicas:

kubectl scale deployment web --replicas=3

Actualiza la imagen del contenedor nginx (el nombre que asignó kubectl create deployment) y sigue el despliegue hasta que termine:

kubectl set image deployment/web nginx=nginx:1.28
kubectl rollout status deployment/web
Waiting for deployment "web" rollout to finish: 1 out of 3 new replicas have been updated...
deployment "web" successfully rolled out

Si la nueva versión falla, consulta el historial y vuelve a la revisión anterior:

kubectl rollout history deployment/web
kubectl rollout undo deployment/web

Para reiniciar todos los pods de un Deployment sin cambiar su definición (por ejemplo, tras actualizar un Secret que se lee al arrancar):

kubectl rollout restart deployment/web

Paso 8: Formatear la salida con JSONPath y columnas personalizadas

Cualquier get acepta -o yaml o -o json para ver el objeto completo. Cuando solo necesitas un campo, por ejemplo en un script, usa JSONPath:

kubectl get pods -l app=web -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
web-6f8d9b7c5-2hxvp	10.42.1.15
web-6f8d9b7c5-8kq4n	10.42.2.21
web-6f8d9b7c5-zr7lm	10.42.1.16

Las columnas personalizadas dan una tabla legible con los campos que elijas:

kubectl get pods -o custom-columns=NOMBRE:.metadata.name,NODO:.spec.nodeName,IMAGEN:.spec.containers[0].image

Y -o name devuelve solo tipo/nombre, cómodo para encadenar con otros comandos:

kubectl get pods -l app=web -o name

Paso 9: Etiquetar y eliminar recursos

Las etiquetas permiten agrupar y filtrar recursos. Añade, modifica o quita una etiqueta así:

kubectl label deployment web entorno=pruebas
kubectl label deployment web entorno=produccion --overwrite
kubectl label deployment web entorno-

Elimina recursos por nombre, por archivo o por etiqueta:

kubectl delete -f web.yaml
kubectl delete service web

Borrar un namespace elimina todo lo que contiene, así que úsalo con cuidado. Para limpiar el ejemplo de esta guía y volver al namespace default:

kubectl config set-context --current --namespace=default
kubectl delete namespace demo

Paso 10: Activar el autocompletado y un alias

El autocompletado de Bash completa verbos, tipos y nombres de recursos con el tabulador. Instala bash-completion y añade kubectl a tu ~/.bashrc, junto con el alias k y su autocompletado:

sudo apt install -y bash-completion
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
source ~/.bashrc

Comprueba que funciona escribiendo k get po y pulsando el tabulador: deberían aparecer los nombres de los pods. Si usas Zsh, el equivalente es source <(kubectl completion zsh) en ~/.zshrc.

Solución de problemas

  • The connection to the server localhost:8080 was refused: kubectl no encuentra un kubeconfig. Comprueba que existe ~/.kube/config o que la variable KUBECONFIG apunta al archivo correcto.
  • error: You must be logged in to the server (Unauthorized): las credenciales del kubeconfig han caducado o no son válidas. Descarga de nuevo el kubeconfig desde tu proveedor o regenera el certificado del usuario.
  • Error from server (Forbidden): tu usuario no tiene permisos RBAC para esa acción. Compruébalo con kubectl auth can-i create deployments -n demo.
  • Aviso de versiones incompatibles: si kubectl version avisa de que el cliente y el servidor difieren en más de una versión menor, cambia el repositorio del paso 1 a la versión de tu clúster.
  • Pod en ImagePullBackOff o Pending: revisa la sección Events de kubectl describe pod y los eventos del namespace; suelen indicar una imagen mal escrita, falta de credenciales del registro o falta de recursos en los nodos.

Conclusión

Has instalado kubectl desde el repositorio oficial, lo has conectado a tu clúster y has usado los comandos que cubren la mayor parte del trabajo diario: gestionar contextos y namespaces, aplicar manifiestos, inspeccionar recursos, depurar pods y controlar los despliegues. A partir de aquí puedes publicar tus aplicaciones hacia Internet con un Ingress y un certificado TLS, dar almacenamiento persistente a tus pods con PersistentVolumeClaims o empaquetar tus manifiestos con Helm o Kustomize (kubectl apply -k).