ArgoCD: Guía Completa de GitOps para Kubernetes

ArgoCD: Guía Completa de GitOps para Kubernetes

ArgoCD se ha convertido en el estándar de facto para la entrega continua basada en GitOps en Kubernetes. Si ejecutas cargas de trabajo en producción sobre Kubernetes y sigues desplegando con kubectl apply directo o releases de Helm sin trazabilidad, ArgoCD resuelve una categoría de problemas que quizás ni sabes que tienes. Esta guía cubre desde los conceptos fundamentales hasta la configuración lista para producción.

El problema que resuelve ArgoCD

El CI/CD tradicional empuja los despliegues hacia el clúster. El sistema de integración continua ejecuta los tests, construye la imagen y llama a kubectl apply o helm upgrade contra el clúster. Este modelo tiene varios problemas estructurales:

  • El drift pasa desapercibido. Alguien aplica un hotfix directamente en el clúster. El repositorio Git ya no refleja la realidad, y nadie lo sabe.
  • No existe una única fuente de verdad. El estado del clúster es el autoritativo, no Git. El estado deseado y el estado real pueden divergir en silencio.
  • El rollback es doloroso. Revertir un despliegue fallido implica re-ejecutar pipelines de CI antiguos o deshacer cambios manualmente, ninguna de las dos opciones es rápida.
  • La gestión multi-clúster multiplica el problema. Cada clúster se convierte en un copo de nieve con su propio historial de cambios no documentados.

GitOps invierte este modelo. Git es la fuente de verdad. El clúster extrae su estado deseado de Git y reconcilia continuamente hacia él. ArgoCD es el operador GitOps más maduro para Kubernetes, implementando este modelo pull con un conjunto de funcionalidades listo para producción.

Cómo funciona ArgoCD: arquitectura principal

ArgoCD se ejecuta como un conjunto de controladores dentro de tu clúster Kubernetes. Los componentes principales son:

  • Application Controller — Observa tanto el repositorio Git como el estado real del clúster. Calcula el diff y dirige la reconciliación.
  • API Server — Expone la API gRPC/REST que consumen la CLI, la UI y los sistemas externos.
  • Repository Server — Genera los manifiestos de Kubernetes a partir de la fuente (Helm, Kustomize, YAML plano, Jsonnet).
  • Redis — Cachea el estado del clúster y los datos del repositorio para reducir la carga del API server.
  • Dex (opcional) — Proporciona autenticación OIDC para la integración con SSO.

La unidad fundamental en ArgoCD es una Application — un CRD que mapea una fuente (una ruta en un repositorio Git en una revisión concreta) a un destino (un namespace en un clúster). ArgoCD compara continuamente el estado deseado de Git con el estado real del clúster y reporta el estado de sincronización.

Sync Status frente a Health Status

Dos conceptos ortogonales que debes entender desde el primer día:

  • Sync Status — ¿Coincide el estado real con lo que Git dice que debería ser? Valores: Synced, OutOfSync, Unknown.
  • Health Status — ¿Está funcionando la aplicación realmente? Valores: Healthy, Progressing, Degraded, Suspended, Missing, Unknown.

Una aplicación puede estar Synced pero Degraded: los manifiestos se aplicaron correctamente, pero un pod está en crash-loop. Por el contrario, puede estar OutOfSync pero Healthy: alguien aplicó un cambio directamente en el clúster al margen de Git.

Este es el punto clave de ArgoCD: te da visibilidad total sobre ambas dimensiones de cada aplicación, algo que ninguna herramienta de CI/CD clásica puede ofrecerte.

Instalación de ArgoCD

El método de instalación oficial utiliza un único manifiesto. En producción, fija siempre una versión específica:

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.11.0/manifests/install.yaml

Esto despliega ArgoCD en el namespace argocd con acceso cluster-admin completo. Para una instalación HA en producción, utiliza la variante manifests/ha/install.yaml, que despliega múltiples réplicas del API server y del application controller.

Acceder a la UI y la CLI

La contraseña inicial del administrador se genera automáticamente y se almacena en un secret:

argocd admin initial-password -n argocd

Para acceso local, haz port-forward al API server:

kubectl port-forward svc/argocd-server -n argocd 8080:443

Luego inicia sesión mediante la CLI:

argocd login localhost:8080 --username admin --password <contraseña> --insecure

