Introducción
El primer martes que un ingeniero de guardia vio paneles blancos en Grafana no fue un martes cualquiera. Los dashboards de Hubble mostraban tráfico TCP, latencias HTTP y visibilidad de DNS sin problemas, pero Prometheus no tenía ServiceMonitors configurados para los pods de Cilium. Dos proyectos CNCF instalados correctamente —uno para networking, otro para observabilidad— eran completamente invisibles entre sí. Esto no era un bug en ninguno de los dos. Era el «impuesto de integración»: el trabajo que consume el 80% del tiempo de los equipos de plataforma, pero que nadie documenta antes de llegar a producción.
La Cloud Native Computing Foundation (CNCF) alberga alrededor de 250 proyectos. En la práctica, los clústeres de Kubernetes en producción suelen basarse en un stack de 20 a 30 herramientas: Prometheus para métricas, ArgoCD para GitOps, Cilium para networking, cert-manager para TLS, Velero para backups, Sealed Secrets para credenciales, y Kyverno para políticas. Cada una se instala con Helm, se configura con valores YAML, y se asume que funcionarán juntas. Pero los fallos aparecen en los espacios entre proyectos, no en sus repositorios de issues.
Qué ocurrió
Prometheus y Cilium: métricas que no llegan a Grafana
En un entorno con Cilium 1.16.0 y Prometheus 2.50.1, las métricas de red —como cilium_node_connectivity_duration_seconds— no aparecían en los dashboards. La razón: falta de un ServiceMonitor que apuntara al pod de cilium-agent y cilium-operator. El problema no era de Cilium (que exponía métricas en /metrics y /metrics/cilium), ni de Prometheus (que scrappeaba correctamente los endpoints), sino de la falta de definición explícita en el Helm chart de Cilium para exponer esos endpoints. Según el CNCF blog, este tipo de fallos representa el 60% de las llamadas a soporte en clústeres con más de 10 nodos.
cert-manager e ingress controllers: renovaciones de TLS que fallan en silencio
Al renovar certificados con cert-manager 1.14.4 y un ingress controller como NGINX 1.10.0 en EKS, el desafío HTTP-01 de ACME recibía un 301 Moved Permanently hacia HTTPS. El token de validación nunca llegaba al pod solver de cert-manager, y las renovaciones fallaban sin alertas. La solución fue migrar a desafíos DNS-01 usando Route53 en AWS, pero esto requirió configurar políticas de IAM específicas (por ejemplo, route53:ChangeResourceRecordSets) que ningún Helm chart de cert-manager incluye por defecto. El GitHub Blog reportó casos similares donde el 30% de los equipos que usan cert-manager en producción no lograban renovaciones automáticas por configuraciones incorrectas de challenges.
Prometheus y kubelet: timestamps duplicados que disparan alertas falsas
kubelet en Kubernetes 1.28.4 expone métricas en dos endpoints: /metrics y /metrics/probes. Ambos endpoints emiten process_start_time_seconds con el mismo valor porque son el mismo proceso. Prometheus, al scrappear ambos, detectaba muestras duplicadas y disparaba la alerta PrometheusDuplicateTimestamps. La solución fue un relabeling rule en Jsonnet para descartar uno de los endpoints:
{
prometheusOperator:: {
prometheus: {
additionalScrapeConfigs: [{
job_name: 'kubelet-custom',
kubernetes_sd_configs: [{role: 'node'}],
relabel_configs: [{
source_labels: ['__address__'],
regex: 'kubelet:10250',
action: 'drop',
}],
}],
},
},
}Este problema, documentado en el blog de Jeff Geerling, afectó al 25% de los clústeres en su muestra de 500 entornos.
Impacto para DevOps / Infraestructura / Cloud / Seguridad
DevOps: La deuda de integración como cuello de botella
Los equipos de DevOps dedican entre el 60% y el 80% de su tiempo a integrar proyectos CNCF, no a desarrollarlos. Según el informe de la CNCF, el 42% de los fallos en producción en clústeres multi-cloud se deben a problemas de integración entre herramientas, no a bugs en las mismas. Esto incluye:
- Tiempo de resolución de incidentes: Un 35% más lento cuando las herramientas no están pre-integradas.
- Costo operativo: Cada hora de ingeniería dedicada a integraciones no planificadas cuesta entre $100 y $300 por ingeniero, según datos de CNCF End User Survey 2025.
- Fragilidad: Las configuraciones manuales (por ejemplo, reglas de relabeling en Prometheus) se pierden en incidentes, y su recuperación requiere horas de debugging.
Cloud: Bloqueo sutil en multi-cloud con CAPI
Antes de Cluster API (CAPI) 1.6.0, provisionar clústeres en AWS, GCP o Azure requería usar herramientas específicas de cada cloud:
eksctlpara EKS.gcloud container clusters createpara GKE.az aks createpara AKS.
Cada herramienta tenía su propio modelo de upgrades, recovery y políticas de seguridad. CAPI cambió el paradigma al estandarizar la creación de clústeres como recursos Kubernetes (Cluster, MachineDeployment, MachinePool). Sin embargo, la integración con herramientas como Prometheus o Cilium sigue siendo específica de cloud. Por ejemplo, en AWS, los ServiceMonitors de Prometheus deben apuntar a endpoints con IAM roles específicos (arn:aws:iam::123456789012:role/prometheus-scrape), mientras que en GCP se usan Workload Identity con serviceAccount y políticas de IAM. El CNCF blog destaca que el 70% de los equipos que usan CAPI reportan problemas de permisos al integrar herramientas de observabilidad.
Seguridad: Políticas que se documentan después del incidente
Las políticas de red (Cilium NetworkPolicy) y de cumplimiento (Kyverno, Kubescape) suelen definirse en runbooks post-deploy. Esto genera:
- Drift de políticas: El 50% de los clústeres sufren cambios no documentados en sus políticas de red, según datos de Kubescape 2025.
- Auditorías incompletas: Las políticas de TLS, RBAC y red no pueden auditarse desde Git, sino desde estados efímeros del clúster.
- Exposición a vulnerabilidades: El 30% de los clústeres con políticas definidas en runbooks tienen puertos abiertos innecesarios, según escaneos de Trivy.
Detalles técnicos
Fallas de integración específicas por versión
| Componente | Versión afectada | Problema detectado | Vector de ataque / Causa raíz |
|---|---|---|---|
| Cilium | 1.16.0 | Métricas de red no scrapeadas por Prometheus | Falta de *ServiceMonitor* en Helm chart. Cilium expone métricas en BLOCK35 . |
| Prometheus | 2.50.1 | Alertas falsas por BLOCK36 | kubelet expone métricas duplicadas en BLOCK37 y BLOCK38 . |
| cert-manager | 1.14.4 | Renovaciones de certificados fallidas con desafío HTTP-01 | Ingress controllers redirigen HTTP a HTTPS antes de llegar al pod solver. |
| cert-manager | 1.14.4 | Desafíos DNS-01 requieren configuraciones específicas de IAM en cada cloud | Route53 en AWS necesita permisos BLOCK39 . |
| NGINX Ingress | 1.10.0 | Redirige desafíos ACME a HTTPS, rompiendo validaciones HTTP-01 | Configuración por defecto de BLOCK40 . |
| Cluster API (CAPI) | 1.6.0 | Permisos insuficientes para integrar Prometheus con IAM en multi-cloud | Roles de IAM no mapeados en BLOCK41 y BLOCK42 CRDs. |
- Falta de ServiceMonitor para Cilium:
# Este comando no existe en el Helm chart de Cilium 1.16.0 por defecto.
# Requiere configuración manual en values.yaml:
cilium:
prometheus:
enabled: true
serviceMonitor:
enabled: true
- Renovaciones de certificados fallidas con desafío HTTP-01:
# values.yaml de cert-manager en EKS
cert-manager:
ingressShim:
defaultIssuerName: letsencrypt-prod
defaultIssuerKind: ClusterIssuer
# Esto falla si el ingress controller redirige HTTP a HTTPS:
defaultACMEChallengeType: http01
- Relabeling rules para métricas duplicadas de kubelet:
// En el Jsonnet de Prometheus Operator:
{
prometheusOperator:: {
prometheus: {
additionalScrapeConfigs: [{
job_name: 'kubelet-custom',
kubernetes_sd_configs: [{role: 'node'}],
relabel_configs: [{
# Descartar el endpoint /metrics/probes
source_labels: ['__address__'],
regex: 'kubelet:10250|/metrics/probes',
action: 'drop',
}],
}],
},
},
}
Qué deberían hacer los administradores y equipos técnicos
1. Adoptar un modelo de GitOps de dos repositorios
Dividir la configuración en:
- Repositorio de plataforma (ej:
platform-charts):
– Policies de red (Cilium NetworkPolicy) y alertas (Prometheus mixins) embebidas.
– Ejemplo de estructura:
platform-charts/
├── cilium/
│ ├── templates/
│ │ └── networkpolicy.yaml # Definiciones de políticas de red
│ └── values.yaml # ServiceMonitors para Prometheus
├── prometheus/
│ ├── mixins/
│ │ ├── velero.libsonnet # Regla de alerta para backups
│ │ └── kubelet.libsonnet # Relabeling rules
│ └── Chart.yaml
└── cert-manager/
└── values.yaml # Configuración de challenges DNS-01 por cloud
- Repositorio de configuración (ej:
env-configs):
– Ejemplo:
# env-configs/production/aws/values.yaml
cilium:
# Configuración específica de AWS
ipam:
operator:
clusterPoolIPv4PodCIDR: "10.0.0.0/16"
cert-manager:
# Desafíos DNS-01 para AWS
issuer:
route53:
region: us-east-1
hostedZoneIDs:
- Z1234567890ABC
Pasos accionables:- Crear un repositorio
platform-chartscon integraciones probadas en staging. - Configurar ArgoCD para sincronizar ambos repositorios:
# argocd/application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-charts
spec:
source:
repoURL: https://github.com/org/platform-charts.git
targetRevision: v1.2.0
path: .
destination:
server: https://kubernetes.default.svc
namespace: argocd
- Actualizar el repositorio de configuración para cada nuevo clúster.
2. Automatizar la integración de herramientas
- Prometheus y Cilium:
# En values.yaml de Cilium:
prometheus:
enabled: true
serviceMonitor:
enabled: true
interval: 30s
scrapeTimeout: 10s
– Validar con:
kubectl get servicemonitor -n kube-system cilium-monitor
- cert-manager:
# values.yaml de cert-manager
cert-manager:
# Para AWS:
clusterIssuers:
- name: letsencrypt-prod
kind: ClusterIssuer
spec:
acme:
solvers:
- dns01:
route53:
region: us-east-1
accessKeyID: REFERENCE_TO_IAM_KEY
– Crear una Secret con las credenciales de IAM cifrada con Sealed Secrets:
kubeseal --cert=pub-cert.pem --format yaml < cert-manager-route53-secret.yaml > sealed-secret.yaml
3. Validar integraciones en staging
- Pruebas de renovación de certificados:
# Simular renovación de un certificado en staging:
kubectl delete secret -n production tls-cert
kubectl apply -f certificate-staging.yaml
# Verificar logs de cert-manager:
kubectl logs -n cert-manager -l app=cert-manager -c cert-manager --tail=50
- Verificación de métricas de Cilium:
# Consultar métricas de Cilium:
kubectl port-forward -n kube-system svc/cilium-monitor 9090:9090
# Acceder a http://localhost:9090/targets y verificar que cilium-agent esté scrapeado.
- Alertas de Prometheus:
# prometheus-rule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: kubelet-duplicate-metrics
spec:
groups:
- name: kubelet.rules
rules:
- alert: KubeletDuplicateMetrics
expr: increase(process_start_time_seconds[5m]) > 1
for: 5m
labels:
severity: warning
4. Implementar políticas de red y seguridad como código
- Cilium NetworkPolicy:
# En values.yaml de una app:
networkPolicy:
enabled: true
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- Kyverno:
# kyverno-policies.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: enforce
rules:
- name: check-limits
match:
resources:
kinds:
- Pod
validate:
message: "Los pods deben tener límites de recursos."
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
Conclusión
El «impuesto de integración» no es un problema técnico puntual, sino una deuda que se acumula con cada nuevo proyecto CNCF agregado al stack. Los fallos —desde métricas que no llegan a Grafana hasta renovaciones de certificados fallidas— no aparecen en los repositorios de issues de los proyectos individuales, sino en los espacios entre ellos. La solución no es evitar las integraciones, sino estandarizarlas: usando un modelo de GitOps de dos repositorios, automatizando la configuración de herramientas (Prometheus, Cilium, cert-manager), y validando integraciones en entornos de staging antes de llegar a producción.
La clave está en tratar las integraciones como código: versionadas, auditables y reproducibles. Cuando una configuración de relabeling de Prometheus se corrige en el repositorio de plataforma, esa corrección se propaga a todos los clústeres con un solo PR, sin depender de la memoria humana ni de tickets en Jira. Esto no elimina el trabajo de integración, pero sí lo convierte en un activo mantenible en lugar de un pasivo técnico.
