ARTICULO

Introducción

Las inconsistencias entre entornos de desarrollo, staging y producción suelen ser el talón de Aquiles en equipos de DevOps. Cambios manuales, secretos hardcodeados y pipelines sin validación de seguridad generan deuda técnica que se paga con downtime y costos imprevistos. Este artículo detalla cómo construir un Internal Developer Platform (IDP) sobre Kubernetes usando herramientas del ecosistema CNCF, enfocado en seguridad de supply chain, GitOps y automatización declarativa.

El diseño propuesto aborda cuatro desafíos clave:

  1. Provisionamiento consistente: Infraestructura versionada y auditada con Terraform.
  2. Despliegue seguro: Pipelines con validación de imágenes, firmas digitales y políticas de admission.
  3. Observabilidad unificada: Métricas, logs y traces integrados en Grafana.
  4. Separación de responsabilidades: Layers de infraestructura, plataforma y aplicación claramente definidos.

Qué es y para qué sirve

Un Internal Developer Platform (IDP) es una capa de abstracción que estandariza cómo los equipos despliegan, monitorean y operan aplicaciones en Kubernetes. No es un producto comercial, sino una arquitectura operativa basada en principios CNCF:

  • Infraestructura como Código (IaC): Terraform para provisionar clusters, redes y servicios de cloud.
  • GitOps: ArgoCD sincroniza el estado deseado definido en Git con el cluster en tiempo real.
  • Seguridad de supply chain: Validación de imágenes (Cosign), políticas de admission (Kyverno) y mTLS con Istio.
  • Observabilidad unificada: Prometheus (métricas), Loki (logs) y Grafana (visualización).

Este enfoque elimina:

✅ Inconsistencias entre entornos (ej: permisos diferentes en staging vs producción).

✅ Secretos expuestos en pipelines o repositorios.

✅ Rollbacks lentos por falta de rollback mechanisms declarativos.

✅ Fragmentación de observabilidad (logs en Kibana, métricas en Datadog, etc.).

Prerequisitos

Antes de empezar, asegurate de tener:

Herramientas