En producción, expón el servidor de ArgoCD mediante un Ingress o un LoadBalancer con un certificado TLS válido. Si usas NGINX Ingress Controller:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.tudominio.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443

La anotación ssl-passthrough es importante: el API server de ArgoCD termina TLS él mismo, por lo que el Ingress debe pasar el tráfico sin descifrarlo.

Definir tu primera Application

Las Applications se pueden crear mediante la UI, la CLI o declarativamente con un manifiesto YAML. El enfoque declarativo es el recomendado: significa que la propia configuración de ArgoCD está en Git, cerrando el círculo del paradigma GitOps:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: mi-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/tu-org/tu-app
    targetRevision: HEAD
    path: k8s/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Campos clave que debes entender:

  • targetRevision — Puede ser el nombre de una rama, un tag o el SHA de un commit. En producción, fija siempre a un tag en lugar de HEAD.
  • path — El directorio dentro del repositorio que contiene tus manifiestos de Kubernetes.
  • automated.prune — Elimina automáticamente los recursos que ya no están en Git. Necesario para un GitOps real, pero úsalo con cuidado: borrará recursos.
  • automated.selfHeal — Revierte automáticamente los cambios manuales aplicados directamente en el clúster. Esto es lo que hace que Git sea la fuente de verdad y no solo una referencia.

La combinación de prune: true y selfHeal: true es lo que diferencia un despliegue GitOps real de simplemente usar ArgoCD como un mecanismo de despliegue sofisticado. Sin ellos, el drift sigue siendo posible.

Integración con Helm

ArgoCD tiene soporte nativo para Helm. Puede desplegar charts de Helm directamente desde repositorios de charts o desde tu repositorio Git. Puedes sobrescribir valores por entorno:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus-stack
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: kube-prometheus-stack
    targetRevision: 58.4.0
    helm:
      releaseName: prometheus-stack
      valuesObject:
        grafana:
          adminPassword: "${GRAFANA_PASSWORD}"
        prometheus:
          prometheusSpec:
            retention: 30d
            storageSpec:
              volumeClaimTemplate:
                spec:
                  storageClassName: fast-ssd
                  resources:
                    requests:
                      storage: 50Gi
  destination:
    server: https://kubernetes.default.svc
    namespace: observability

Un matiz importante: ArgoCD renderiza los charts de Helm en el lado del servidor usando su propio motor de plantillas, no helm install. Esto significa que los hooks de Helm (pre-install, post-upgrade, etc.) están soportados, pero el release no se registra en el historial de Helm. Ejecutar helm list no mostrará los releases gestionados por ArgoCD a menos que configures ArgoCD para usar el backend de secrets de Helm.

Esta es una fuente frecuente de confusión para equipos que migran de un flujo de trabajo basado exclusivamente en Helm: ArgoCD y Helm no son competidores, pero sí hay matices en cómo interactúan.

Projects: multi-tenancy y control de acceso

Los AppProjects de ArgoCD proporcionan multi-tenancy dentro de una única instancia de ArgoCD. Permiten restringir qué repositorios de fuentes, clústeres de destino y namespaces puede usar cada equipo. Toda Application pertenece a un Project.

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: equipo-plataforma
  namespace: argocd
spec:
  description: Aplicaciones del equipo de plataforma
  sourceRepos:
  - 'https://github.com/tu-org/*'
  destinations:
  - namespace: 'plataforma-*'
    server: https://kubernetes.default.svc
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  namespaceResourceBlacklist:
  - group: ''
    kind: ResourceQuota

Los Projects son donde defines los límites de lo que cada equipo puede hacer. El proyecto default no tiene restricciones: nunca lo uses para cargas de trabajo en producción. Crea proyectos dedicados por equipo o por entorno.

El modelo habitual en entornos empresariales es un proyecto por equipo de producto, con restricciones de namespace y de repositorio de fuente que impidan que un equipo accidentalmente despliegue en el entorno de otro.

Configuración RBAC

ArgoCD tiene su propio sistema RBAC superpuesto sobre el RBAC de Kubernetes. Se configura mediante el ConfigMap argocd-rbac-cm. Los roles se definen por proyecto o de forma global:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  policy.csv: |
    # El equipo de plataforma tiene acceso completo a su proyecto
    p, role:platform-admin, applications, *, equipo-plataforma/*, allow
    p, role:platform-admin, projects, get, equipo-plataforma, allow
    p, role:platform-admin, repositories, *, *, allow

    # El equipo de desarrollo puede sincronizar pero no borrar
    p, role:developer, applications, get, */*, allow
    p, role:developer, applications, sync, */*, allow
    p, role:developer, applications, action/*, */*, allow

    # Vincular grupos SSO a roles
    g, tu-org:equipo-plataforma, role:platform-admin
    g, tu-org:developers, role:developer

