Módulo 5: Gitops With Argocd

2. GitOps *pull-based*: un operador que hace *watch*, no un pipeline que empuja

Descripción

La lección anterior te mostró la cita completa, pero todavía en abstracto: "un operador que corre dentro del clúster observa el repositorio Git constantemente y jala los cambios hacia adentro". Esta lección hace ese mecanismo concreto, con el mismo nivel de detalle técnico que cicd-and-gitops-on-aws-guide M7.4 usó para compararlo contra su propio apply.yml — la diferencia exacta de quién inicia el movimiento, hacia dónde viajan las credenciales, y con qué frecuencia se aplica un cambio. Todavía no instalas nada en esta lección; instalas el vocabulario preciso que las lecciones 3 y 4 van a convertir en un clúster real.

Conexión con el módulo

Esta lección es el puente entre la introducción (lección 1) y el primer "manos a la obra" (lección 3). Sin el mecanismo claro en la cabeza, instalar Gitea y ArgoCD sería seguir instrucciones sin entender qué resuelven — con el mecanismo claro, cada paso de las lecciones 3-6 tiene una razón técnica visible.


El mecanismo, lado a lado con lo que ya conoces

Si completaste cicd-and-gitops-on-aws-guide, ya viste este diagrama —o uno casi idéntico— en su Módulo 7, lección 4. Vale la pena reconstruirlo aquí, con los nombres exactos de esta guía en vez de genéricos:

   PUSH-BASED GITOPS (cicd-and-gitops-on-aws-guide, apply.yml)

   Desarrollador          GitHub                  Pipeline CI          AWS
        │                    │                         │                │
        │──git push─────────▶│                         │                │
        │                    │──dispara apply.yml─────▶│                │
        │                    │                         │──terraform apply──▶│
        │                    │                         │   (credenciales    │
        │                    │                         │    salen HACIA     │
        │                    │                         │    afuera)         │
        │                    │◀────estado actualizado──│                │

   El PIPELINE inicia el movimiento. Un evento (push a main) lo dispara.


   PULL-BASED GITOPS (este módulo, ArgoCD)

   Tú                     Gitea                   ArgoCD                andes-cargo-cluster
                       (dentro del clúster)    (dentro del clúster)     (el mismo clúster)
        │                    │                         │                     │
        │──git push─────────▶│                         │                     │
        │                    │◀── compara cada pocos segundos ────────────────│
        │                    │      (ArgoCD VIENE a buscar, nadie lo empuja)  │
        │                    │────repositorio actual─▶│                     │
        │                    │                         │──aplica dentro────▶│
        │                    │                         │   del MISMO         │
        │                    │                         │   clúster donde     │
        │                    │                         │   ya corre          │

   ArgoCD inicia el movimiento. Un temporizador interno lo dispara,
   no un evento externo. Gitea, ArgoCD y andes-cargo-cluster son,
   los tres, el mismo clúster kind — no hay ninguna frontera de red
   externa que cruzar.

La diferencia más importante frente al diagrama de cicd-and-gitops-on-aws-guide: ahí, Pipeline CI y AWS eran dos sistemas completamente distintos, con una frontera de red real entre ambos —el runner de GitHub Actions no es parte de tu cuenta de AWS—. Aquí, Gitea, ArgoCD y el clúster que ArgoCD administra son, literalmente, el mismo kind create cluster. Esto no es una simplificación del laboratorio: es, de hecho, más fiel al patrón real de producción que el ejemplo de cicd-and-gitops-on-aws-guide con AWS — en un EKS real (Módulo 7 de esta guía), ArgoCD también corre como Pods dentro del propio clúster que sincroniza, aunque el repositorio Git normalmente viva en un servicio externo (GitHub, GitLab).


La secuencia completa, como flujo

