GitOps en 2026: gestión de infraestructura Kubernetes con ArgoCD y CI/CD automatizado
Introducción: qué es GitOps y cómo se diferencia del CI/CD clásico
GitOps es un modelo operativo en el que el repositorio Git es la única fuente de verdad sobre el estado de la infraestructura y las aplicaciones. Cualquier cambio en el clúster Kubernetes se realiza a través de un pull request, no mediante un kubectl apply manual ni un comando directo desde el pipeline.
La principal diferencia arquitectónica entre GitOps y el CI/CD clásico es el modelo push vs. modelo pull. En el esquema CI/CD clásico, el pipeline "empuja" los cambios al clúster: accede a la API de Kubernetes, se autentica y aplica los manifiestos. En GitOps funciona de otra manera:
- Modelo push (clásico): Jenkins/GitLab CI → kubectl apply → clúster. El pipeline tiene acceso directo al clúster y los secretos se almacenan en el sistema de CI.
- Modelo pull (GitOps): Repositorio Git → ArgoCD dentro del clúster → clúster. El operador dentro del clúster extrae el estado deseado desde Git.
El modelo pull tiene ventajas fundamentales: no es necesario "exponer" el clúster al exterior, el pipeline externo no almacena kubeconfig con amplios permisos y cada cambio pasa por una revisión de código en Git.
En 2026, GitOps se ha convertido en el estándar de facto para los equipos que trabajan con Kubernetes. ArgoCD y Flux son las dos herramientas más utilizadas. En este artículo analizaremos en detalle el enfoque con ArgoCD, construiremos un pipeline CI/CD completo con GitHub Actions y mostraremos cómo organizar un repositorio GitOps para múltiples entornos.
Principios de GitOps
GitOps se basa en cuatro principios fundamentales formulados por Weaveworks y consolidados en OpenGitOps 1.0:
1. Declaratividad
Todo el estado deseado del sistema se describe de forma declarativa: mediante manifiestos de Kubernetes, charts de Helm o configuraciones de Kustomize. Se describe qué debe existir, no cómo lograrlo.
2. Fuente única de verdad
El repositorio Git es el único lugar donde se almacena el estado actual de la infraestructura. Sin "parches manuales" directamente en el clúster, sin cambios mediante kubectl sin un commit en Git.
3. Sincronización automática
El operador (ArgoCD) compara continuamente el estado deseado (Git) con el real (clúster) y lleva automáticamente el clúster al estado deseado.
4. Auditoría a través del historial de Git
Cada cambio en la infraestructura es un commit con autor, fecha y descripción. Un audit trail completo de forma gratuita. La reversión es un simple git revert.
ArgoCD: instalación en el clúster, conceptos de Application y AppProject
Instalación de ArgoCD
ArgoCD se instala en un namespace dedicado del clúster Kubernetes. Se recomienda usar el chart Helm oficial para instalaciones en producción:
# Creamos el namespace
kubectl create namespace argocd
# Instalamos con Helm
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd \
--namespace argocd \
--set server.service.type=LoadBalancer \
--set configs.params."server.insecure"=true \
--version 6.7.0
# Obtenemos la contraseña inicial de admin
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
Tras la instalación, ArgoCD ofrece una interfaz web y la herramienta CLI argocd. La CLI se instala por separado y permite gestionar aplicaciones, sincronización y proyectos desde la terminal.
Concepto de Application
La unidad principal de ArgoCD es la Application. El objeto Application define de dónde tomar los manifiestos (source) y dónde aplicarlos (destination):
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-service
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/gitops-repo.git
targetRevision: HEAD
path: apps/my-service/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Concepto de AppProject
AppProject es una agrupación de aplicaciones con restricciones: qué repositorios están permitidos como fuente, en qué namespaces y clústeres se puede desplegar, qué recursos están permitidos. Esto es fundamental para clústeres multi-tenant donde diferentes equipos trabajan de forma aislada.
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: backend-team
namespace: argocd
spec:
description: Backend microservices team
sourceRepos:
- https://github.com/myorg/gitops-repo.git
destinations:
- namespace: production
server: https://kubernetes.default.svc
- namespace: staging
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
Estructura del repositorio GitOps
Mono-repo vs. Multi-repo
Existen dos enfoques principales para organizar un repositorio GitOps:
- Mono-repo: todos los manifiestos de todos los servicios y entornos en un único repositorio. Más fácil de comenzar, conveniente para equipos pequeños y con una revisión de código unificada.
- Multi-repo: un repositorio separado para cada servicio o entorno. Escala mejor, con límites de acceso claros, pero es más complejo gestionar las dependencias entre servicios.
Para la mayoría de los equipos que comienzan con GitOps en 2026, recomendamos el mono-repo con una estructura de directorios clara. A continuación se muestra la estructura recomendada:
gitops-repo/
├── apps/
│ ├── api-service/
│ │ ├── base/
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ ├── configmap.yaml
│ │ │ └── kustomization.yaml
│ │ └── overlays/
│ │ ├── dev/
│ │ │ ├── kustomization.yaml
│ │ │ └── patch-replicas.yaml
│ │ ├── staging/
│ │ │ ├── kustomization.yaml
│ │ │ └── patch-resources.yaml
│ │ └── production/
│ │ ├── kustomization.yaml
│ │ └── patch-hpa.yaml
│ └── worker-service/
│ ├── base/
│ └── overlays/
├── infrastructure/
│ ├── cert-manager/
│ ├── ingress-nginx/
│ └── monitoring/
├── argocd/
│ ├── projects/
│ │ └── backend-team.yaml
│ └── applications/
│ ├── api-service-dev.yaml
│ ├── api-service-staging.yaml
│ └── api-service-production.yaml
└── helm-charts/
└── base-service/
├── Chart.yaml
├── values.yaml
└── templates/
Kustomize vs. Helm en GitOps
Kustomize está integrado en kubectl y ArgoCD lo soporta de forma nativa. El enfoque base/overlays permite tener una configuración base común y sobrescribir solo lo que difiere entre entornos: por ejemplo, el número de réplicas, los límites de recursos o los nombres de imágenes.
Helm es conveniente para charts complejos con gran cantidad de parámetros. ArgoCD soporta charts de Helm directamente: se indica la ruta al chart y el archivo values en la Application. En el enfoque GitOps con Helm, se recomienda almacenar en Git no las plantillas en sí, sino el values.yaml para cada entorno.
Construcción del pipeline CI con GitHub Actions
En GitOps, CI y CD se dividen en dos etapas independientes. El pipeline CI se encarga únicamente de compilar y publicar la imagen Docker, así como de actualizar el tag de la imagen en el repositorio GitOps. ArgoCD recoge el cambio y ejecuta el despliegue.
A continuación se muestra un ejemplo completo del workflow de GitHub Actions para la parte CI:
name: CI — Build and Update Manifest
on:
push:
branches: [main]
paths:
- 'src/**'
- 'Dockerfile'
env:
REGISTRY: ghcr.io
IMAGE_NAME: myorg/api-service
GITOPS_REPO: myorg/gitops-repo
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=,suffix=,format=short
type=ref,event=branch
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Update image tag in GitOps repo
env:
IMAGE_TAG: ${{ github.sha }}
GITOPS_TOKEN: ${{ secrets.GITOPS_PAT }}
run: |
SHORT_SHA=$(echo "$IMAGE_TAG" | cut -c1-7)
git config --global user.email "ci-bot@myorg.com"
git config --global user.name "CI Bot"
git clone https://x-access-token:${GITOPS_TOKEN}@github.com/${GITOPS_REPO}.git gitops
cd gitops
# Actualizamos el tag de la imagen con kustomize
cd apps/api-service/overlays/dev
kustomize edit set image api-service=${REGISTRY}/${IMAGE_NAME}:${SHORT_SHA}
git add .
git commit -m "chore: update api-service image to ${SHORT_SHA}"
git push
Puntos clave de este pipeline: CI no conoce el clúster Kubernetes en absoluto. Solo actualiza el manifiesto en el repositorio GitOps. El token GITOPS_PAT es un Personal Access Token con permiso de escritura únicamente en el repositorio GitOps, no en el clúster.
Estrategias de despliegue con ArgoCD
Sincronización automática para dev y staging
Para los entornos dev y staging se recomienda habilitar la sincronización automática. En cuanto aparece un nuevo commit en el repositorio GitOps, ArgoCD aplica los cambios automáticamente:
syncPolicy:
automated:
prune: true # eliminar recursos que no existen en Git
selfHeal: true # revertir cambios manuales en el clúster
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
Confirmación manual para producción
Para el entorno de producción, la sincronización automática se desactiva. El despliegue requiere confirmación explícita a través de la UI de ArgoCD o la CLI. Esto permite realizar una revisión final antes de aplicar los cambios:
syncPolicy: {} # sin sincronización automática
# El despliegue se realiza manualmente:
# argocd app sync api-service-production
También es posible configurar sync windows: ventanas de tiempo en las que la sincronización está permitida. Por ejemplo, prohibir despliegues en producción los viernes por la tarde y los fines de semana es una práctica estándar.
Estrategias de actualización
ArgoCD soporta las estrategias nativas de Kubernetes: RollingUpdate y Recreate. Para escenarios más complejos —canary y blue/green— se utiliza Argo Rollouts, una extensión de ArgoCD que añade el CRD Rollout en lugar del Deployment estándar.
Gestión de secretos en GitOps
El principal problema de GitOps es que los secretos no pueden almacenarse en Git en texto plano. Existen varios enfoques para resolverlo.
Sealed Secrets
Sealed Secrets de Bitnami permite cifrar un secreto con la clave pública del clúster. El SealedSecret cifrado se almacena de forma segura en Git. El controlador dentro del clúster lo descifra con la clave privada y crea un Secret normal.
# Instalamos el CLI kubeseal
brew install kubeseal
# Obtenemos la clave pública del clúster
kubeseal --fetch-cert \
--controller-name=sealed-secrets-controller \
--controller-namespace=kube-system \
> pub-cert.pem
# Creamos un Secret normal y lo ciframos
kubectl create secret generic db-credentials \
--from-literal=password=supersecret \
--dry-run=client -o yaml | \
kubeseal --cert pub-cert.pem \
--format yaml > db-credentials-sealed.yaml
# db-credentials-sealed.yaml se puede commitear en Git de forma segura
La ventaja de Sealed Secrets: es completamente nativo para GitOps y todo se almacena en el repositorio. La desventaja: si se pierde la clave privada del clúster, todos los secretos deben recrearse.
External Secrets Operator
External Secrets Operator (ESO) se integra con almacenes externos de secretos: AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, Azure Key Vault. En Git solo se almacena el ExternalSecret, una referencia al secreto en el almacén externo:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: prod/api-service/db
property: password
ESO es el enfoque preferido para producción en 2026, especialmente si la organización ya utiliza un almacén de secretos centralizado. En Git solo se almacenan metadatos, no los datos en sí.
Multi-entorno: dev, staging, producción
Existen dos enfoques populares para organizar múltiples entornos en GitOps:
Enfoque por directorios (recomendado)
Cada entorno es un subdirectorio separado en el repositorio. Todos los entornos están en la rama main. Los cambios pasan por PR. La promoción entre entornos es un commit que actualiza el tag de la imagen en el directorio del siguiente entorno:
apps/api-service/overlays/dev/— sincronización automática en cada push a mainapps/api-service/overlays/staging/— sincronización tras pruebas exitosas en devapps/api-service/overlays/production/— sincronización manual tras aprobación
Enfoque por ramas
Cada entorno es una rama separada (dev, staging, main/production). ArgoCD observa una rama específica. La promoción consiste en hacer merge entre ramas. Este enfoque es más difícil de gestionar y no se recomienda para proyectos nuevos, ya que las ramas divergen y es complicado rastrear qué está desplegado en cada entorno.
Para la promoción automática entre entornos se puede usar un workflow de GitHub Actions que, tras un despliegue exitoso en staging, crea un PR con el tag de imagen actualizado en el directorio de producción.
Detección de drift y Self-Healing
Una de las capacidades clave de ArgoCD es la detección de drift de configuración (configuration drift). Esta situación ocurre cuando el estado real del clúster diverge del estado deseado en Git.
El drift puede surgir por:
- Un
kubectl editokubectl scalemanual directamente en el clúster - El autoescalado (HPA modifica el número de réplicas)
- Operadores de Kubernetes que modifican recursos
- Fallos en sincronizaciones anteriores
ArgoCD compara continuamente (por defecto cada 3 minutos) el estado deseado y el real. Al detectar drift, la aplicación recibe el estado OutOfSync.
Con selfHeal: true activado, ArgoCD lleva automáticamente el clúster al estado definido en Git. Esto significa que cualquier cambio manual será sobreescrito, que es precisamente el objetivo de GitOps: Git es la única fuente de verdad.
Un detalle importante: si HPA gestiona el número de réplicas, no conviene especificar replicas en el manifiesto Deployment (o usar la anotación de ArgoCD para ignorar ese campo), de lo contrario ArgoCD revertirá constantemente los cambios del HPA:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api-service
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
Métricas de éxito en GitOps: DORA Metrics
La transición a GitOps debe medirse con métricas concretas. El estándar de la industria son las métricas DORA (DevOps Research and Assessment):
- Deployment Frequency (Frecuencia de despliegues): con qué frecuencia el equipo despliega en producción. GitOps reduce la barrera para el despliegue: un commit en el repositorio lanza automáticamente el proceso. Los equipos de élite despliegan varias veces al día.
- Lead Time for Changes (Tiempo desde el commit hasta producción): tiempo desde el commit del código hasta el despliegue en funcionamiento. Con GitOps y CI/CD automatizado, este tiempo se reduce a minutos.
- Change Failure Rate (Tasa de cambios fallidos): qué porcentaje de despliegues provoca incidentes. El despliegue declarativo y la revisión de código mediante PR reducen este indicador.
- Mean Time to Recovery (Tiempo medio de recuperación): con qué rapidez el equipo se recupera tras un incidente. En GitOps, la reversión es un
git revert+ ArgoCD sync, lo que lleva minutos.
Para recopilar estas métricas en entornos Kubernetes se utiliza la combinación Prometheus + Grafana. ArgoCD exporta métricas en formato Prometheus por defecto: número de sincronizaciones, estados de las aplicaciones, tiempo del último despliegue.
# Ejemplo de consulta PromQL para monitorizar ArgoCD
# Número de sincronizaciones exitosas en las últimas 24 horas
sum(increase(argocd_app_sync_total{phase="Succeeded"}[24h])) by (name)
# Aplicaciones en estado OutOfSync
argocd_app_info{sync_status="OutOfSync"}
Conclusión: errores comunes al migrar a GitOps
La transición a GitOps implica un cambio no solo de herramientas, sino también de procesos. Estos son los errores más frecuentes de los equipos:
Error 1: almacenar secretos en Git en texto plano
Es el error más crítico. Utiliza Sealed Secrets o External Secrets Operator desde el primer día. Nunca hagas commit de un kind: Secret con datos sin cifrar.
Error 2: realizar cambios manuales en el clúster junto con GitOps
Si parte del equipo sigue usando kubectl apply directamente, GitOps pierde sentido. Es necesario establecer una prohibición organizativa de los cambios directos y configurar RBAC para que los desarrolladores no tengan permisos de edición en el namespace de producción.
Error 3: un repositorio GitOps monolítico sin estructura
Sin una estructura de directorios clara, el repositorio se vuelve inmanejable rápidamente. Define desde el principio la estructura base/overlays y la separación por equipos mediante AppProject.
Error 4: habilitar la sincronización automática en producción desde el primer día
Empieza con sincronización manual en producción. El equipo debe acostumbrarse al proceso y comprender qué hace ArgoCD antes de darle autonomía en un entorno crítico.
Error 5: ignorar la detección de drift
Si ArgoCD muestra una aplicación en estado OutOfSync, es una señal para investigar. No pulses "Sync" sin entender por qué se produjo el drift.
Error 6: ausencia de pruebas de manifiestos en CI
Añade al pipeline CI del repositorio GitOps la validación de manifiestos: kustomize build | kubeval o helm lint. Esto detectará errores de sintaxis antes de que ArgoCD intente aplicarlos en el clúster.
GitOps en 2026 no es solo una herramienta, es una cultura de trabajo con la infraestructura. Una transición exitosa requiere tanto la configuración técnica de ArgoCD y los pipelines CI/CD como un cambio en los procesos del equipo: todo a través de PR, todo a través de Git, sin cambios manuales.
Empieza por algo pequeño: despliega un servicio no crítico con ArgoCD en el entorno dev. Asegúrate de que el equipo comprende el ciclo "commit → CI → actualización del manifiesto → ArgoCD sync". Luego migra gradualmente el resto de servicios y entornos. GitOps con ArgoCD es una inversión que se amortiza mediante la mejora de las métricas DORA y el aumento de la fiabilidad de los despliegues.
Tecnologías
Etiquetas
Ruslan Ismailov
Desarrollador Senior Web / Backend. Desarrollador senior web/backend con 9 años de experiencia. Stack: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, microservicios, CI/CD. Más sobre mí →