El policy.default: role:readonly garantiza que cualquier usuario autenticado sin asignación de rol explícita obtenga acceso de solo lectura: un valor por defecto seguro para producción.

La integración con SSO (vía Dex u otro proveedor OIDC) permite que los grupos de tu directorio corporativo (Active Directory, Okta, Google Workspace) se mapeen directamente a roles en ArgoCD, sin necesidad de gestionar usuarios locales.

Gestión multi-clúster

ArgoCD puede gestionar múltiples clústeres Kubernetes desde un único plano de control. Registra clústeres externos con la CLI:

# Primero, asegúrate de que el contexto del clúster destino está en tu kubeconfig
argocd cluster add produccion-eu-west --name produccion-eu-west

# Verifica el registro
argocd cluster list

ArgoCD creará un ServiceAccount en el clúster destino y almacenará sus credenciales como un secret de Kubernetes en el namespace de ArgoCD. Las Applications pueden entonces apuntar a este clúster por nombre en el campo destination.server.

Para setups multi-clúster a gran escala, considera el patrón App of Apps o los ApplicationSets. Los ApplicationSets son un controlador que genera Applications dinámicamente basándose en generadores: listas de clústeres, estructuras de directorios Git o combinaciones matriciales:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-addons
  namespace: argocd
spec:
  generators:
  - clusters:
      selector:
        matchLabels:
          environment: production
  template:
    metadata:
      name: '{{name}}-addons'
    spec:
      project: plataforma
      source:
        repoURL: https://github.com/tu-org/cluster-addons
        targetRevision: HEAD
        path: 'addons/{{metadata.labels.region}}'
      destination:
        server: '{{server}}'
        namespace: kube-system

Este único ApplicationSet despliega los addons apropiados en cada clúster etiquetado como environment: production, usando la etiqueta de región de cada clúster para seleccionar la ruta correcta en el repositorio.

La potencia de este enfoque es significativa: añadir un nuevo clúster de producción solo requiere etiquetarlo correctamente; ArgoCD se encarga automáticamente de desplegar todos los addons necesarios.

Estrategias de sync y waves

Al desplegar aplicaciones complejas con dependencias entre recursos, necesitas controlar el orden de despliegue. ArgoCD ofrece dos mecanismos para esto:

Fases de sync

Los recursos se despliegan en tres fases: PreSync, Sync y PostSync. Usa Sync Hooks para recursos que deben completarse antes de que avance el sync principal (migraciones de base de datos, emisión de certificados, etc.):

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: tu-app:v1.2.3
        command: ["./migrate.sh"]
      restartPolicy: Never

La anotación HookSucceeded asegura que el Job se limpie una vez completado con éxito, evitando acumulación de recursos en el clúster.

Sync waves

Dentro de la fase Sync, las waves controlan el orden. Los recursos con un número de wave menor se aplican y deben estar sanos antes de que se apliquen los de waves superiores:

# Se aplica primero
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "1"

# Se aplica después de que la wave 1 esté sana
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "2"

El caso de uso más habitual es: wave 0 para CRDs, wave 1 para el Namespace y ConfigMaps base, wave 2 para el Deployment, wave 3 para el Ingress. Este orden garantiza que los recursos dependientes no intentan crearse antes de que sus prerequisitos existan.

Notificaciones y alertas

ArgoCD Notifications es un controlador independiente que envía alertas cuando cambia el estado de una Application. Soporta Slack, PagerDuty, estado de commits de GitHub, email y más de una docena de proveedores adicionales. Se configura mediante el ConfigMap argocd-notifications-cm:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  template.app-sync-failed: |
    slack:
      attachments: |
        [{
          "title": "{{.app.metadata.name}}",
          "color": "#E96D76",
          "fields": [{
            "title": "Sync Status",
            "value": "{{.app.status.sync.status}}",
            "short": true
          },{
            "title": "Mensaje",
            "value": "{{range .app.status.conditions}}{{.message}}{{end}}",
            "short": false
          }]
        }]
  trigger.on-sync-failed: |
    - when: app.status.sync.status == 'Unknown'
      send: [app-sync-failed]
    - when: app.status.operationState.phase in ['Error', 'Failed']
      send: [app-sync-failed]