sequenceDiagram
    participant Tu as Tú
    participant Gitea as Gitea (namespace gitea)
    participant ArgoCD as ArgoCD (namespace argocd)
    participant K8s as andes-cargo-cluster (namespace andes-cargo)

    Tu->>Gitea: git push (deployment.yaml cambiado)

    loop cada pocos segundos
        ArgoCD->>Gitea: poll del repositorio andes-cargo-k8s
        Gitea-->>ArgoCD: último commit en main
    end

    ArgoCD->>ArgoCD: compara Git (deseado) vs clúster (real)

    alt hay diferencia
        ArgoCD->>K8s: aplica el estado declarado en Git
        K8s-->>ArgoCD: estado reconciliado
    else sin diferencia
        ArgoCD->>ArgoCD: Sync Status permanece "Synced"
    end

El paso que no tiene equivalente en apply.yml: el bucle loop cada pocos segundos. apply.yml no tiene ningún bucle — corre una vez, cuando GitHub le avisa que hubo un push, y termina. ArgoCD nunca "termina": el Pod de argocd-application-controller (vas a verlo correr de verdad en la lección 4) queda comparando, indefinidamente, mientras el clúster exista.


Analogía: el termostato que lee la libreta, no la persona que llama a la calefacción

Imagina dos formas de mantener una habitación a la temperatura correcta. En la primera, cada vez que hace frío, tú mismo llamas a la calefacción y le pides que se encienda — funciona, pero exige que estés presente y atento todo el tiempo. En la segunda, hay un termostato en la pared: lee, cada pocos segundos, una temperatura objetivo que anotaste en una libreta, la compara contra la temperatura real de la habitación, y enciende o apaga la calefacción él solo, sin que tú intervengas — ni siquiera necesitas estar en la casa. Tú sigues siendo quien decide la temperatura objetivo (escribiendo en la libreta); lo que el termostato elimina es la necesidad de que tú ejecutes la corrección cada vez.

apply.yml es la primera forma: cada push a main es, literalmente, la llamada a la calefacción. ArgoCD es el termostato: la "libreta" es el repositorio andes-cargo-k8s en Gitea, la "temperatura real" es el estado actual de andes-cargo-cluster, y el ciclo de comparación corre solo, cada pocos segundos, mientras el Pod de ArgoCD esté vivo.


Qué NO cambia frente a apply.yml: las cuatro propiedades de GitOps

cicd-and-gitops-on-aws-guide M7.4 ya estableció esta tabla para su propio caso. Vale la pena reconstruirla con los nombres de esta guía, porque el punto es el mismo: push y pull son dos implementaciones del mismo principio, ninguna es "GitOps más completo" que la otra.

Propiedad de GitOpsCómo la cumple apply.yml (cicd-and-gitops-on-aws-guide)Cómo la cumple ArgoCD (este módulo)
Estado deseado, declaradoHCL de TerraformManifiestos de Kubernetes (deployment.yaml, etc.)
Git como única fuente de verdadpush a main, revisado antes de fusionarIgual — push a main en el repositorio de Gitea
Aplicación automática de cambiosapply.yml, disparado por el evento pushArgoCD, disparado por su propio temporizador interno
Reconciliación continuadrift.yml, programado, detecta y avisaselfHeal: true, continuo, detecta y corrige

La última fila es, otra vez, la diferencia más concreta: drift.yml de cicd-and-gitops-on-aws-guide corre en un horario y avisa si algo cambió — la corrección exige que una persona revise y apruebe un apply nuevo. selfHeal: true de ArgoCD, que vas a ver en acción con evidencia real en la lección 5, corrige solo, sin que nadie apruebe nada, en el momento exacto en que detecta la diferencia.


La implicación de seguridad, la misma que ya conoces

cicd-and-gitops-on-aws-guide M7.4 construyó esta tabla para explicar por qué la industria de Kubernetes prefiere pull. Se aplica sin cambios a este módulo:

Push (apply.yml)Pull (ArgoCD, este módulo)
¿Quién tiene credenciales de escritura hacia el destino?El pipeline de CI (externo a AWS)Nadie externo — ArgoCD ya vive dentro de andes-cargo-cluster
¿Dónde viven esas credenciales?Secreto de GitHub Actions, inyectado en cada corridaNo existen credenciales "externas" — ArgoCD usa el ServiceAccount con el que ya corre
Si el sistema que inicia el cambio se comprometeUn atacante con acceso al pipeline puede escribir en AWS directamenteNo aplica — no hay credenciales de escritura hacia afuera que robar

La diferencia concreta en este laboratorio: cuando instales ArgoCD en la lección 4, no vas a configurar ninguna credencial de AWS, ninguna clave de acceso, nada que "salga" del clúster hacia un destino externo — porque el destino es el clúster donde ArgoCD ya corre. La única credencial que sí vas a configurar es de lectura, de ArgoCD hacia el repositorio de Gitea (y, en este laboratorio, ni siquiera hace falta: el repositorio es público dentro del clúster, como vas a confirmar en la lección 3).


Errores comunes

Pensar que "cada pocos segundos" significa "instantáneo" (de expectativa, choca con la lección 8). Qué pasa: alguien, en la lección 8, hace git push y espera ver el cambio reflejado en el mismo segundo, como si fuera un push-based. Cómo detectarlo: si te alarmas al ver que kubectl get pods todavía muestra el estado viejo diez segundos después de tu git push. Cómo corregirlo: ArgoCD sondea el repositorio en un intervalo (por defecto, unos pocos minutos; configurable) — no es instantáneo por diseño, aunque sí soporta webhooks para reducir esa latencia cuando hace falta. La lección 8 mide, con timestamps reales, cuánto tarda exactamente en este laboratorio.

Confundir "el repositorio vive dentro del clúster" con "ArgoCD no necesita ningún permiso" (el mismo error que ya advirtió cicd-and-gitops-on-aws-guide M7.4, aquí con más razón porque todo está en el mismo clúster). Qué pasa: alguien concluye que, como todo corre en kind, no hace falta configurar ningún tipo de acceso. Cómo detectarlo: si te sorprende ver, en la lección 4, que ArgoCD se instala con su propio conjunto de ServiceAccount/ClusterRole. Cómo corregirlo: ArgoCD sigue necesitando permisos explícitos de Kubernetes (RBAC) para crear, actualizar y borrar recursos dentro de los namespaces que administra — "vivir dentro del clúster" elimina la necesidad de credenciales externas de AWS o de otro proveedor, no la necesidad de permisos de Kubernetes en general.

Creer que este mecanismo es exclusivo de ArgoCD, y que "GitOps" y "ArgoCD" son sinónimos (de vocabulario impreciso). Qué pasa: alguien empieza a usar "hacer GitOps" y "usar ArgoCD" como si fueran la misma frase. Por qué pasa: ArgoCD es, hoy, la herramienta más citada del mercado para este mecanismo (la evidencia de VALIDACION.md que abrió esta guía lo confirma). Cómo detectarlo: si no puedes nombrar ninguna otra herramienta que implemente el mismo mecanismo. Cómo corregirlo: Flux (nombrado en cicd-and-gitops-on-aws-guide M7.3) implementa exactamente el mismo principio pull-based, con una forma distinta (GitRepository + Kustomization en vez de Application). GitOps es el principio (Git como fuente de verdad, con reconciliación continua); ArgoCD es una herramienta que lo implementa, no la única.


Ejercicios

Ejercicio 1 — Dibuja el diagrama de credenciales, sin ayuda. Sin mirar esta lección, dibuja (en texto) las dos flechas de credenciales: ¿hacia dónde viajan en apply.yml, y hacia dónde en ArgoCD?

Ver solución

apply.yml (push): las credenciales viajan desde el runner de GitHub Actions (externo a AWS) hacia AWS — el pipeline necesita autenticarse para poder escribir ahí. ArgoCD (pull): no hay credenciales de escritura que crucen ninguna frontera — ArgoCD ya corre dentro de andes-cargo-cluster, el mismo clúster que administra, así que usa el ServiceAccount con el que ya está autenticado localmente. La única credencial que cruza una frontera es de lectura, de ArgoCD hacia Gitea — y en este laboratorio, ni siquiera esa, porque el repositorio es público dentro del clúster.

