La Implementación de GitOps Más Simple Que Realmente Funciona
Introducción
En este artículo vamos a reducir GitOps a sus elementos esenciales y construir la implementación más simple que realmente funciona. Sin operadores sofisticados, sin herramientas complejas - solo Git, GitHub Actions y un poco de magia de automatización.
Después de explorar diferentes enfoques de GitOps en mi artículo anterior, me di cuenta de que a veces pensamos demasiado las cosas. A veces, todo lo que necesitás es un pipeline simple y confiable que haga el trabajo. Construyamos exactamente eso.
El objetivo acá es simple:
- Un repositorio para tu código de aplicación
- Un repositorio para tus manifiestos de Kubernetes
- Un workflow que los conecte
- Cero infraestructura adicional más allá de lo que ya tenés
Solo GitOps puro y simple que podés entender, depurar y mantener sin un doctorado en tecnologías cloud-native.
Lo que vamos a construir
Vamos a implementar un flujo de trabajo GitOps basado en push que:
- Construye y prueba tu aplicación
- Crea una imagen de contenedor con versionado apropiado
- La pushea a GitHub Container Registry (¡gratis con GitHub!)
- Actualiza tus manifiestos de Kubernetes automáticamente
- Agrega escaneo de seguridad porque, bueno, no somos cowboys
Toda la configuración requiere solo dos repositorios y un workflow de GitHub Actions. Eso es todo. Sin servicios adicionales, sin facturas mensuales, sin configuraciones complejas.
El Repositorio de la Aplicación
Primero, hablemos del repositorio de la aplicación. Acá es donde vive tu código, y donde los desarrolladores pasan la mayor parte del tiempo. Lo único específico de GitOps acá es el workflow de CI/CD.
Esto es lo que pasa cuando pusheás código:
name: CI/CD Pipeline
on:
push:
branches: [ master ]
tags: [ 'v*' ]
Disparador simple - push a master o creá un tag, y la magia comienza. Sin webhooks para configurar, sin servicios externos para integrar. GitHub maneja todo.
Paso 1: Testing (Porque Somos Profesionales)
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.24'
- name: Run tests
run: go test -v ./...
Nada sofisticado acá. Checkout del código, configurar el entorno, ejecutar las pruebas. Si las pruebas fallan, nada más sucede. Esta es tu primera puerta de calidad, y no es negociable.
Paso 2: Construir y Pushear el Contenedor
Acá es donde las cosas se ponen interesantes. Estamos usando GitHub Container Registry (ghcr.io) porque es gratis, está integrado y simplemente funciona:
build-and-push:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
Estamos usando GITHUB_TOKEN
para el registry de github, no necesitás crear y gestionar credenciales del registro. GitHub proporciona este token automáticamente con los permisos justos. Un secreto menos para rotar, una cosa menos de qué preocuparse.
La estrategia de etiquetado de imágenes es donde ocurre la magia:
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=sha,prefix=,suffix=,format=short
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
Etiquetamos las imágenes con el SHA del commit. ¿Por qué? Porque los SHAs son inmutables, únicos y te dicen exactamente qué código está corriendo en producción. No más pesadillas con “latest”, no más conflictos de versiones.
Paso 3: Escaneo de Seguridad
Antes de desplegar cualquier cosa, asegurémonos de que no estamos enviando vulnerabilidades:
security-scan:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
Trivy escanea nuestra imagen en busca de vulnerabilidades conocidas y las reporta directamente a la pestaña de Seguridad de GitHub. Si se encuentran vulnerabilidades críticas, lo sabrás inmediatamente. Sin dashboards externos, sin logins adicionales - todo permanece en GitHub.
Paso 4: La Magia de GitOps - Actualizando Manifiestos
Acá es donde GitOps realmente sucede. Después de que nuestra imagen está construida y escaneada, actualizamos el repositorio de manifiestos:
update-manifests:
needs: [build-and-push, security-scan]
runs-on: ubuntu-latest
steps:
- name: Checkout manifest repository
uses: actions/checkout@v4
with:
repository: tu-org/tus-manifiestos
token: ${{ secrets.MANIFEST_REPO_TOKEN }}
path: manifests
- name: Update deployment image
working-directory: manifests
run: |
yq eval '.spec.template.spec.containers[0].image = "ghcr.io/${{ github.repository }}:${{ github.sha }}"' \
-i deployment.yaml
- name: Commit and push changes
working-directory: manifests
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add deployment.yaml
git commit -m "Update image to ${{ github.sha }}"
git push
Esto es hermoso en su simplicidad. Hacemos checkout del repo de manifiestos, actualizamos el tag de la imagen usando yq
, commiteamos el cambio y pusheamos. Eso es todo. Tus manifiestos ahora reflejan la versión exacta que se acaba de construir.
El Repositorio de Manifiestos
El repositorio de manifiestos es aún más simple. Contiene tus archivos YAML de Kubernetes y… eso es todo. Sin scripts, sin pipelines, solo configuración declarativa:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mi-app
spec:
template:
spec:
containers:
- name: app
image: ghcr.io/tu-org/tu-app:abc123f
# Este SHA se actualiza automáticamente por CI
Cada cambio en este repositorio está rastreado en Git. Podés ver quién desplegó qué, cuándo y por qué. ¿Necesitás hacer rollback? Solo revertí el commit. ¿Necesitás ver qué está corriendo en producción? Mirá la rama principal.
Configurándolo
¿Listo para implementar esto? Acá está tu checklist:
1. Crear un Token de Acceso Personal
# Andá a GitHub Settings > Developer settings > Personal access tokens
# Creá un token con scope 'repo' para el repositorio de manifiestos
# Guardalo como MANIFEST_REPO_TOKEN en los secrets del repo de tu app
2. Crear Tu Repositorio de Manifiestos
mkdir k8s-manifests
cd k8s-manifests
git init
# Agregá tus archivos YAML de Kubernetes
cp /ruta/a/tus/*.yaml .
git add .
git commit -m "Manifiestos iniciales"
git push
3. Agregar el Workflow
Copiá el workflow a .github/workflows/ci.yaml
en tu repositorio de aplicación. Actualizá los nombres de los repositorios y listo.
4. Desplegar en Tu Cluster Ahora, tenés dos opciones:
Opción A: Sincronización manual (más simple)
kubectl apply -f https://raw.githubusercontent.com/tu-org/tus-manifiestos/main/deployment.yaml
Opción B: Sincronización automatizada Configurá un CronJob simple en tu cluster que hace pull y aplica los cambios:
apiVersion: batch/v1
kind: CronJob
metadata:
name: gitops-sync
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: sync
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- |
kubectl apply -f https://raw.githubusercontent.com/tu-org/tus-manifiestos/main/
Eso es todo. Cada 5 minutos, tu cluster verifica cambios y los aplica. Sin operadores, sin controladores, solo un simple cron job.
Por Qué Esto Funciona
Este enfoque puede parecer demasiado simple, pero es exactamente por eso que funciona:
- Sin curva de aprendizaje: Si conocés Git y CI/CD básico, estás listo
- Depurable: Cuando algo se rompe, podés ver exactamente dónde y por qué
- Portable: Funciona con cualquier cluster de Kubernetes, en cualquier lugar
- Auditable: Cada cambio está en Git con historial completo
- Gratis: Usa solo las características gratuitas de GitHub
- Seguro: Superficie de ataque mínima, seguridad estándar de GitHub
Cuándo Usar Esto
Esta configuración es perfecta para:
- Equipos pequeños a medianos comenzando con GitOps
- Proyectos donde la simplicidad supera a las características
- Equipos que quieren entender todo su pipeline
- Situaciones donde no podés instalar herramientas adicionales en el cluster
Probablemente no sea ideal si necesitás:
- Despliegues multi-cluster
- Estrategias de despliegue complejas (canary, blue-green)
- Rollback automático basado en métricas
- Multi-tenancy con RBAC estricto
¿Pero sabés qué? Siempre podés agregar esas características más tarde. Empezá simple, entendé lo básico, después agregá complejidad solo cuando realmente la necesites.
Problemas Comunes y Soluciones
¿La imagen no se actualiza?
Verificá que tu política de pull de imagen no esté configurada en IfNotPresent
con un tag que no cambia. Usar SHAs resuelve esto automáticamente.
¿Token del repo de manifiestos expirado? Usá tokens de acceso personal de GitHub con fechas de vencimiento más largas, o mejor aún, usá una GitHub App para producción.
¿Necesitás hacer rollback rápidamente?
git revert HEAD
git push
# Esperá la sincronización, o aplicá manualmente
Conclusión
GitOps no tiene que ser complicado. Esta configuración simple te da el 90% de los beneficios con el 10% de la complejidad. Obtenés control de versiones, despliegues automatizados, escaneo de seguridad y auditoría completa con solo un workflow de GitHub Actions.
Empezá acá, sentite cómodo con los conceptos, y después explorá herramientas más avanzadas como ArgoCD o Flux cuando realmente necesites sus características. Recordá, la mejor implementación de GitOps es la que tu equipo puede entender y mantener.
A veces, la solución más simple es la mejor solución. Y en este caso, simple no significa amateur - significa enfocado, mantenible y listo para producción.
¡Espero que te haya sido útil y hayas disfrutado leyéndolo, hasta la próxima!
No tienes cuenta? Regístrate aqui
Ya registrado? Iniciar sesión a tu cuenta ahora.
-
Comentarios
Online: 0
Por favor inicie sesión para poder escribir comentarios.