Es habitual trabajar con varios clústeres de Kubernetes a la vez: uno de desarrollo y otro de producción, o uno por región. kubectl lo resuelve con los contextos del fichero kubeconfig, pero sin orden es fácil lanzar un comando en el clúster equivocado. En este tutorial combinarás los kubeconfig de dos clústeres en uno, cambiarás de clúster y namespace de forma segura con kubectx y kubens, crearás un kubeconfig de acceso limitado para otra persona o herramienta, y ejecutarás comandos en todos los clústeres a la vez.
Requisitos previos
Para seguir esta guía necesitas:
- Acceso de administrador a dos o más clústeres de Kubernetes, por ejemplo desplegados sobre VPS de CubePath en ubicaciones distintas, y el fichero kubeconfig de cada uno.
- Una estación de trabajo con Ubuntu 24.04 (o cualquier Linux o macOS) con
kubectlinstalado.
En los ejemplos, los clústeres se llaman dev y prod, y sus kubeconfig originales están en ~/Descargas/dev.yaml y ~/Descargas/prod.yaml. Sustitúyelos por tus rutas.
Cómo está organizado un kubeconfig
Un kubeconfig tiene tres listas y un valor activo:
| Sección | Contenido |
|---|---|
clusters | Dirección de la API y certificado de la CA de cada clúster. |
users | Credenciales: certificado de cliente, token o plugin de autenticación. |
contexts | Combinaciones de un clúster, un usuario y, opcionalmente, un namespace. |
current-context | El contexto que usa kubectl cuando no indicas otro. |
kubectl busca la configuración en la variable KUBECONFIG (una lista de ficheros separados por :) o, si no existe, en ~/.kube/config.
Paso 1: Dar nombres únicos a cada kubeconfig
Los kubeconfig generados por kubeadm usan siempre los mismos nombres: el clúster se llama kubernetes, el usuario kubernetes-admin y el contexto kubernetes-admin@kubernetes. Si combinas dos ficheros con esos nombres, las entradas del segundo se ignoran en silencio y acabarías con dos contextos apuntando al mismo clúster. Comprueba los nombres de cada fichero:
kubectl --kubeconfig ~/Descargas/dev.yaml config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
Copia cada fichero a ~/.kube/ y edítalo para dar nombres únicos a las tres entradas:
mkdir -p ~/.kube
cp ~/Descargas/dev.yaml ~/.kube/dev.yaml
cp ~/Descargas/prod.yaml ~/.kube/prod.yaml
chmod 600 ~/.kube/dev.yaml ~/.kube/prod.yaml
nano ~/.kube/dev.yaml
Cambia los nombres en las secciones clusters, users y contexts, y en current-context, de modo que queden así (los certificados y la dirección del servidor no se tocan):
apiVersion: v1
kind: Config
clusters:
- name: dev
cluster:
server: https://203.0.113.10:6443
certificate-authority-data: LS0tLS1CRUdJTi...
users:
- name: dev-admin
user:
client-certificate-data: LS0tLS1CRUdJTi...
client-key-data: LS0tLS1CRUdJTi...
contexts:
- name: dev
context:
cluster: dev
user: dev-admin
current-context: dev
Haz lo mismo en ~/.kube/prod.yaml con los nombres prod, prod-admin y prod.
Paso 2: Combinar los kubeconfig en uno
Haz una copia del fichero actual si ya tienes uno, y genera el fichero combinado. La opción --flatten incrusta los certificados para que el resultado no dependa de otros ficheros:
[ -f ~/.kube/config ] && cp ~/.kube/config ~/.kube/config.bak
KUBECONFIG=~/.kube/dev.yaml:~/.kube/prod.yaml kubectl config view --flatten > ~/.kube/config.new
mv ~/.kube/config.new ~/.kube/config
chmod 600 ~/.kube/config
Lista los contextos disponibles:
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* dev dev dev-admin
prod prod prod-admin
Comprueba que cada contexto llega a su clúster con la opción --context, que sirve para lanzar un comando en otro clúster sin cambiar el contexto activo:
kubectl --context dev get nodes
kubectl --context prod get nodes
Cada comando debe devolver los nodos de un clúster distinto.
Consejocomo alternativa a combinar ficheros, puedes dejar cada kubeconfig por separado y añadir
export KUBECONFIG=~/.kube/dev.yaml:~/.kube/prod.yamla tu~/.bashrc. Así añadir o quitar un clúster es solo tocar un fichero.
Paso 3: Cambiar de contexto y namespace
Con kubectl puro, se cambia de clúster y de namespace así:
kubectl config use-context prod
kubectl config set-context --current --namespace=kube-system
kubectl config current-context
Switched to context "prod".
Context "prod" modified.
prod
Los comandos son largos para algo que se hace decenas de veces al día. Las herramientas kubectx y kubens los simplifican y están en los repositorios de Ubuntu:
sudo apt update
sudo apt install kubectx
Ahora puedes listar y cambiar contextos y namespaces con órdenes cortas:
kubectx # lista los contextos y marca el activo
kubectx dev # cambia al contexto dev
kubectx - # vuelve al contexto anterior
kubens default # cambia el namespace del contexto actual
kubens - # vuelve al namespace anterior
Comprueba el resultado:
kubectx -c
kubens -c
dev
default
Si instalas también fzf (sudo apt install fzf), kubectx y kubens sin argumentos abren un selector interactivo.
Paso 4: Evitar comandos en el clúster equivocado
El error más caro en un entorno multiclúster es aplicar en producción algo pensado para desarrollo. Dos medidas sencillas lo reducen mucho.
La primera es ver siempre el contexto activo en el prompt. Añade estas líneas al final de ~/.bashrc:
nano ~/.bashrc
kube_ctx() {
local ctx
ctx=$(kubectl config current-context 2>/dev/null) || return
printf '[%s] ' "$ctx"
}
PS1='$(kube_ctx)'"$PS1"
Recarga la configuración y comprueba que el prompt muestra el contexto:
source ~/.bashrc
[dev] usuario@estacion:~$
La segunda es usar --context de forma explícita en scripts y en cualquier operación destructiva sobre producción, en lugar de depender del contexto activo:
kubectl --context prod -n web rollout restart deployment/frontend
Paso 5: Crear un kubeconfig de acceso limitado
No compartas el kubeconfig de administrador con compañeros, pipelines de CI o herramientas de monitoreo. Crea una ServiceAccount con los permisos justos y un kubeconfig propio para ella. En este ejemplo, una cuenta de solo lectura en el clúster prod:
kubectl --context prod create serviceaccount readonly -n kube-system
kubectl --context prod create clusterrolebinding readonly-view \
--clusterrole=view --serviceaccount=kube-system:readonly
El ClusterRole view incluido en Kubernetes permite leer la mayoría de objetos pero no los Secret. Genera un token con caducidad para la cuenta, en este caso de 30 días:
TOKEN=$(kubectl --context prod create token readonly -n kube-system --duration=720h)
Notael servidor de API puede limitar la duración máxima de los tokens. Si necesitas un token sin caducidad para una herramienta, crea un
Secretde tipokubernetes.io/service-account-tokenasociado a la cuenta, y tenlo en cuenta al revocar accesos.
Extrae la dirección y la CA del clúster prod y construye el nuevo kubeconfig:
SERVER=$(kubectl config view --raw -o jsonpath='{.clusters[?(@.name=="prod")].cluster.server}')
kubectl config view --raw -o jsonpath='{.clusters[?(@.name=="prod")].cluster.certificate-authority-data}' | base64 -d > prod-ca.crt
kubectl config set-cluster prod --kubeconfig=prod-readonly.yaml \
--server="$SERVER" --certificate-authority=prod-ca.crt --embed-certs=true
kubectl config set-credentials readonly --kubeconfig=prod-readonly.yaml --token="$TOKEN"
kubectl config set-context prod-readonly --kubeconfig=prod-readonly.yaml \
--cluster=prod --user=readonly
kubectl config use-context prod-readonly --kubeconfig=prod-readonly.yaml
rm prod-ca.crt
Comprueba que el acceso funciona para lectura y que se deniega la escritura:
kubectl --kubeconfig=prod-readonly.yaml get pods -A | head -3
kubectl --kubeconfig=prod-readonly.yaml auth can-i create deployments
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-76f75df574-8xk2p 1/1 Running 0 12d
kube-system coredns-76f75df574-qz7lw 1/1 Running 0 12d
no
Entrega prod-readonly.yaml por un canal seguro. Para revocar el acceso, borra la ServiceAccount: kubectl --context prod delete serviceaccount readonly -n kube-system.
Paso 6: Ejecutar un comando en todos los clústeres
Para revisiones rápidas, un bucle sobre los contextos evita repetir el mismo comando a mano. Por ejemplo, para ver la versión y el estado de los nodos de cada clúster:
for ctx in $(kubectl config get-contexts -o name); do
echo "=== $ctx"
kubectl --context "$ctx" get nodes -o wide
done
=== dev
NAME STATUS ROLES AGE VERSION INTERNAL-IP ...
dev-cp-1 Ready control-plane 40d v1.33.4 10.0.0.10 ...
=== prod
NAME STATUS ROLES AGE VERSION INTERNAL-IP ...
prod-cp-1 Ready control-plane 90d v1.33.4 10.1.0.10 ...
El mismo patrón sirve para buscar pods que no están en Running en todos los clústeres:
for ctx in $(kubectl config get-contexts -o name); do
echo "=== $ctx"
kubectl --context "$ctx" get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded
done
Úsalo para consultas. Para desplegar aplicaciones en varios clústeres, es mejor una herramienta declarativa (ver la conclusión) que un bucle de kubectl apply.
Herramientas para flotas más grandes
Cuando el número de clústeres crece, conviene pasar de kubeconfig y bucles a herramientas dedicadas:
| Herramienta | Para qué sirve |
|---|---|
| Argo CD (ApplicationSet) o Flux | Desplegar las mismas aplicaciones desde Git en varios clústeres, con estado declarativo. |
| Rancher | Interfaz web y gestión centralizada de usuarios, permisos y actualizaciones de muchos clústeres. |
| Cluster API | Crear, actualizar y borrar clústeres de forma declarativa con recursos de Kubernetes. |
KubeFed (Kubernetes Cluster Federation), que aparece en muchas guías antiguas, fue archivado por el proyecto Kubernetes en 2023 y no debe usarse en instalaciones nuevas.
Solución de problemas
- Después de combinar, dos contextos muestran los mismos nodos. Los ficheros originales tenían entradas de clúster o usuario con el mismo nombre. Restaura
~/.kube/config.baky repite el paso 1 con nombres únicos. error: You must be logged in to the server (Unauthorized). El certificado de cliente o el token ha caducado. En kubeadm, los certificados del administrador duran un año; renuévalos en el plano de control consudo kubeadm certs renew admin.confy copia de nuevo/etc/kubernetes/admin.conf.- Helm avisa de que el kubeconfig es legible por el grupo u otros usuarios. Ejecuta
chmod 600 ~/.kube/config.
Conclusión
Ahora tienes un único kubeconfig con nombres claros para cada clúster, cambias de contexto y namespace con kubectx y kubens, ves siempre en el prompt dónde estás trabajando y sabes crear accesos limitados y revocables. Como siguientes pasos, puedes adoptar Argo CD con ApplicationSets para desplegar desde Git en todos tus clústeres, centralizar la autenticación con OIDC en lugar de certificados de cliente, y monitorizar todos los clústeres desde un mismo Grafana.