En la práctica, configura al menos notificaciones para sync-failed y health-degraded. El resto de eventos (sync iniciado, sync exitoso) generan demasiado ruido para canales de alertas de producción.

Gestión de secrets con ArgoCD

ArgoCD no incluye gestión de secrets de forma intencionada: almacenar secrets en Git como texto plano nunca es aceptable. Los patrones habituales son:

  • Sealed Secrets (Bitnami) — Cifra los secrets con una clave específica del clúster. El secret cifrado se puede commitear en Git; solo el clúster puede descifrarlo.
  • External Secrets Operator — Sincroniza secrets desde Vault, AWS Secrets Manager, GCP Secret Manager, etc. a secrets de Kubernetes. La Application en ArgoCD gestiona el CRD ExternalSecret, no el valor del secret en sí.
  • argocd-vault-plugin — Un plugin que reemplaza valores de marcador de posición en los manifiestos con secrets recuperados de Vault en el momento del sync.

El enfoque de External Secrets Operator es el más flexible para equipos que ya usan un backend centralizado de secrets. La Application en ArgoCD despliega objetos ExternalSecret, que el controlador ESO resuelve en tiempo de ejecución sin que los valores lleguen nunca a Git.

Para equipos que empiezan desde cero en España, Sealed Secrets tiene una curva de aprendizaje más baja y es perfectamente válido para la mayoría de los casos de uso. La complejidad adicional de External Secrets Operator se justifica cuando ya tienes Vault o un servicio cloud de gestión de secrets.

Buenas prácticas para producción

  • Ejecuta ArgoCD en modo HA. Usa manifests/ha/install.yaml con 3 réplicas del API server y múltiples shards del application controller para clústeres grandes (100+ aplicaciones).
  • Fija las versiones de imagen. Nunca uses latest para la propia imagen de ArgoCD. Fija una versión específica y actualiza deliberadamente.
  • Usa el patrón App of Apps para el bootstrapping. Una única Application raíz despliega todas las demás Applications. Esto hace que el bootstrapping del clúster sea idempotente y reproducible.
  • Separa la configuración de ArgoCD de la configuración de aplicación. Almacena los manifiestos de Application de ArgoCD en un repositorio gitops dedicado, separado del código fuente de las aplicaciones.
  • Activa el resource tracking mediante anotaciones. Usa application.resourceTrackingMethod: annotation en argocd-cm en lugar del tracking basado en labels por defecto, que puede entrar en conflicto con los propios labels de Helm.
  • Establece límites de recursos en los controladores de ArgoCD. La CPU y la memoria del application controller escalan con el número de recursos rastreados. Monitoriza y ajusta según sea necesario.
  • Restringe el auto-sync en producción. Considera requerir aprobación manual de sync para entornos de producción incluso cuando usas GitOps, o al menos exige un gate de aprobación de PR antes de que los cambios lleguen a la rama objetivo.

El patrón App of Apps merece un desarrollo adicional: la idea es tener un repositorio gitops-config que contenga una Application raíz. Esa Application raíz apunta a un directorio que contiene los manifiestos de todas las demás Applications. Para añadir una nueva aplicación al clúster, añades su manifiesto Application al repositorio gitops-config. ArgoCD lo detecta y la despliega automáticamente.

ArgoCD frente a Flux

Flux v2 es el otro operador GitOps principal. Ambos son proyectos graduados de CNCF. Las diferencias principales en la práctica:

CaracterísticaArgoCDFlux v2
UIUI web integradaSin UI oficial (usa Weave GitOps)
Multi-clústerUn plano de control gestiona muchos clústeresAgente por clúster, modelo pull
ApplicationSetsNativoKustomization + HelmRelease
Gestión de secretsBasada en pluginsIntegración nativa con SOPS
Curva de aprendizajeMayor (más conceptos)Menor (más Kubernetes-nativo)
Estado CNCFGraduadoGraduado

ArgoCD gana cuando necesitas la UI, gestión multi-clúster desde un plano central, o tienes un equipo de operaciones grande que se beneficia de la vista visual de topología de aplicaciones. Flux gana cuando quieres un enfoque más simple y puramente Kubernetes-nativo con mejor integración de SOPS para la gestión de secrets.