ComponenteVersión mínimaInstalación recomendada
**Kubernetes**1.27+AKS (Azure), EKS (AWS) o cluster autogestionado
**Helm**3.12+[Instrucciones oficiales](https://helm.sh/docs/intro/install/)
**Terraform**1.6+[Descarga aquí](https://developer.hashicorp.com/terraform/downloads)
**ArgoCD**2.8+BLOCK25
**Cosign**2.0+[Instalación](https://docs.sigstore.dev/cosign/installation/)
**Kyverno**1.10+BLOCK26
**Istio**1.19+BLOCK27
**Prometheus**2.45+BLOCK28
**Loki**2.9+BLOCK29
**Grafana**10.0+BLOCK30
**OpenTelemetry**0.85+BLOCK31
### Accesos y permisos
  • Cuenta de cloud con permisos para crear clusters AKS/EKS/GKE y recursos asociados (VNet, Key Vault, etc.).
  • Acceso a repositorios Git (GitHub/GitLab) con permisos para crear branches y webhooks.
  • Dominio DNS configurado para el Ingress Controller (ej: *.dev.idp.miempresa.com).
  • Clave GPG para firmar imágenes (Cosign) y certificado TLS para Istio mTLS.

Repositorios de ejemplo

Este tutorial asume una estructura de repositorios modularizada. Creá estos 4 repositorios (o directorios dentro de uno monorepo) con el siguiente layout:

idp-infra/          # Terraform para provisionar clusters y recursos de cloud
│
├── modules/
│   ├── aks/         # Módulo para AKS
│   ├── networking/  # VNet, subnets, NSGs, etc.
│   ├── observability/ # Prometheus, Loki, Grafana
│   └── security/    # Kyverno, Istio, Cosign
│
├── environments/
│   ├── dev/         # Variables para entorno de desarrollo
│   ├── staging/     # Variables para staging
│   └── prod/        # Variables para producción
│
idp-platform/        # Helm charts y manifiestos de plataforma (ArgoCD, Istio, etc.)
idp-apps/           # Aplicaciones de ejemplo (microservicios Java/Angular)
idp-secrets/        # Repositorio para secretos (usando sealed-secrets o external-secrets)

Guía paso a paso

Paso 1: Bootstrap del cluster con Terraform

El primer paso es provisionar el cluster de Kubernetes usando Terraform. Este ejemplo usa AKS (los comandos para EKS/GKE son similares, ajustando el provider de cloud).

  1. Inicializá el módulo de AKS:
   cd idp-infra/modules/aks
   terraform init -upgrade
   
  1. Configurá las variables de entorno (ej: environments/dev/aks.auto.tfvars):
   cluster_name        = "idp-dev"
   location           = "eastus"
   kubernetes_version = "1.28"
   node_count         = 3
   vm_size            = "Standard_D4s_v3"
   resource_group_name = "idp-dev-rg"
   
  1. Aplicá el plan:
   terraform apply -var-file=../../environments/dev/aks.auto.tfvars
   
  1. Verificá el acceso al cluster:
   az aks get-credentials --resource-group idp-dev-rg --name idp-dev --admin
   kubectl cluster-info
   

Resultado esperado: Cluster AKS creado con 3 nodos, versión 1.28 de Kubernetes.

Paso 2: Configurar el controlador GitOps (ArgoCD)

ArgoCD será el cerebro del IDP, sincronizando el estado deseado desde Git con el cluster.

  1. Instalá ArgoCD:
   kubectl create namespace argocd
   kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
   
  1. Exponé el UI de ArgoCD (para desarrollo, usa NodePort o LoadBalancer):
   kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
   kubectl -n argocd get svc argocd-server
   

Obtené la IP del LoadBalancer y accedé a https://<IP>:443 (usuario: admin, contraseña: kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d).

  1. Configurá el repositorio de plataforma en ArgoCD:
   argocd repo add https://github.com/tudominio/idp-platform.git --username tu_usuario --password $GITHUB_TOKEN
   

Resultado esperado: ArgoCD sincronizando cambios desde idp-platform sin intervención manual.

Paso 3: Implementar seguridad de supply chain

3.1. Firmar imágenes con Cosign

  1. Generá una clave GPG (o usá una existente):
   cosign generate-key-pair
   

Esto crea cosign.key (privada) y cosign.pub (pública).

  1. Configurá el pipeline de CI (ej: GitHub Actions) para firmar imágenes:
   # .github/workflows/build-push-sign.yml
   - name: Sign image
     run: |
       cosign sign --key cosign.key ghcr.io/tudominio/app:${{ github.sha }}
       cosign verify --key cosign.pub ghcr.io/tudominio/app:${{ github.sha }}
   

3.2. Validar imágenes con Kyverno

  1. Aplicá una política para rechazar imágenes no firmadas:
   # idp-platform/policies/unsigned-image-policy.yaml
   apiVersion: kyverno.io/v1
   kind: ClusterPolicy
   metadata:
     name: require-cosign-signature
   spec:
     validationFailureAction: enforce
     background: false
     rules:
     - name: check-cosign-signature
       match:
         resources:
           kinds:
           - Pod
       verifyImages:
       - imageReferences:
         - "ghcr.io/tudominio/*"
         attestors:
         - count: 1
           entries:
           - keys:
               publicKeys: |-
                 -----BEGIN PUBLIC KEY-----
                 <contenido-de-cosign.pub>
                 -----END PUBLIC KEY-----
   
  1. Aplicá la política:
   kubectl apply -f idp-platform/policies/unsigned-image-policy.yaml
   

Resultado esperado: Cualquier pod que intente usar una imagen no firmada con Cosign será rechazado por Kyverno.

Paso 4: Configurar Istio para mTLS y observabilidad

  1. Instalá Istio:
   cd istio-1.19.0
   ./bin/istioctl install --set profile=demo -y
   
  1. Habilitá mTLS en modo «permissive» (para evitar errores de conectividad):
   # idp-platform/istio/mtls-permissive.yaml
   apiVersion: security.istio.io/v1beta1
   kind: PeerAuthentication
   metadata:
     name: default
     namespace: default
   spec:
     mtls:
       mode: PERMISSIVE
   
   kubectl apply -f idp-platform/istio/mtls-permissive.yaml
   
  1. Verificá la inyección de sidecars:
   kubectl get pods -n default
   

Todos los pods deben tener 2/2 contenedores (el pod + el sidecar de Istio).

Paso 5: Implementar observabilidad unificada

5.1. Instalar Prometheus, Grafana y Loki

  1. Instalá el stack de observabilidad:
   helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
   helm install prometheus prometheus-community/kube-prometheus-stack -n observability --create-namespace
   
  1. Configurá Loki para logs:
   helm repo add grafana https://grafana.github.io/helm-charts
   helm install loki grafana/loki -n observability
   
  1. Conectá Prometheus y Loki a Grafana:
– Accedé a http://<IP-del-LoadBalancer-de-Grafana>:3000.

– En Configuration > Data Sources, agregá:

Prometheus: http://prometheus-server.observability.svc:80

Loki: http://loki.observability.svc:3100

Paso 6: Desplegar una aplicación de ejemplo con GitOps

  1. Creá un Helm chart para tu aplicación (ej: idp-apps/myapp):
   helm create myapp
   
  1. Configurá el values.yaml para usar imágenes firmadas:
   image:
     repository: ghcr.io/tudominio/myapp
     tag: ${{ github.sha }}
     pullPolicy: IfNotPresent
   
  1. Creá un manifiesto de ArgoCD para sincronizar la app:
   # idp-platform/applications/myapp.yaml
   apiVersion: argoproj.io/v1alpha1
   kind: Application
   metadata:
     name: myapp
   spec:
     project: default
     source:
       repoURL: https://github.com/tudominio/idp-apps.git
       path: charts/myapp
       targetRevision: main
     destination:
       server: https://kubernetes.default.svc
       namespace: myapp
     syncPolicy:
       automated:
         prune: true
         selfHeal: true
   
  1. Aplicá el manifiesto:
   argocd app create -f idp-platform/applications/myapp.yaml
   

Resultado esperado: La aplicación se desplegará automáticamente en el cluster y ArgoCD mantendrá el estado sincronizado con Git.

Paso 7: Validar el pipeline de seguridad

  1. Simulá un cambio en el código:
   git clone https://github.com/tudominio/idp-apps.git
   cd idp-apps
   echo "test" >> README.md
   git add . && git commit -m "Test commit"
   git push origin main
   
  1. Verificá en ArgoCD:
– El cambio debería reflejarse en ~1 minuto.

– Si la imagen no está firmada, el pod fallará con el error:

     Error from server (Forbidden): admission webhook "validate.kyverno.svc-fail" denied the request: resource Pod/myapp-7d4f7c9d9-abcde was blocked due to the following policies
     require-cosign-signature: validation error: failed to verify the image signature. rule check-cosign-signature failed at index 0
     

Consideraciones y buenas prácticas

Seguridad

  • mTLS: Empezá en modo PERMISSIVE y migra a STRICT por namespace solo después de verificar que todos los pods tengan sidecars de Istio inyectados. Un error común es habilitar STRICT globalmente antes de tiempo, lo que rompe servicios legacy sin sidecar.
  • Secrets: Usá External Secrets con Azure Key Vault, AWS Secrets Manager o HashiCorp Vault para evitar hardcodear secretos en repositorios. Ejemplo:
  # idp-platform/secrets/external-secret.yaml
  apiVersion: external-secrets.io/v1beta1
  kind: ExternalSecret
  metadata:
    name: db-credentials
  spec:
    refreshInterval: 1h
    secretStoreRef:
      name: azure-keyvault
      kind: SecretStore
    target:
      name: db-secret
    data:
    - secretKey: password
      remoteRef:
        key: db-password
  
  • Políticas de Kyverno: Priorizá políticas para:
– Bloquear latest tag en imágenes (disallow-latest-tag).

– Requerir labels estándar en pods (ej: app.kubernetes.io/name).

– Restringir permisos de pods (ej: no usar hostPath o hostNetwork).

Costos

  • AKS/EKS/GKE: Los clusters con 3 nodos de tipo Standard_D4s_v3 (AKS) cuestan ~$150/mes por ambiente. Para reducir costos:
– Usá autoscaling horizontal (cluster-autoscaler) y autoscaling vertical (vertical-pod-autoscaler).

– Configurá spot instances para nodos no críticos.

  • Observabilidad: Loki es más económico que Elasticsearch para logs, pero requiere ajustar retención de datos (ej: 7 días en staging, 30 en producción).

Limitaciones y alternativas

ComponenteLimitaciónAlternativa recomendada
**Istio**Complejidad de configuración inicialLinkerd (más simple, pero menos features)
**Kyverno**Políticas requieren testing manualOPA (Open Policy Agent) con Rego
**Cosign**Requiere GPG o KMS para firmarNotary v2 (CNCF)
**ArgoCD**UI limitada para debugging avanzadoFlux CD (para equipos que prefieren Kustomize)
### Migración de herramientas
  • De Elasticsearch a Loki: Si ya tenés un stack con Elasticsearch, podés usar Promtail como agente para enviar logs a Loki sin migrar todo el pipeline.
  • De Helm a Kustomize: Para entornos con múltiples overlays (dev/staging/prod), Kustomize permite mayor reutilización de manifiestos.

Conclusión

Construir un Internal Developer Platform (IDP) sobre Kubernetes no es solo instalar herramientas, sino diseñar un flujo de trabajo seguro, automatizado y observable. Los pasos clave de esta guía:

  1. Provisionar el cluster con Terraform para garantizar consistencia.
  2. Automatizar despliegues con ArgoCD y GitOps.
  3. Validar imágenes con Cosign y Kyverno para evitar supply chain attacks.
  4. Observar todo con Prometheus, Loki y Grafana (no con 3 herramientas separadas).
  5. Separar responsabilidades entre infraestructura, plataforma y aplicaciones.

El mayor aprendizaje de implementaciones reales es empezar simple: no necesitas OpenTelemetry, Fluentd y Jaeger desde día 1. Priorizá estabilidad sobre features. Una vez que el IDP esté maduro, podés integrar herramientas como OpenTelemetry o Policy Reporter para auditorías avanzadas.

Fuentes

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *