GitOps con Git como fuente de verdad: guía práctica
GitOps no es 'usar Git para desplegar'. Es un modelo concreto donde un controlador dentro del clúster tira de los cambios en vez de que un pipeline externo los empuje. La diferencia importa para la seguridad y la fiabilidad.
“Usamos Git para desplegar” es la frase que más confusión genera alrededor de GitOps. Cualquier pipeline de CI/CD moderno usa Git como disparador: haces push, algo se ejecuta, algo se despliega. Eso no es GitOps, es simplemente CI/CD con Git como origen. GitOps es un modelo más estricto y más concreto: Git no es solo el disparador, es la única fuente de verdad del estado deseado del sistema, y algo que vive dentro del entorno de destino se encarga de comprobar continuamente que la realidad coincide con lo que dice el repositorio, y de corregirla si no coincide.
Esa diferencia —quién tira de quién— es la que separa un pipeline de despliegue convencional de un sistema GitOps real, y tiene consecuencias directas en seguridad, en capacidad de auditoría y en qué pasa cuando algo se desvía sin que nadie lo autorice.
Los cuatro principios (y por qué no son opcionales)
El proyecto OpenGitOps, bajo el paraguas de la CNCF, formalizó cuatro principios que definen si un sistema es GitOps o no lo es:
- Declarativo: el estado deseado se describe de forma declarativa (qué debe existir), no imperativa (qué comandos ejecutar). Un manifiesto de Kubernetes en YAML es declarativo; un script que hace una secuencia de
kubectl create,kubectl patchykubectl scaleno lo es, aunque viva en Git. - Versionado e inmutable: el estado deseado se guarda de una forma que garantiza historial completo, versionado e inmutabilidad — en la práctica, un repositorio Git con su historial de commits, sus pull requests y su capacidad de volver a cualquier punto anterior.
- Extraído automáticamente (pull, no push): un agente de software dentro del entorno de destino extrae las declaraciones de estado deseado desde la fuente, en vez de que un sistema externo las empuje hacia el entorno.
- Reconciliado continuamente: ese mismo agente observa el estado real del sistema de forma continua e intenta converger hacia el estado deseado, sin esperar a que alguien dispare un despliegue.
Los tres primeros principios son relativamente fáciles de cumplir con cualquier pipeline moderno. El cuarto —reconciliación continua— es el que de verdad distingue a GitOps: un pipeline tradicional despliega una vez y se olvida; un controlador GitOps sigue vigilando después.
graph LR Dev[Developer] -->|"pull request"| Repo[(Repositorio Git manifiestos)] Repo -->|"merge a main"| RepoMain[Estado deseado] Controller[Controlador GitOps ArgoCD / Flux] -->|"pull periódico"| RepoMain Controller -->|"compara"| Cluster[Estado real del clúster] Controller -->|"reconcilia"| Cluster Cluster -.->|"drift detectado"| Controller
Push vs. pull: la diferencia que importa para seguridad
En un pipeline de CI/CD tradicional tipo “push”, es el propio sistema de CI —GitHub Actions, GitLab CI, Jenkins— el que se conecta activamente al clúster de destino y aplica los cambios, típicamente con kubectl apply o helm upgrade ejecutados desde el runner. Para que eso funcione, el runner necesita credenciales con permisos de escritura sobre el clúster, casi siempre almacenadas como secretos en el propio sistema de CI.
En un modelo “pull” —el que usan Argo CD y Flux—, el runner de CI ya no necesita esas credenciales en absoluto. Su trabajo termina en construir la imagen, pasar los tests y actualizar el manifiesto en Git (por ejemplo, cambiando el tag de la imagen). El controlador GitOps, que vive dentro del propio clúster, es quien detecta ese cambio y lo aplica, usando credenciales que nunca salen del clúster.
Esto tiene implicaciones concretas:
- Superficie de ataque menor: ningún sistema externo guarda credenciales privilegiadas de escritura sobre producción. Si el sistema de CI se ve comprometido, el atacante no hereda acceso directo al clúster.
- Tráfico de red más simple de asegurar: el controlador solo necesita salida (egress) hacia el repositorio Git; no hace falta abrir entrada hacia el clúster desde una red externa.
- Detección de drift: si alguien —o algo— modifica un recurso directamente en el clúster con
kubectl edit, fuera del flujo de Git, el controlador lo detecta en el siguiente ciclo de reconciliación y, según la configuración, lo revierte automáticamente al estado declarado en Git. Esto convierte a Git en una fuente de verdad real, no solo nominal: los cambios manuales dejan de sobrevivir. - Rollback trivial: revertir un despliegue problemático es un
git revertsobre el commit que lo introdujo, no una secuencia de comandos manuales contra el clúster bajo presión.
ArgoCD vs. Flux: dos formas de implementar lo mismo
Ambos son proyectos graduados de la CNCF, ambos implementan el mismo modelo pull-based, y ambos son razonablemente maduros para producción en 2026. La diferencia está en la filosofía:
| Argo CD | Flux | |
|---|---|---|
| Enfoque | Centrado en aplicación, con un servidor y una UI web propia | Conjunto de controladores pequeños y componibles, sin UI propia |
| Interfaz | Dashboard visual con vista de árbol de recursos, diffs y sincronización manual/automática | Se opera vía CLI y CRDs; la observabilidad se delega en herramientas externas (Grafana, Weave GitOps) |
| Multi-tenency | RBAC y SSO propios, pensado para que varios equipos compartan una instancia | Cada controlador es más ligero; el aislamiento se apoya más en namespaces y en la estructura del repositorio |
| Curva de entrada | Más rápida de ver “funcionando” gracias a la UI | Requiere más familiaridad con Kubernetes y sus CRDs desde el principio |
Ninguna es objetivamente superior: equipos que valoran una interfaz visual para que developers no familiarizados con Kubernetes puedan ver el estado de sus despliegues tienden a preferir Argo CD; equipos que ya operan con una filosofía muy centrada en Kubernetes puro y prefieren piezas pequeñas y componibles tienden a preferir Flux. Ambos se pueden combinar con Kubernetes sin fricción porque los dos actúan como controladores nativos del clúster.
Montarlo paso a paso en un proyecto real
Un flujo GitOps mínimo pero real separa dos repositorios (o dos carpetas claramente diferenciadas dentro de uno): el repositorio de código de la aplicación y el repositorio de configuración/estado deseado.
1. El repositorio de aplicación sigue haciendo CI normal
# .github/workflows/build.yml
name: build-and-publish
on:
push:
branches: [main]
permissions:
contents: read
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/miorg/miapp:${{ github.sha }}
Este pipeline construye y publica la imagen. Termina ahí: no hace kubectl apply, no toca el clúster.
2. Un paso final actualiza el repositorio de configuración
- name: Actualizar manifiesto de despliegue
run: |
git clone https://github.com/miorg/config-repo.git
cd config-repo
sed -i "s|image: ghcr.io/miorg/miapp:.*|image: ghcr.io/miorg/miapp:${{ github.sha }}|" apps/miapp/deployment.yaml
git commit -am "chore: actualiza miapp a ${{ github.sha }}"
git push
Este es el único punto de contacto entre CI y GitOps: CI escribe en Git, no toca el clúster.
3. El controlador GitOps vigila ese segundo repositorio
# Application de Argo CD
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: miapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/miorg/config-repo.git
targetRevision: main
path: apps/miapp
destination:
server: https://kubernetes.default.svc
namespace: miapp
syncPolicy:
automated:
prune: true
selfHeal: true
selfHeal: true es la reconciliación continua en acción: si alguien cambia algo manualmente en el clúster, Argo CD lo revierte al estado declarado en config-repo. prune: true elimina del clúster cualquier recurso que ya no exista en el repositorio.
4. Promoción entre entornos, sin duplicar lógica de despliegue
La forma habitual de gestionar staging y producción en GitOps no es tener pipelines distintos, sino carpetas o ramas distintas dentro del mismo repositorio de configuración (environments/staging, environments/production), con herramientas como Kustomize para expresar las diferencias como overlays sobre una base común. Promocionar a producción se convierte en un pull request que copia un cambio de una carpeta a otra — auditable, revisable y reversible como cualquier otro cambio de código.
Cuándo NO merece la pena
GitOps añade piezas: un controlador que mantener, un segundo repositorio o estructura de carpetas que sincronizar, una curva de aprendizaje sobre reconciliación y drift. Para un proyecto pequeño con un único entorno y despliegues poco frecuentes, un pipeline de CI/CD tradicional que haga kubectl apply directamente puede ser perfectamente razonable y mucho más simple de operar. GitOps demuestra su valor cuando hay varios clústeres o entornos que mantener consistentes, cuando la auditoría de “qué cambió y quién lo aprobó” importa de verdad (regulación, compliance), o cuando el equipo ya ha crecido lo suficiente como para que la coordinación manual de despliegues empiece a fallar.
Esto conecta directamente con Platform Engineering: GitOps es, en la práctica, la tubería de despliegue que casi todos los Internal Developer Platforms usan por debajo, precisamente porque le da al developer una experiencia simple (un pull request) mientras mantiene el control y la auditoría en manos de la plataforma. Si además el pipeline de CI que alimenta ese repositorio de configuración necesita reforzarse en seguridad y velocidad, es la continuación natural de este artículo revisar los patrones de CI/CD en producción con GitHub Actions.
Artículos relacionados
Platform Engineering en 2026: qué es y por qué está reemplazando al DevOps tradicional
DevOps prometía que cada equipo fuera dueño de su infraestructura. En la práctica, eso se ha traducido en desarrolladores agotados de configurar YAML. Platform Engineering es la respuesta organizativa a ese problema.
Monorepos full-stack en 2026: Turborepo, Nx y cuándo merece la pena
Un monorepo no es una arquitectura ni una moda: es una forma de organizar código que solo compensa a partir de ciertas señales. Comparamos Turborepo y Nx sin dogmatismo.
CI/CD moderno con GitHub Actions: patrones de producción
Un workflow de GitHub Actions que funciona en la demo y uno que aguanta un equipo grande en producción no se parecen tanto como crees. La diferencia está en la estructura, los permisos y lo que decides cachear.