En el contexto del mercado español y europeo, ArgoCD domina en organizaciones con equipos de plataforma dedicados. Flux es más frecuente en equipos pequeños que valoran la simplicidad operativa.

Primeros pasos: de cero a ArgoCD en producción

El camino más rápido desde cero hasta un setup funcional de ArgoCD en un clúster local:

# 1. Crea un clúster local (kind o minikube)
kind create cluster --name argocd-demo

# 2. Instala ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 3. Espera a que los pods estén listos
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=120s

# 4. Obtén la contraseña inicial del administrador
argocd admin initial-password -n argocd

# 5. Port-forward e inicia sesión
kubectl port-forward svc/argocd-server -n argocd 8080:443 &
argocd login localhost:8080 --username admin --insecure

# 6. Despliega tu primera aplicación
argocd app create guestbook \
  --repo https://github.com/argoproj/argocd-example-apps.git \
  --path guestbook \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace guestbook \
  --sync-policy automated

Desde aquí, los próximos pasos naturales son integrar ArgoCD con tu pipeline de CI existente (el CI construye y publica la imagen, actualiza el tag de imagen en Git, ArgoCD detecta el cambio y sincroniza), configurar SSO mediante Dex y establecer el patrón App of Apps para gestionar múltiples aplicaciones de forma declarativa.

Preguntas frecuentes

¿Puede ArgoCD desplegar en el clúster donde se ejecuta?

Sí. El destino https://kubernetes.default.svc hace referencia al clúster local. ArgoCD puede gestionar simultáneamente su propio clúster y clústeres externos.

¿Soporta ArgoCD repositorios Git privados?

Sí. Configura las credenciales del repositorio mediante argocd repo add con claves SSH, usuario/contraseña HTTPS o credenciales de GitHub App. Las credenciales se almacenan como secrets de Kubernetes en el namespace de ArgoCD.

¿Cómo gestiona ArgoCD la instalación de CRDs?

Los CRDs pueden ser gestionados por ArgoCD, pero hay un problema de dependencia circular: si un CRD no está instalado aún, ArgoCD no puede validar recursos que lo usen. El patrón recomendado es colocar los CRDs en wave 1 y los recursos dependientes en wave 2, o usar una Application separada para los CRDs.

¿Cuál es la diferencia entre una Application y un AppProject?

Una Application es la unidad de despliegue: mapea una fuente Git a un destino en el clúster. Un AppProject es un agrupador y límite de control de acceso: restringe qué fuentes y destinos puede usar una Application dentro del proyecto. Toda Application pertenece exactamente a un AppProject.

¿Cómo hago un rollback de un despliegue con ArgoCD?

La forma GitOps: revertir el commit en Git y dejar que ArgoCD reconcilie. ArgoCD también proporciona un rollback basado en UI a cualquier revisión de sync anterior, pero esto se considera una medida temporal: el historial de Git siempre debe actualizarse para reflejar el estado deseado.

¿Cuántas aplicaciones puede gestionar una instancia de ArgoCD?

Una instancia en modo HA puede gestionar cómodamente miles de Applications. El cuello de botella suele ser el application controller; configurar múltiples shards (mediante ARGOCD_CONTROLLER_REPLICAS) permite escalar horizontalmente para clústeres con cientos de Applications.

Conclusión

ArgoCD no es simplemente otra herramienta de despliegue: es un cambio de paradigma en cómo se gestiona la infraestructura y las aplicaciones en Kubernetes. El modelo pull basado en Git elimina la clase entera de problemas de drift, rollback doloroso y falta de trazabilidad que plagan los enfoques push tradicionales.

La curva de aprendizaje inicial — Projects, Applications, ApplicationSets, sync waves, hooks — puede parecer intimidante. Pero cada concepto resuelve un problema real que encontrarás en producción. Empieza con una Application simple, activa auto-sync con selfHeal, y observa cómo ArgoCD empieza a rechazar el drift. Desde ese momento, la visibilidad y el control que obtienes son difíciles de abandonar.

Para equipos que quieren profundizar más en GitOps y ArgoCD en producción, la guía de patrones de arquitectura de Kubernetes cubre cómo ArgoCD encaja en un stack de platform engineering más amplio junto con service mesh, aplicación de políticas y herramientas de observabilidad.