Ejercicio 2 — Aplica la distinción a un escenario nuevo. Un colega propone: "en vez de instalar ArgoCD, hagamos que un CronJob de Kubernetes corra kubectl apply -f contra el repositorio cada cinco minutos". ¿Ese diseño es push o pull? Justifica con el criterio de esta lección (quién inicia el movimiento, no dónde vive el destino).

Ver solución

Es, en espíritu, pull-based — aunque más rudimentario que ArgoCD. El criterio de esta lección no es "¿el destino es Kubernetes?", es "¿quién inicia el movimiento, y desde dónde?". Un CronJob que corre dentro del propio clúster, en un temporizador interno, y va a buscar el estado deseado a un repositorio Git, cumple la misma forma que ArgoCD: el propio clúster inicia la comparación, sin que un evento externo lo dispare. Le faltarían, frente a ArgoCD, cosas concretas que sí importan en producción: comparación declarativa fina (no solo "reaplicar todo"), selfHeal real, una UI de estado, prune seguro de recursos eliminados — por eso la industria no reinventa esto con un CronJob casero, pero la forma básica del mecanismo (pull, no push) es la misma.

Ejercicio 3 — Explica por qué Gitea, ArgoCD y andes-cargo-cluster "son el mismo clúster" no es una simplificación del laboratorio. En dos o tres frases, explica a un colega por qué este detalle de arquitectura de este módulo es, de hecho, más representativo de un EKS real que el ejemplo de AWS de cicd-and-gitops-on-aws-guide.

Ver solución

Una explicación razonable: "En un EKS real de producción, ArgoCD también corre como Pods dentro del propio clúster que administra — eso no cambia entre kind y EKS, es la forma estándar de instalar ArgoCD en cualquier lado. Lo que sí suele cambiar es dónde vive el repositorio Git: en producción normalmente es un servicio externo como GitHub, mientras que este laboratorio lo trae adentro también (Gitea, dentro del mismo clúster) para no depender de ninguna cuenta externa con $0. La parte que importa para entender el mecanismo —el operador vive dentro de lo que administra— es idéntica en los dos casos."


Resumen y siguiente paso

Esta lección hizo concreto el mecanismo que la introducción del módulo nombró: un operador que vive dentro del clúster, compara el estado real contra un repositorio Git cada pocos segundos, y corrige la diferencia sin que ningún evento externo lo dispare — el opuesto exacto de apply.yml, que reacciona a un push desde afuera. Confirmaste que las cuatro propiedades de GitOps se cumplen en ambos mecanismos, y que la ventaja de seguridad de pull (ninguna credencial de escritura viaja hacia el clúster desde afuera) tiene un costo real: latencia de sondeo en vez de reacción instantánea, y la necesidad de un clúster de Kubernetes corriendo para que el operador tenga dónde vivir.

Antes de avanzar deberías poder: dibujar de memoria el diagrama de secuencia de esta lección; explicar la diferencia entre drift.yml (detecta y avisa) y selfHeal: true (detecta y corrige); y defender por qué Gitea, ArgoCD y andes-cargo-cluster viviendo en el mismo kind no es una simplificación artificial del laboratorio.

Siguiente lección: manos a la obra, Gitea en el clúster. Ahí instalas la primera pieza real de este mecanismo — el repositorio Git que ArgoCD va a observar, corriendo dentro de tu propio clúster, con el Helm chart oficial del proyecto.

Recursos

  1. cicd-and-gitops-on-aws-guide (NIEVA), Módulo 7, lección 4 — la fuente completa del diagrama y las tablas de esta lección, aquí adaptados a Kubernetes ejecutado de verdad.
  2. Argo CD — How it works — documentación oficial del mecanismo de reconciliación continua de ArgoCD.
  3. Weaveworks Blog — What Is GitOps, Really? — el origen del término GitOps, ya citado en cicd-and-gitops-on-aws-guide, base de las cuatro propiedades de esta lección.
  4. Gitea — Documentation — el servidor Git que la lección 3 instala dentro del clúster.