kubectl apply vs set: Cómo elegir el comando correcto para actualizar recursos
Comprende cuándo usar kubectl apply, set y edit sin generar desviaciones entre los objetos de Kubernetes en vivo y Git.
kubectl apply vs set: Cómo elegir el comando correcto para actualizar recursos
La diferencia entre kubectl apply y kubectl set no es solo sintáctica. Es la diferencia entre gestionar Kubernetes desde una fuente de verdad declarada y cambiar objetos en vivo directamente. Ambos son útiles. Ambos pueden perjudicarte si los usas en el lugar equivocado.
Usa kubectl apply cuando el cambio deba convertirse en el estado deseado del sistema. Usa kubectl set cuando necesites un cambio enfocado en vivo, generalmente temporal o urgente. Usa kubectl edit cuando necesites inspeccionar y parchear un objeto en vivo de forma interactiva, pero entiende que es la forma más fácil de crear desviación de Git.
Un objeto de Kubernetes tiene un estado deseado almacenado en el servidor API. Un Deployment indica cuántas réplicas deben existir, qué imagen debe ejecutarse, qué etiquetas identifican los pods, qué recursos se solicitan y más. Los controladores trabajan para que la realidad coincida con ese estado deseado. Tu comando de actualización cambia el estado deseado; los controladores hacen el resto.
Con kubectl apply, mantienes ese estado deseado en archivos YAML o JSON. El archivo es lo que revisas, confirmas, promueves y reviertes. Un comando típico es simple:
kubectl apply -f deployment.yaml
Si el objeto no existe, Kubernetes lo crea. Si existe, Kubernetes lo actualiza para que coincida con el manifiesto. Aplicar el mismo archivo nuevamente no debería causar un nuevo cambio de comportamiento. Esa idempotencia es una de las razones por las que apply funciona bien en flujos de trabajo CI/CD y GitOps.
kubectl apply del lado del cliente históricamente usaba una anotación de última aplicación para calcular cambios. La aplicación del lado del servidor, habilitada con --server-side, rastrea la propiedad de los campos a través de campos gestionados en el servidor API. Los detalles difieren, pero la idea operativa es la misma: una configuración declarada posee el estado deseado.
Aquí hay un pequeño manifiesto de Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
Si cambias la imagen en el archivo y ejecutas kubectl apply -f deployment.yaml, el Deployment se actualiza. Si el archivo está en Git, el cambio puede ser revisado. Si el despliegue falla, puedes revertir el commit o usar el historial de despliegues de Kubernetes, dependiendo de cómo tu proceso de despliegue registre las revisiones.
kubectl set funciona de manera diferente. Cambia un campo específico en un objeto en vivo. El ejemplo común es cambiar la imagen de un contenedor:
kubectl set image deployment/web nginx=nginx:1.26
Ese comando es rápido y legible. Durante un incidente, la velocidad importa. Si la imagen actual está rota y necesitas mover un Deployment a una imagen conocida como buena, kubectl set image puede ser el camino más rápido. El peligro es lo que sucede después. Si deployment.yaml todavía dice nginx:1.25, el próximo kubectl apply -f deployment.yaml puede mover la carga de trabajo de vuelta a 1.25.
Esa discrepancia es desviación de configuración. El clúster en vivo dice una cosa. El archivo fuente dice otra. La desviación no siempre es catastrófica, pero dificulta la depuración porque la gente deja de confiar en el repositorio. Alguien pregunta: "¿Qué está corriendo en producción?" y la respuesta honesta se convierte en: "Déjame revisar el clúster".
kubectl set tiene varios subcomandos útiles:
kubectl set image deployment/web nginx=nginx:1.26
kubectl set env deployment/web FEATURE_FLAG=true
kubectl set resources deployment/web -c=nginx --requests=cpu=200m,memory=256Mi --limits=cpu=500m,memory=512Mi
Estos son prácticos para clústeres de desarrollo, demostraciones, pruebas de corta duración y cambios de emergencia en producción con un commit de seguimiento. No son un reemplazo para manifiestos mantenidos.
kubectl edit obtiene el objeto en vivo, lo abre en tu editor y envía el objeto modificado de vuelta al servidor API cuando guardas:
kubectl edit deployment/web
Es conveniente porque puedes ver el YAML completo en vivo, incluidos los campos añadidos por los controladores. También es arriesgado porque los objetos en vivo contienen muchos campos que no deberías gestionar manualmente, como status, metadatos generados, versiones de recursos y campos gestionados. Kubernetes ignorará o rechazará algunas ediciones inválidas, pero no todas las ediciones incorrectas son sintácticamente inválidas.
Un uso seguro común de kubectl edit es un experimento rápido fuera de producción: aumentar réplicas, cambiar una anotación o probar un valor de sonda. Un uso inseguro común es editar manualmente Deployments de producción cada semana y nunca actualizar los manifiestos. Eso crea un clúster que nadie puede reconstruir con confianza.
La regla práctica es esta: si quieres que el cambio sobreviva al próximo despliegue, ponlo en el manifiesto y usa apply. Si solo necesitas tocar el objeto en vivo, usa set o edit, luego revierte el cambio o transpórtalo a Git.
Hay algunos casos donde los comandos imperativos no solo son aceptables sino útiles. Durante la depuración, podrías agregar temporalmente una variable de entorno que aumente la verbosidad del registro:
kubectl set env deployment/api LOG_LEVEL=debug
Después de recopilar registros, elimínala:
kubectl set env deployment/api LOG_LEVEL-
Si la configuración de depuración debe volverse permanente, confírmala en el manifiesto en su lugar. No confíes en la memoria.
Otro caso es la reversión de emergencia. Si tu pipeline de despliegue está atascado y los clientes están afectados, establecer la imagen directamente puede ser razonable:
kubectl set image deployment/api api=registry.example.com/api:2026-05-23-good
kubectl rollout status deployment/api
El seguimiento debe ocurrir inmediatamente: abre un pull request o commit que haga que el manifiesto declarado coincida con el estado de emergencia, o ejecuta el proceso de reversión normal una vez que el pipeline esté saludable. La corrección en vivo gana tiempo; no debería convertirse en el nuevo método de despliegue no documentado.
kubectl apply también tiene trampas. Si mezclas múltiples herramientas que gestionan los mismos campos, puedes obtener conflictos o sobrescrituras sorprendentes. Por ejemplo, un controlador GitOps, Helm y un humano ejecutando kubectl apply contra el mismo Deployment pueden creer que poseen parte del objeto. Elige una propiedad clara. Si Helm gestiona el recurso, actualiza los valores de Helm y ejecuta el proceso de release de Helm. Si Argo CD o Flux lo gestiona, cambia Git y deja que el controlador reconcilie.
Para secretos y configuraciones, ten especial cuidado. kubectl set env puede poner cambios rápidos en un Deployment, pero puede exponer valores en el historial del shell o en registros de auditoría. Para valores sensibles, actualiza el Secret a través de tu proceso normal de gestión de secretos. No pegues credenciales de producción en un comando ad hoc a menos que tu equipo haya aceptado explícitamente ese flujo de trabajo.
Antes de cambiar un objeto en vivo, inspecciónalo:
kubectl get deployment web -o yaml
kubectl diff -f deployment.yaml
kubectl diff está infrautilizado. Muestra lo que apply cambiaría antes de hacer el cambio. En producción, esa vista previa puede detectar errores como eliminar accidentalmente un selector de etiquetas, eliminar un límite de recursos o aplicar el manifiesto del entorno incorrecto.
Para la aplicación del lado del servidor, el comando se ve así:
kubectl apply --server-side -f deployment.yaml
La aplicación del lado del servidor puede ser útil cuando múltiples actores gestionan diferentes campos, pero no elimina la necesidad de disciplina de propiedad. Si dos gestores intentan poseer el mismo campo, Kubernetes puede reportar un conflicto. Eso es una característica; te está diciendo que el flujo de trabajo es ambiguo.
Aquí hay una guía de decisión simple que uso en clústeres reales. ¿Nuevo lanzamiento de aplicación? Cambia el manifiesto y usa apply a través del pipeline. ¿Aumentar réplicas para una prueba de carga en staging? kubectl scale o kubectl set está bien si lo reviertes. ¿Corregir una imagen rota en producción? kubectl set image puede ser aceptable, pero crea el cambio de fuente de verdad de inmediato. ¿Ajustar solicitudes de CPU permanentemente? Actualiza el manifiesto. ¿Explorar qué campos existen en un recurso? Usa kubectl get -o yaml antes de recurrir a edit.
Cuando los equipos hacen esto bien, Kubernetes se vuelve más fácil de razonar. El repositorio cuenta la historia. El clúster coincide con el repositorio la mayor parte del tiempo. Los cambios temporales en vivo se etiquetan como temporales y se limpian. Los incidentes siguen siendo estresantes, pero la configuración no se convierte en un segundo misterio.
El comando en sí no es el punto. El punto es si puedes reconstruir el estado del clúster mañana a partir de archivos confiables. kubectl apply apoya ese hábito. kubectl set y kubectl edit son herramientas afiladas para momentos en que la acción directa es útil. Mantén ese límite claro y evitarás mucha confusión evitable de Kubernetes.
Hay otro comando que la gente pone en el mismo cubo mental: kubectl patch. También es imperativo, pero es mejor para cambios precisos con scripts que edit. Por ejemplo, puedes parchear una anotación de Deployment para desencadenar un reinicio o actualizar un campo pequeño en automatización. Se aplica la misma regla de desviación. Si el campo parcheado representa el estado deseado a largo plazo, actualiza también el manifiesto fuente.
kubectl patch deployment web -p '{"spec":{"template":{"metadata":{"annotations":{"restartedAt":"2026-05-24T10:00:00Z"}}}}}'
Para reinicios, prefiere el comando diseñado para ese propósito:
kubectl rollout restart deployment/web
Ese comando aún cambia el objeto en vivo, pero su intención es clara: iniciar un nuevo despliegue desde la plantilla de pod actual. No es un sustituto para cambiar la configuración en Git.
En entornos GitOps, el límite es aún más estricto. Si Argo CD o Flux posee un objeto, un kubectl set image manual puede ser revertido automáticamente porque el controlador ve desviación y reconcilia de vuelta a Git. Eso puede ser sorprendente durante un incidente. Antes de hacer un cambio manual en producción, sabe si un controlador GitOps te combatirá. A veces la acción de emergencia correcta es pausar la reconciliación para esa aplicación, hacer la corrección, luego confirmar el cambio coincidente en Git y reanudar la reconciliación.
También debes saber cómo capturar una diferencia en vivo sin confirmar ciegamente campos generados. kubectl get deployment web -o yaml incluye estado, versiones de recursos, campos gestionados y otros datos que no deberían ir a un manifiesto limpio. Si necesitas retroportar una corrección rápida, edita el manifiesto fuente manualmente o usa una herramienta como Kustomize o valores de Helm, luego ejecuta kubectl diff para verificar el cambio previsto. No reemplaces tu archivo fuente con YAML en vivo crudo a menos que lo limpies cuidadosamente.
Para los equipos, la política más saludable suele ser corta y explícita. Los cambios de producción pasan por Git. Los cambios de emergencia en vivo están permitidos cuando sea necesario, pero requieren un cambio fuente de seguimiento o reversión. Los clústeres de desarrollo son más flexibles, pero cualquier cosa promovida más allá del desarrollo debe ser declarada. Esa política es más fácil de seguir que una larga lista de comandos prohibidos.
También hay un lado humano en esto. Durante una interrupción, la persona con acceso al clúster puede hacer la corrección más rápida posible. Eso está bien cuando el equipo lo trata como una excepción de emergencia. Se vuelve peligroso cuando esas excepciones se convierten en operaciones normales. Si la producción se corrige rutinariamente a mano, el proceso de despliegue es demasiado lento, demasiado frágil o no es confiable. Arregla ese proceso en lugar de enseñar a todos más trucos de edición en vivo.
RBAC puede reforzar el flujo de trabajo. Muchos equipos permiten acceso amplio a kubectl en desarrollo pero restringen las escrituras en producción a sistemas CI/CD, controladores GitOps o un pequeño grupo de guardia. Eso no es burocracia por sí misma. Reduce la cantidad de caminos que pueden cambiar el estado deseado. Cuando algo cambia, los registros de auditoría y el historial de Git son más fáciles de seguir.
Para aprender, aún vale la pena practicar los tres comandos en un namespace desechable. Crea un Deployment con apply, cambia su imagen con set, inspecciona la desviación con kubectl diff, luego actualiza el manifiesto y aplica de nuevo. Ver la desviación ocurrir una vez en un entorno seguro hace que la regla de producción sea mucho más fácil de recordar.