Pipeline DevOps del Futuro: GitOps, Terraform y Azure DevOps en 2026
La Evolución del Pipeline DevOps: Hacia un Futuro GitOps
La automatización y el control de versiones del código se han convertido en el estándar para la infraestructura moderna. Este artículo presenta una implementación completa de GitOps con Terraform y Azure DevOps.
Arquitectura del Pipeline
1. Estructura del Repositorio
repository/
├── .azure/
│ └── pipelines/
│ ├── ci.yml
│ └── cd.yml
├── terraform/
│ ├── environments/
│ │ ├── dev/
│ │ ├── staging/
│ │ └── prod/
│ ├── modules/
│ │ ├── compute/
│ │ ├── network/
│ │ └── database/
│ └── main.tf
├── kubernetes/
│ ├── base/
│ └── overlays/
└── src/
└── microservices/
Implementación del Pipeline CI/CD
1. Azure Pipeline Principal
# .azure/pipelines/ci.yml
trigger:
branches:
include:
- main
- feature/*
paths:
include:
- src/*
- terraform/*
- kubernetes/*
variables:
- group: terraform-secrets
- name: ENVIRONMENT
value: 'dev'
stages:
- stage: ValidateInfrastructure
jobs:
- job: TerraformValidate
pool:
vmImage: 'ubuntu-latest'
steps:
- task: TerraformInstaller@0
inputs:
terraformVersion: '1.5.7'
- task: TerraformTaskV4@4
inputs:
provider: 'azurerm'
command: 'init'
workingDirectory: '$(System.DefaultWorkingDirectory)/terraform'
backendServiceArm: 'terraform-backend'
backendAzureRmResourceGroupName: 'terraform-storage-rg'
backendAzureRmStorageAccountName: 'tfstate'
backendAzureRmContainerName: 'tfstate'
backendAzureRmKey: '$(ENVIRONMENT).tfstate'
- task: TerraformTaskV4@4
inputs:
provider: 'azurerm'
command: 'plan'
workingDirectory: '$(System.DefaultWorkingDirectory)/terraform'
environmentServiceNameAzureRM: 'terraform-backend'
- stage: BuildAndTest
jobs:
- job: BuildCode
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: 'src/**/*.csproj'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
projects: 'tests/**/*.csproj'
- stage: SecurityScan
jobs:
- job: CodeScan
steps:
- task: SonarCloudPrepare@1
inputs:
SonarCloud: 'sonarcloud'
organization: 'your-org'
scannerMode: 'CLI'
configMode: 'manual'
cliProjectKey: 'your-project'
cliProjectName: 'Your Project'
- task: SonarCloudAnalyze@1
2. Despliegue con GitOps
# .azure/pipelines/cd.yml
trigger: none
pr: none
resources:
pipelines:
- pipeline: CI
source: CI-Pipeline
trigger:
branches:
include:
- main
variables:
- group: gitops-secrets
stages:
- stage: DeployInfrastructure
jobs:
- deployment: TerraformApply
environment: $(ENVIRONMENT)
strategy:
runOnce:
deploy:
steps:
- task: TerraformTaskV4@4
inputs:
provider: 'azurerm'
command: 'apply'
workingDirectory: '$(Pipeline.Workspace)/terraform'
environmentServiceNameAzureRM: 'terraform-backend'
- stage: DeployApplications
jobs:
- deployment: FluxCD
environment: $(ENVIRONMENT)
strategy:
runOnce:
deploy:
steps:
- task: Kubernetes@1
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceEndpoint: 'aks-connection'
command: 'apply'
arguments: '-f $(Pipeline.Workspace)/kubernetes/flux/'
Configuración de GitOps con Flux
1. Flux Bootstrap
# kubernetes/flux/gotk-components.yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: flux-system
namespace: flux-system
spec:
interval: 1m0s
ref:
branch: main
secretRef:
name: flux-system
url: ssh://git@github.com/your-org/your-repo.git
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: flux-system
namespace: flux-system
spec:
interval: 10m0s
path: ./kubernetes/base
prune: true
sourceRef:
kind: GitRepository
name: flux-system
2. Aplicación Base
# kubernetes/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
commonLabels:
app: microservice
environment: base
Seguridad y Cumplimiento
1. Policy as Code
# terraform/policies/main.tf
resource "azurerm_policy_definition" "require_tags" {
name = "require-tags"
policy_type = "Custom"
mode = "Indexed"
display_name = "Require tags on resources"
policy_rule = <<POLICY_RULE
{
"if": {
"field": "tags",
"exists": "false"
},
"then": {
"effect": "deny"
}
}
POLICY_RULE
}
2. Seguridad en Pipeline
# .azure/pipelines/security.yml
trigger: none
schedules:
- cron: "0 0 * * *"
displayName: Daily Security Scan
branches:
include:
- main
always: true
pool:
vmImage: 'ubuntu-latest'
steps:
- task: ContainerStructureTest@0
inputs:
dockerFile: '**/Dockerfile'
testFile: '**/test.yaml'
- task: Checkmarx@1
inputs:
projectName: '$(Build.Repository.Name)'
checkmarxUsername: '$(checkmarx.username)'
checkmarxPassword: '$(checkmarx.password)'
checkmarxServerUrl: '$(checkmarx.url)'
Monitorización y Observabilidad
1. Prometheus y Grafana
# kubernetes/monitoring/prometheus.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: prometheus
spec:
serviceAccountName: prometheus
serviceMonitorSelector:
matchLabels:
team: frontend
resources:
requests:
memory: 400Mi
2. Logging con Azure Monitor
resource "azurerm_log_analytics_workspace" "main" {
name = "workspace-${var.environment}"
location = var.location
resource_group_name = azurerm_resource_group.main.name
sku = "PerGB2018"
retention_in_days = 30
}
Automatización de Pruebas
1. Pruebas de Infraestructura
# tests/main.tf
module "test" {
source = "../modules/network"
providers = {
azurerm = azurerm.test
}
# Test inputs
vnet_name = "test-vnet"
address_space = ["10.0.0.0/16"]
}
# Test assertions
resource "test_assertions" "network" {
component = "network"
equal "vnet_name" {
description = "VNet name should match input"
got = module.test.vnet_name
want = "test-vnet"
}
}
2. Pruebas de Integración
# tests/integration/test.yaml
apiVersion: v1
kind: Pod
metadata:
name: integration-test
spec:
containers:
- name: test
image: test-runner:latest
env:
- name: API_ENDPOINT
value: http://api-service
command: ["pytest", "-v", "tests/"]
Mejores Prácticas
- Control de Versiones
- Ramificación por característica
- Pull requests obligatorios
- Revisiones de código automatizadas
- Seguridad
- Escaneo de secretos
- Análisis de dependencias
- RBAC granular
- Monitorización
- Métricas de pipeline
- Logs centralizados
- Alertas proactivas
- Automatización
- Pruebas automatizadas
- Despliegues automáticos
- Rollbacks automáticos
Conclusiones
Un pipeline DevOps moderno requiere:
- Automatización completa
- Seguridad integrada
- Observabilidad robusta
- GitOps como base
Próximos Pasos
- Implementar control de versiones
- Configurar CI/CD básico
- Integrar seguridad
- Implementar GitOps
- Añadir monitorización