Hace unos años, cuando empecé a meterme más a fondo con Kubernetes, me topé con un problema recurrente en los despliegues automáticos. Tenía un script de CI/CD que usaba kubectl create para un ConfigMap, y cada vez que intentaba redeployar, ¡pum! La pipeline fallaba diciendo que el recurso ya existía. Me frustraba, de hecho, me costó un PR rechazado por esa tontera.
Ahí fue cuando me obligué a entender la diferencia entre kubectl create y kubectl apply. Parecen hacer lo mismo, pero son fundamentalmente distintas, y saber cuál usar te puede salvar de muchos dolores de cabeza.
Imperativo vs. Declarativo: La Clave
La diferencia principal radica en el enfoque que tienen para gestionar tus recursos en Kubernetes:
-
kubectl create: Gestión ImperativaCon
create, le dices directamente a la API de Kubernetes lo que quieres que haga: "crea este Pod", "crea este ConfigMap". Es una instrucción directa. El problema es que si el recurso ya existe, Kubernetes te arroja un error y no hace nada más. Es útil para operaciones manuales, de una sola vez, cuando *quieres* que falle si el recurso ya está ahí. -
kubectl apply: Gestión DeclarativaAquí le dices a Kubernetes cuál es el estado deseado de tu clúster. "Asegúrate de que este Pod exista y tenga estas características". Si el recurso no existe, lo crea. Si existe, lo actualiza para que coincida con tu definición. Esto lo logra guardando una anotación (
last-applied-configuration) en el recurso, que usa para calcular las diferencias.Para mí, esta es la forma de trabajar en casi todos los escenarios modernos, especialmente con CI/CD o GitOps. Es idempotente, lo que significa que puedes ejecutarlo cien veces y el resultado será el mismo: tu clúster en el estado que definiste.
Existe también kubectl replace, que es imperativo y reemplaza un recurso por completo. Es menos flexible que apply porque si te olvidas de algún campo en tu YAML, ese campo se borra. Por eso, rara vez lo uso.
¿Cuándo usar qué? Mi experiencia.
En mi caso, y en la mayoría de los proyectos donde he trabajado, la respuesta es simple: casi siempre kubectl apply. De hecho, diría que es la herramienta por defecto para desplegar tus aplicaciones y configuraciones.
Si estás gestionando tu infraestructura con código (infra-as-code), apply es tu amigo. Mantiene el estado deseado de tu clúster alineado con tus archivos YAML sin fallar por recursos existentes. Me ahorra la sobreingeniería de tener que hacer un delete antes de un create, algo que nunca me ha convencido porque implica más estados intermedios y posibles errores.
¿Y create? Lo reservo para casos muy específicos:
- Crear un namespace por primera vez, donde si ya existe, quiero saberlo.
- Generar recursos de forma programática y luego, en una segunda fase, aplicarles un
apply. Ojo que aquí hay un truco útil:
kubectl create secret generic my-secret --from-literal=password=supersecret \
--dry-run=client -o yaml | kubectl apply -f -
Este comando crea un secreto (imperativo), pero en vez de enviarlo directo a Kubernetes, lo imprime en YAML (--dry-run=client -o yaml) y luego lo pasa por un pipe a kubectl apply -f -, que lo aplica de forma declarativa. Así obtienes lo mejor de ambos mundos para situaciones puntuales, como crear secretos que no quieres almacenar directamente en un archivo YAML.
Conclusión
La moraleja es clara: para despliegues continuos y mantener un estado deseado en tu clúster, kubectl apply es la herramienta que necesitas. Su naturaleza declarativa e idempotente lo hace ideal para la automatización. kubectl create tiene su lugar, sí, para operaciones únicas donde un error por existencia es deseable, pero no para gestionar el ciclo de vida completo de tus recursos. Entender esta diferencia me evitó muchos dolores de cabeza y me ayudó a construir pipelines mucho más robustas.