Argo CD en producción: qué cambia GitOps de verdad en tus despliegues
Argo CD es fácil de instalar y fácil de usar mal. La estructura de repositorios, la política de sincronización y la decisión sobre secretos que separan un GitOps que funciona de un panel lleno de rojo.
El argumento de GitOps es que el clúster converge a lo que dice git, así que el repositorio es el registro de lo desplegado. Es cierto y merece la pena tenerlo. Lo que sorprende a los equipos es que adoptar Argo CD sobre todo obliga a tomar decisiones que venían evitando: dónde vive el estado del despliegue, quién puede cambiarlo y qué pasa cuando alguien edita el clúster a mano.
Parte el pipeline en dos
El cambio más importante: CI deja de desplegar.
Antes, un solo pipeline construía la imagen y hacía kubectl apply, lo que exigía credenciales con forma de administrador del clúster, y el único registro de lo desplegado era un log de compilación. Después hay dos mitades:
- CI compila, prueba, publica la imagen y escribe la nueva etiqueta en un repositorio de manifiestos. Sus credenciales de clúster: ninguna.
- Argo CD, corriendo dentro del clúster, ve el commit y reconcilia.
La escritura del paso 1 es un commit, con lo que el histórico de despliegues es git log, la vuelta atrás es git revert y la aprobación es la revisión de una pull request. Ese es el premio de verdad, y solo funciona si nada más escribe en el clúster.
Estructura de repositorios
Dos repositorios, no uno: código de aplicación y manifiestos. Meter los manifiestos en el repositorio de la aplicación parece más ordenado hasta que un cambio de etiqueta de imagen dispara la CI de la aplicación, que publica una imagen nueva, que cambia la etiqueta: un bucle que luego esquivas con filtros por mensaje de commit.
Dentro del repositorio de manifiestos, organiza por entorno con superposiciones de Kustomize:
base/orders/{deployment,service,hpa}.yaml
overlays/staging/orders/kustomization.yaml
overlays/production/orders/kustomization.yaml
y deja que un ApplicationSet de Argo genere las Applications en vez de escribir decenas a mano:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata: { name: services, namespace: argocd }
spec:
generators:
- git:
repoURL: https://github.com/acme/manifests
revision: main
directories: [{ path: "overlays/production/*" }]
template:
metadata: { name: 'prod-{{path.basename}}' }
spec:
project: production
source:
repoURL: https://github.com/acme/manifests
targetRevision: main
path: '{{path}}'
destination: { server: https://kubernetes.default.svc, namespace: '{{path.basename}}' }
syncPolicy:
automated: { prune: true, selfHeal: true }
La política de sincronización: la parte que se falla
selfHeal: true significa que Argo revierte los kubectl edit manuales en pocos minutos. Los equipos lo desactivan la primera vez que deshace un arreglo de urgencia, y a partir de ahí ya no tienen GitOps: tienen un panel.
Deja el autoarreglo activado y convierte la vía de urgencia en un commit rápido. Si tu respuesta a incidentes no tolera una PR de dos minutos, arregla esa vía (una rama de emergencia con un aprobador, o permiso de escritura directa para el rol de guardia) en lugar de apagar el mecanismo que garantiza que el clúster coincide con el repositorio.
prune: true borra los recursos eliminados de git. Actívalo primero en preproducción y observa qué desaparece: encontrará los recursos que alguien creó a mano hace meses.
Para producción, la mayoría de equipos con los que trabajamos usan sincronización automática en preproducción y sincronización manual con diferencia automática en producción: Argo muestra exactamente qué cambiaría y una persona pulsa sincronizar. Eso conserva la traza de auditoría y el paso de revisión sin frenar los nueve despliegues diarios que son aburridos.
Secretos
Argo CD reconcilia lo que hay en git, y la contraseña de tu base de datos no va a git. Tres respuestas viables:
- External Secrets Operator: un
SecretStoreapunta a tu gestor de secretos de nube o a Vault, unExternalSecreten git referencia una clave y el operador materializa elSecret. Git guarda la referencia, nunca el valor. Es nuestra opción por defecto. - Sealed Secrets: cifrados con la clave pública del clúster, seguros de subir, descifrados dentro. Simple, pero la rotación y el multiclúster se vuelven incómodos.
- El driver CSI de secretos: monta los secretos como ficheros al arrancar el pod. Bien cuando no quieres ningún objeto
Secretde Kubernetes.
Elijas lo que elijas, el acceso a la nube por debajo debe venir de una identidad de carga de trabajo ligada a la cuenta de servicio, no de una clave estática: el mismo principio que la federación OIDC en CI.
Realidades operativas
La deriva pasa a ser visible, y al principio incomoda. La primera semana tras instalar Argo CD, el panel se pone amarillo con recursos fuera de sincronía que no sabías que existían: webhooks de mutación que añaden campos, un HPA que cambia réplicas, una malla de servicios que inyecta sidecars. Casi todo se arregla con ignoreDifferences sobre los campos concretos, no rindiéndose.
¿Un Argo por clúster o uno para muchos? Un Argo central que gobierna muchos clústeres es menos cosas que operar, pero con un radio de impacto que abarca todos los entornos. Preferimos uno por clúster de producción con el patrón de aplicación de aplicaciones, y asumimos las instalaciones extra.
El RBAC importa más de lo que parece. Los proyectos de Argo restringen qué repositorios, clústeres y espacios de nombres puede tocar una Application. Sin ellos, cualquiera que pueda hacer commit en el repositorio de manifiestos puede desplegar lo que sea donde sea, que es un permiso mayor que las credenciales de CI que acabas de quitar.
La recompensa compensa el montaje: cada despliegue es un commit revisado, la vuelta atrás es inmediata y a un estado conocido, y "qué hay corriendo en producción" deja de ser una pregunta que nadie tenga que adivinar. Combínalo con entrega progresiva y el despliegue deja de ser un acontecimiento.