GKE (Google Kubernetes Engine)
Visión General
Sección titulada «Visión General»Google Kubernetes Engine (GKE) es el corazón de HERA. Como nuestra plataforma de orquestación de contenedores gestionada, nos permite desplegar, escalar y gestionar aplicaciones en contenedores con alta disponibilidad y seguridad.
¿Por qué GKE? (vs alternativas en GCP)
Sección titulada «¿Por qué GKE? (vs alternativas en GCP)»GCP ofrece varias opciones para ejecutar workloads. La decisión de usar GKE como plataforma principal de HERA es deliberada. Esta sección explica el porqué y cuándo aplican las alternativas.
Matriz de decisión: GKE vs alternativas
Sección titulada «Matriz de decisión: GKE vs alternativas»| Plataforma | Cuándo usarla | Cuándo NO | Estado en HERA |
|---|---|---|---|
| GKE (estándar HERA) | Microservicios complejos, control fino de runtime, escalado avanzado, mTLS, network policies, multi-tenant | Workloads triviales que no necesitan Kubernetes | Estándar para todos los servicios HERA |
| Cloud Run | APIs REST stateless, scale-to-zero, picos irregulares, ejecuciones cortas | Workloads que requieren persistencia local, sidecars complejos, stateful | Caso de uso aprobado para servicios data con bursting (sandbox) |
| Cloud Functions | Triggers de eventos puntuales (Pub/Sub, Storage), glue code, transformaciones simples | Aplicaciones con state, procesos largos, dependencias pesadas | Caso de uso para transformaciones de eventos en event services |
| App Engine Standard | Aplicaciones web monolíticas, prototipos rápidos | Microservicios distribuidos, observabilidad avanzada, multi-cluster | No usar — legacy approach para HERA |
| Compute Engine (VMs) | Workloads que NO se pueden contenerizar (legacy enterprise software, GPU específico) | Cualquier cosa que pueda correr en contenedor | Excepción documentada — requiere aprobación de Arquitectura |
Por qué GKE es el estándar HERA
Sección titulada «Por qué GKE es el estándar HERA»| Razón | Detalle |
|---|---|
| Portabilidad | Kubernetes es estándar de la industria. Si mañana migramos de GCP, los workloads se mueven con menor fricción |
| Ecosystem maduro | Helm, Operators, Service Mesh, GitOps, observabilidad — todo el ecosystem CNCF disponible |
| Control de runtime | requests/limits, probes, security contexts, network policies, RBAC granular |
| Multi-tenant seguro | Namespaces + Network Policies + Workload Identity permiten múltiples productos en un cluster |
| Escalado avanzado | HPA + VPA + Cluster Autoscaler combinados — no disponible al mismo nivel en otras opciones |
| Estándar de la industria | El equipo de plataforma puede contratar talent que ya conoce Kubernetes |
Cuándo NO usar GKE (excepciones documentadas)
Sección titulada «Cuándo NO usar GKE (excepciones documentadas)»GKE no es siempre la mejor opción. Estas son las excepciones aprobadas:
-
Workloads serverless puros con scale-to-zero crítico → Cloud Run
- Ejemplo: API pública que recibe 100 requests al día con picos eventuales
- Razón: GKE tiene baseline cost (mínimo 1 nodo); Cloud Run baja a cero
-
Procesamiento de eventos puntuales y ligeros → Cloud Functions
- Ejemplo: redimensionar imágenes al subir a Cloud Storage
- Razón: setup más simple, billing por invocación
-
Workloads con dependencias no contenerizables → Compute Engine
- Ejemplo: software enterprise que requiere kernel modules específicos
- Razón: GKE no permite drivers custom de kernel
- Requiere aprobación formal del equipo de Arquitectura
Arquitectura de Clusters
Sección titulada «Arquitectura de Clusters»En HERA, la configuración de nuestros clusters varía según el ambiente para balancear costo, rendimiento y resiliencia.
Topología General
Sección titulada «Topología General»default-pool (n2-standard-4) — Apps críticasspot-pool (e2-standard-4) — Workloads BatchEspecificaciones por Ambiente
Sección titulada «Especificaciones por Ambiente»| Ambiente | Tipo | Nodos / Capacidad | Machine types | Uso principal |
|---|---|---|---|---|
| Development | Regional Standard | 3-6 nodos | e2-standard-4 (spot) | Desarrollo y pruebas unitarias. |
| QA | Regional Standard | 3-6 nodos | e2-standard-4 (spot) | Pruebas de integración y rendimiento. |
| Production | Regional Standard | 3-12 nodos | n2-standard-4 (default), e2-standard-4 (spot) | Aplicaciones críticas y de cara al cliente. |
Node Pools: Aislamiento y Dimensionamiento
Sección titulada «Node Pools: Aislamiento y Dimensionamiento»En GKE Standard (PRD), no todos los workloads son iguales. Los node pools permiten segmentar la infraestructura para que cada tipo de carga tenga los recursos apropiados y el aislamiento necesario.
Pools definidos en HERA
Sección titulada «Pools definidos en HERA»| Pool | Machine type | Min / Max nodos | Propósito | Taints |
|---|---|---|---|---|
| default | n2-standard-4 | 3 / 10 | Workloads generales (backends, BFFs) | Ninguno |
| spot-workers | e2-standard-4 | 0 / 8 | Batch jobs, workers, procesamiento async | cloud.google.com/gke-spot=true:NoSchedule |
| tier1-critical | n2-standard-8 | 2 / 6 | Servicios Tier 1 (checkout, pagos, auth) | hera.cloudherdez.com/tier=critical:NoSchedule |
| data-intensive | n2-highmem-4 | 1 / 4 | Servicios de datos (analytics, ETL, ML inference) | hera.cloudherdez.com/workload=data:NoSchedule |
Aislamiento con Taints y Tolerations
Sección titulada «Aislamiento con Taints y Tolerations»Los taints en nodos aseguran que solo los pods con la toleration correspondiente puedan ejecutarse ahí. Esto previene que workloads no críticos consuman recursos reservados para Tier 1.
# deployment-checkout-service.yaml — solo corre en pool tier1-criticalapiVersion: apps/v1kind: Deploymentmetadata: name: backend-checkout-servicespec: template: spec: tolerations: - key: "hera.cloudherdez.com/tier" operator: "Equal" value: "critical" effect: "NoSchedule" nodeSelector: cloud.google.com/gke-nodepool: tier1-critical# deployment-worker-etl.yaml — corre en pool spot (batch tolerante a interrupción)apiVersion: apps/v1kind: Deploymentmetadata: name: worker-etl-inventariosspec: template: spec: tolerations: - key: "cloud.google.com/gke-spot" operator: "Equal" value: "true" effect: "NoSchedule" nodeSelector: cloud.google.com/gke-nodepool: spot-workers # Spot VMs pueden ser interrumpidas — el pod debe manejar SIGTERM gracefully terminationGracePeriodSeconds: 60Dimensionamiento de Node Pools
Sección titulada «Dimensionamiento de Node Pools»HERA define node pools separados por tier de criticidad. Cada tier usa un perfil de recursos y aislamiento específico.
Ejemplo: pool Tier 1 (crítico)
Sección titulada «Ejemplo: pool Tier 1 (crítico)»| Parámetro | Valor estándar PRD | Justificación |
|---|---|---|
| Machine type | n2-standard-8 | 8 vCPU / 32 GB RAM — capacidad para workloads críticos sin sobredimensionar |
| Disco | 100 GB SSD (pd-ssd) | IOPS predecibles, necesarias para logs y caché local del pod |
| Autoscaling | min 2 / max 6 nodos | Capacidad base para HA multi-zona + crecimiento durante picos |
| Región | us-central1 (regional) | 3 zonas activas para tolerancia a fallas de zona |
| Taint | hera.cloudherdez.com/tier=critical:NO_SCHEDULE | Sólo pods con toleration explícito pueden aterrizar aquí |
| Labels | tier=critical, environment=prd | Selección explícita desde deployments (nodeSelector) |
Hardening obligatorio del node config
Sección titulada «Hardening obligatorio del node config»- Shielded VM:
enable_secure_bootyenable_integrity_monitoringactivados — garantiza boot auditable y detección de rootkits. - Workload Identity:
mode=GKE_METADATA— única forma autorizada de acceder a GCP (no se permiten Service Account keys montadas en disco). - Auto-repair: activo — GKE reemplaza automáticamente nodos unhealthy.
- Auto-upgrade: activo — parches del SO aplicados durante la ventana de mantenimiento configurada.
Tiers disponibles
Sección titulada «Tiers disponibles»| Tier | Uso | Machine type típico | Min/Max nodos |
|---|---|---|---|
| Tier 1 — Critical | Checkout, payments, APIs core | n2-standard-8 | 2 / 6 |
| Tier 2 — Important | Catalog, search, BFF | n2-standard-4 | 2 / 4 |
| Tier 3 — Standard | Admin panels, batch, reporting | n2-standard-2 | 1 / 3 |
Alta Disponibilidad
Sección titulada «Alta Disponibilidad»Alta disponibilidad en GKE no es solo “cluster regional”. Es una combinación de estrategias a nivel cluster, nodo y pod que garantizan que los servicios sobrevivan a fallas de zona, nodo o pod individual.
Estrategia HA por ambiente
Sección titulada «Estrategia HA por ambiente»| Nivel | DEV/QA (Autopilot) | PRD (Standard Regional) |
|---|---|---|
| Cluster | Zonal (1 zona) | Regional (3 zonas: us-central1-a/b/c) |
| Réplicas mínimas | 1 | 3 (Tier 1), 2 (Tier 2), 1 (Tier 3) |
| Pod anti-affinity | No requerido | Obligatorio para Tier 1 y Tier 2 |
| PDB | No requerido | Obligatorio para Tier 1 |
| Topology spread | No requerido | Obligatorio para Tier 1 |
Distribución multi-zona con Topology Spread Constraints
Sección titulada «Distribución multi-zona con Topology Spread Constraints»Para servicios Tier 1, las réplicas deben distribuirse entre zonas. Si una zona cae, las otras siguen sirviendo.
apiVersion: apps/v1kind: Deploymentmetadata: name: backend-checkout-servicespec: replicas: 3 # Mínimo 3 para distribución en 3 zonas template: spec: # Distribuir pods uniformemente entre zonas topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule # NO aceptar desbalance labelSelector: matchLabels: app: backend-checkout-service # Evitar que 2 réplicas corran en el mismo nodo affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app: backend-checkout-service topologyKey: kubernetes.io/hostnamePod Disruption Budgets (PDB)
Sección titulada «Pod Disruption Budgets (PDB)»Un PDB garantiza que durante mantenimientos voluntarios (upgrades de nodos, drain, autoscaler scale-down), siempre haya un mínimo de réplicas disponibles.
apiVersion: policy/v1kind: PodDisruptionBudgetmetadata: name: backend-checkout-service-pdb namespace: tienda-herdezspec: minAvailable: 2 # Siempre al menos 2 pods vivos selector: matchLabels: app: backend-checkout-service| Servicio tier | Réplicas | PDB minAvailable | Resultado |
|---|---|---|---|
| Tier 1 (checkout, auth) | 3 | 2 | Solo 1 pod puede estar down a la vez |
| Tier 2 (catálogos, CMS) | 2 | 1 | Solo 1 pod puede estar down a la vez |
| Tier 3 (reportes, batch) | 1 | N/A | No necesita PDB |
HA para Workloads Stateful
Sección titulada «HA para Workloads Stateful»Los servicios stateless se resuelven con réplicas. Los stateful (bases de datos, caches) requieren estrategia adicional:
| Componente | Estrategia HA | Detalle |
|---|---|---|
| Cloud SQL | Regional con failover automático | Réplica standby en zona distinta — failover en menos de 60s |
| Redis (Memorystore) | HA con réplica read | Failover automático, datos persistidos |
| Pub/Sub | Regional por defecto | Google gestiona la replicación entre zonas |
| GCS (Storage) | Multi-regional | Replicación automática en 2+ regiones |
Unschedulable Pods: Diagnóstico y Resolución
Sección titulada «Unschedulable Pods: Diagnóstico y Resolución»Cuando un pod queda en estado Pending con el evento FailedScheduling, significa que el scheduler no encontró un nodo que cumpla todos los requisitos. Esta es una de las situaciones más comunes en operación de clusters.
Diagnóstico rápido
Sección titulada «Diagnóstico rápido»# 1. Ver pods en Pendingkubectl get pods --all-namespaces --field-selector=status.phase=Pending
# 2. Ver los eventos del pod específicokubectl describe pod <pod-name> -n <namespace> | grep -A 10 Events
# 3. Ver estado de nodoskubectl get nodes -o widekubectl describe node <node-name> | grep -A 5 "Allocated resources"
# 4. Ver si Cluster Autoscaler tiene problemaskubectl get events -n kube-system --field-selector source=cluster-autoscaler --sort-by='.lastTimestamp'Matriz de causas y soluciones
Sección titulada «Matriz de causas y soluciones»| Causa | Mensaje típico en Events | Solución |
|---|---|---|
| Recursos insuficientes | Insufficient cpu / Insufficient memory | Reducir requests del pod o aumentar maxNodeCount del pool |
| Taint sin toleration | node(s) had taint {key=value:NoSchedule} | Agregar tolerations al Deployment o verificar que el pod apunta al pool correcto |
| Node selector sin match | node(s) didn't match Pod's node affinity/selector | Verificar que el nodeSelector coincide con labels de los nodos |
| Anti-affinity | node(s) didn't match pod anti-affinity rules | Verificar que hay suficientes nodos para distribuir todas las réplicas |
| PDB bloqueando drain | Pod pending durante upgrade de nodos | Verificar PDB minAvailable vs número de réplicas — debe haber margen |
| PVC sin provisionar | persistentvolumeclaim not found | Verificar que el StorageClass existe y tiene capacidad |
| Cluster Autoscaler lento | Cluster Autoscaler status: ScaleUp | Esperar 2-5 min para provisión de nodo. Si persiste: verificar cuota de GCE |
| Cuota de GCP agotada | QUOTA_EXCEEDED en Cluster Autoscaler events | Solicitar aumento de cuota en la consola de GCP (CPU, IP addresses, SSD) |
Preemption y prioridad
Sección titulada «Preemption y prioridad»Cuando no hay recursos disponibles, Kubernetes puede desalojar pods de menor prioridad para hacer espacio a pods más importantes. HERA define PriorityClasses para este propósito:
apiVersion: scheduling.k8s.io/v1kind: PriorityClassmetadata: name: hera-tier1-criticalvalue: 1000globalDefault: falsedescription: "Servicios Tier 1 — máxima prioridad de scheduling"---apiVersion: scheduling.k8s.io/v1kind: PriorityClassmetadata: name: hera-tier2-standardvalue: 500globalDefault: true # Default para pods sin PriorityClass explícitadescription: "Servicios Tier 2 — prioridad estándar"---apiVersion: scheduling.k8s.io/v1kind: PriorityClassmetadata: name: hera-tier3-lowvalue: 100globalDefault: falsedescription: "Servicios Tier 3 — prioridad baja, pueden ser preempted"# Uso en Deploymentspec: template: spec: priorityClassName: hera-tier1-critical # Este pod tiene prioridad máximaCon estas PriorityClasses, si el cluster está lleno y un pod Tier 1 necesita recursos, Kubernetes desaloja pods Tier 3 para hacer espacio. Esto garantiza que los servicios críticos (checkout, pagos, auth) siempre tengan recursos disponibles.
Workload Identity: La Clave de la Seguridad
Sección titulada «Workload Identity: La Clave de la Seguridad»Workload Identity es la forma recomendada y más segura para que las cargas de trabajo dentro de GKE accedan a los servicios de GCP.
Configuración
Sección titulada «Configuración»-
Crear y anotar el SA de Kubernetes:
k8s-service-account.yaml apiVersion: v1kind: ServiceAccountmetadata:name: mi-app-ksanamespace: productionannotations:# Vincula el SA de K8s al SA de Googleiam.gke.io/gcp-service-account: mi-app-gsa@mi-proyecto.iam.gserviceaccount.com -
Vincular el SA de IAM (con Terraform):
# Permitir que el SA de K8s impersonifique al SA de Googleresource "google_service_account_iam_member" "workload_identity" {service_account_id = google_service_account.my_app.namerole = "roles/iam.workloadIdentityUser"member = "serviceAccount:mi-proyecto.svc.id.goog[production/mi-app-ksa]"} -
Usar el SA en el Deployment:
deployment.yaml apiVersion: apps/v1kind: Deployment# ...spec:template:spec:serviceAccountName: mi-app-ksa # <-- Aquí se usa el SA de K8s# ...
Service Accounts Críticas del Clúster
Sección titulada «Service Accounts Críticas del Clúster»Además de los SAs de aplicación (vinculados con Workload Identity), el clúster tiene Service Accounts del sistema que requieren gobernanza especial.
Inventario de SAs del sistema
Sección titulada «Inventario de SAs del sistema»| Service account | Namespace | Propósito | Nivel de privilegio |
|---|---|---|---|
default | Cada namespace | SA por defecto de pods sin SA explícito | Restringir — no debe tener permisos |
cluster-autoscaler | kube-system | Escalar nodos automáticamente | Alto — gestiona VMs en GCE |
argocd-server | argocd | Deploy de manifests al cluster | Alto — CRUD en todos los namespaces |
argocd-application-controller | argocd | Reconciliación GitOps continua | Alto — lectura/escritura de recursos |
asm-controller | istio-system | Gestión del service mesh | Alto — inyección de sidecars |
external-dns | kube-system | Sincronizar DNS records en Cloud DNS | Medio — modifica records DNS |
cert-manager | cert-manager | Gestionar certificados TLS | Medio — accede a Cloud DNS para ACME |
monitoring-agent | monitoring | Scraping de métricas | Bajo — solo lectura |
Principio de Least Privilege para SAs
Sección titulada «Principio de Least Privilege para SAs»# Restringir el SA "default" — NUNCA debe tener permisos# Aplicar en CADA namespaceapiVersion: v1kind: ServiceAccountmetadata: name: default namespace: tienda-herdezautomountServiceAccountToken: false # No montar token automáticamenteAuditoría de permisos de SAs
Sección titulada «Auditoría de permisos de SAs»# Ver qué permisos tiene un SA específicokubectl auth can-i --list --as=system:serviceaccount:tienda-herdez:bff-web-store
# Ver todos los ClusterRoleBindings (permisos globales)kubectl get clusterrolebindings -o custom-columns='NAME:.metadata.name,SA:.subjects[*].name,ROLE:.roleRef.name' | grep -v system:
# Verificar que ningún SA de aplicación tenga cluster-adminkubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects[]'Estrategia de Upgrade de Nodos
Sección titulada «Estrategia de Upgrade de Nodos»Mantener los nodos actualizados es crítico para seguridad y estabilidad. GKE ofrece release channels que gestionan upgrades automáticamente, pero la estrategia de upgrade debe minimizar el impacto en workloads.
Release Channels
Sección titulada «Release Channels»| Channel | Velocidad | Estabilidad | Uso en HERA |
|---|---|---|---|
| Rapid | Acceso temprano a nuevas versiones | Menor — puede tener bugs | No usar en HERA |
| Regular | Balance velocidad/estabilidad | Media | DEV/QA — probar versiones antes de PRD |
| Stable | Versiones probadas por semanas | Alta | PRD — máxima estabilidad |
Maintenance Windows
Sección titulada «Maintenance Windows»HERA define ventanas de mantenimiento para que los upgrades automáticos del cluster y sus nodos NO ocurran durante horario de alto tráfico.
Política estándar (clusters PRD)
Sección titulada «Política estándar (clusters PRD)»| Aspecto | Valor | Justificación |
|---|---|---|
| Días permitidos | Martes y miércoles | Menor tráfico en ecommerce; se evitan lunes (picos post-fin-de-semana) y viernes–domingo (picos de compra) |
| Horario | 00:00–04:00 CST | Franja de mínimo tráfico; suficiente para completar upgrades de control plane + node pools |
| Duración máxima | 4 horas por ventana | Evita extender el upgrade al horario de tráfico matutino |
| Frecuencia | Semanal | Recoge parches de Google al poco tiempo de publicarlos |
Tipos de mantenimiento cubiertos por la ventana
Sección titulada «Tipos de mantenimiento cubiertos por la ventana»- Upgrades del control plane de GKE (automáticos según release channel).
- Upgrades de nodos (respetando los surge settings — ver sección siguiente).
- Parches de seguridad del sistema operativo de los nodos (auto-upgrade).
- Migraciones de infraestructura subyacente ejecutadas por Google.
Exclusiones durante eventos comerciales críticos
Sección titulada «Exclusiones durante eventos comerciales críticos»Cuando el negocio tiene un evento que no puede absorber ninguna disrupción, el equipo de Platform Engineering declara una exclusión formal. Durante ese periodo ningún upgrade se ejecuta, ni siquiera parches menores.
| Evento | Periodo típico | Alcance |
|---|---|---|
| Buen Fin | Del miércoles previo al lunes siguiente | Todos los clusters PRD |
| Hot Sale | 7 días calendario completos | Todos los clusters PRD |
| Diciembre / Temporada alta | 15 de diciembre – 6 de enero | Todos los clusters PRD |
| Lanzamientos de campaña | Según calendario del producto | Cluster del producto afectado |
Responsabilidades (RACI)
Sección titulada «Responsabilidades (RACI)»| Responsabilidad | Rol |
|---|---|
| Mantener la ventana de mantenimiento y el calendario de exclusiones | Platform Engineer |
| Notificar eventos críticos que requieran exclusión (mín. 2 semanas antes) | Product Owner + Tech Lead |
| Monitorear que los upgrades se completen dentro de la ventana y reportar desbordamientos | SRE |
| Aprobar excepciones fuera del calendario estándar | Comité de Arquitectura (COMA) |
Surge Upgrades
Sección titulada «Surge Upgrades»Durante un upgrade de nodos, GKE usa surge upgrades para minimizar la disrupción:
| Parámetro | Valor HERA (PRD) | Efecto |
|---|---|---|
max_surge | 1 | Crea 1 nodo extra durante upgrade (cuesta temporalmente más) |
max_unavailable | 0 | Nunca deja nodos fuera de servicio — siempre capacidad completa |
Política estándar (node pools PRD)
Sección titulada «Política estándar (node pools PRD)»| Parámetro | Valor HERA | Qué garantiza |
|---|---|---|
| Estrategia | Surge | Crea primero la capacidad nueva antes de retirar la vieja |
| max_surge | 1 | Durante el upgrade puede existir temporalmente 1 nodo extra (costo puntual) |
| max_unavailable | 0 | Nunca se retira un nodo antes de que el nuevo esté listo — capacidad completa todo el tiempo |
Flujo del upgrade
Sección titulada «Flujo del upgrade»- GKE crea un nodo nuevo con la versión actualizada.
- Marca el nodo viejo como
cordon(deja de aceptar pods nuevos). - Ejecuta
drainsobre el nodo viejo (mueve los pods al nuevo, respetando los Pod Disruption Budgets). - Elimina el nodo viejo.
- Repite el proceso con el siguiente nodo del pool.
Por qué estos valores
Sección titulada «Por qué estos valores»max_unavailable=0es obligatorio en PRD: garantiza que la capacidad del cluster nunca baja durante un upgrade. Un valor mayor permitiría que durante minutos parte del tráfico no tuviera nodos disponibles.max_surge=1equilibra velocidad y costo: más nodos simultáneos aceleran el upgrade pero multiplican el costo temporal. Un único nodo extra es suficiente para un cluster de tamaño estándar.- Estrategia
Surge(noBlueGreen): la blue-green duplica todo el node pool en paralelo; es más cara y compleja. Para HERA, surge es adecuado.
Auto-escalado Inteligente
Sección titulada «Auto-escalado Inteligente»Nuestros clusters se adaptan a la carga de trabajo de forma automática en tres niveles.
1. Horizontal Pod Autoscaler (HPA)
Sección titulada «1. Horizontal Pod Autoscaler (HPA)»Escala el número de réplicas (pods) de un deployment basado en métricas como el uso de CPU o memoria.
HPA básico (CPU)
Sección titulada «HPA básico (CPU)»apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: mi-app-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: mi-app minReplicas: 3 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 75 # Escala cuando el uso de CPU supera el 75%HPA con Custom Metrics
Sección titulada «HPA con Custom Metrics»Para servicios event-driven o APIs con SLAs de latencia, CPU no es la mejor señal. HERA usa custom metrics de Cloud Monitoring:
# hpa-custom-metrics.yaml — escalar por mensajes pendientes en Pub/SubapiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: worker-inventarios-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: worker-inventarios minReplicas: 1 maxReplicas: 20 metrics: # Escalar por profundidad de cola Pub/Sub - type: External external: metric: name: pubsub.googleapis.com|subscription|num_undelivered_messages selector: matchLabels: resource.labels.subscription_id: inventarios-subscription target: type: AverageValue averageValue: 100 # 100 mensajes pendientes por pod # Combinado con CPU como safety net - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 80# hpa-latency.yaml — escalar por latencia P99apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: bff-web-store-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: bff-web-store minReplicas: 3 maxReplicas: 15 metrics: - type: Pods pods: metric: name: http_request_duration_seconds_p99 target: type: AverageValue averageValue: "500m" # 500ms — escalar si P99 sube de 500msBehavior: Scale-Down Gradual
Sección titulada «Behavior: Scale-Down Gradual»Por defecto, HPA puede escalar hacia abajo agresivamente causando flapping. La sección behavior controla la velocidad:
apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: backend-checkout-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: backend-checkout-service minReplicas: 3 maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 behavior: scaleUp: stabilizationWindowSeconds: 30 # Esperar 30s antes de escalar up policies: - type: Percent value: 100 # Duplicar pods si es necesario periodSeconds: 60 scaleDown: stabilizationWindowSeconds: 300 # Esperar 5 min antes de escalar down policies: - type: Pods value: 1 # Máximo 1 pod a la vez periodSeconds: 120 # Cada 2 minutos| Parámetro | Recomendación HERA | Razón |
|---|---|---|
| Scale-up window | 30s | Reaccionar rápido a picos (ej: flash sales) |
| Scale-down window | 300s (5 min) | Evitar flapping — los picos pueden volver |
| Scale-down rate | 1 pod cada 2 min | Gradual para evitar la pérdida abrupta de capacidad |
| Scale-up rate | 100% (duplicar) | Agresivo para absorber tráfico repentino |
2. Cluster Autoscaler (CA)
Sección titulada «2. Cluster Autoscaler (CA)»Añade o elimina nodos (VMs) del cluster cuando no hay suficientes recursos para los pods (escala hacia arriba) o cuando hay nodos infrautilizados (escala hacia abajo). Esto aplica principalmente a GKE Standard.
3. Vertical Pod Autoscaler (VPA)
Sección titulada «3. Vertical Pod Autoscaler (VPA)»Ajusta automáticamente las solicitudes (requests) de CPU y memoria de los pods para optimizar el uso de recursos. Lo usamos en modo “recomendación” en producción para evitar reinicios inesperados.
Health Checks (Probes): Guía Completa
Sección titulada «Health Checks (Probes): Guía Completa»Las probes son el mecanismo de Kubernetes para saber si un pod está vivo, listo para recibir tráfico, o todavía arrancando. Configurarlas correctamente es la diferencia entre un servicio que se auto-recupera y uno que acumula errores silenciosos.
Los 3 tipos de probe
Sección titulada «Los 3 tipos de probe»| Probe | Pregunta que responde | Acción si falla | Cuándo aplica |
|---|---|---|---|
startupProbe | ¿Ya terminó de arrancar? | No evalúa liveness/readiness hasta que pase | Apps con arranque lento (JVM, carga de modelos ML) |
readinessProbe | ¿Puede recibir tráfico? | Quita el pod del Service (no recibe requests) | Siempre — obligatoria en HERA |
livenessProbe | ¿Sigue vivo? | Reinicia el pod (kill + recreate) | Siempre — obligatoria en HERA |
Ejemplo completo para un servicio backend
Sección titulada «Ejemplo completo para un servicio backend»apiVersion: apps/v1kind: Deploymentmetadata: name: backend-catalogo-servicespec: template: spec: containers: - name: catalogo image: us-docker.pkg.dev/hera-prd/hera/backend-catalogo-service:v2.1.0 ports: - containerPort: 8080 # Probe de arranque — para apps que tardan en iniciar startupProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 30 # 30 x 5s = 150s máximo para arrancar # Probe de readiness — ¿puede recibir tráfico? readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 0 # Sin delay — startupProbe ya cubrió el arranque periodSeconds: 10 successThreshold: 1 failureThreshold: 3 # 3 fallas = quitar del balanceador timeoutSeconds: 3 # Probe de liveness — ¿sigue vivo? livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 0 periodSeconds: 15 failureThreshold: 3 # 3 fallas = reiniciar el pod timeoutSeconds: 3Qué debe responder cada endpoint
Sección titulada «Qué debe responder cada endpoint»| Endpoint | Qué valida | Qué NO debe validar | Código OK | Código error |
|---|---|---|---|---|
/healthz (liveness) | El proceso responde, no está en deadlock | Dependencias externas (DB, cache, APIs) | 200 | 503 |
/ready (readiness) | Conexión a DB, cache warm, dependencias listas | Nada externo al pod que sea transient | 200 | 503 |
Timeouts recomendados por tipo de servicio
Sección titulada «Timeouts recomendados por tipo de servicio»| Tipo de servicio | startupProbe | readinessProbe | livenessProbe |
|---|---|---|---|
| BFF / Frontend (Node.js) | failureThreshold: 6 (30s) | period: 10s, timeout: 3s | period: 15s, timeout: 3s |
| Backend (Java/Spring) | failureThreshold: 30 (150s) | period: 10s, timeout: 5s | period: 15s, timeout: 5s |
| Worker (Python/Go) | failureThreshold: 12 (60s) | period: 15s, timeout: 3s | period: 20s, timeout: 3s |
| Data pipeline (Spark/dbt) | failureThreshold: 60 (300s) | period: 30s, timeout: 5s | period: 30s, timeout: 5s |
Anti-patterns comunes
Sección titulada «Anti-patterns comunes»| Anti-pattern | Consecuencia | Corrección |
|---|---|---|
| Liveness valida la base de datos | DB lenta = Kubernetes reinicia TODOS los pods = cascading failure | Liveness solo valida el proceso local; readiness valida DB |
Sin startupProbe en apps JVM | Liveness mata el pod antes de que termine de arrancar | Agregar startupProbe con failureThreshold alto |
timeoutSeconds: 1 (default) | GC pause de 2s = pod reiniciado innecesariamente | Subir a 3-5s según el runtime |
periodSeconds: 1 | Overhead de health checks satura el servicio | Mínimo 10s para readiness, 15s para liveness |
| Mismo endpoint para liveness y readiness | No puedes distinguir “el proceso murió” de “la DB está lenta” | Endpoints separados: /healthz (local) y /ready (dependencias) |
Network Policies: Modelo Zero Trust
Sección titulada «Network Policies: Modelo Zero Trust»Por defecto, todos los pods en un namespace pueden comunicarse entre sí. Implementamos Network Policies para restringir este comportamiento, siguiendo un modelo de confianza cero (Zero Trust).
-
Denegar todo por defecto: La primera regla en cada namespace es denegar todo el tráfico de entrada (ingress) y salida (egress).
default-deny.yaml apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: default-deny-allspec:podSelector: {} # Aplica a todos los podspolicyTypes:- Ingress- Egress -
Permitir tráfico explícitamente: Luego, creamos reglas específicas para permitir únicamente el tráfico necesario.
allow-ingress-to-app.yaml apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-ingress-to-mi-appspec:podSelector:matchLabels:app: mi-app # Aplica solo a los pods de nuestra aplicaciónpolicyTypes:- Ingressingress:- from:# Permite tráfico solo desde pods en el namespace del Ingress Controller- namespaceSelector:matchLabels:name: ingress-nginxports:- protocol: TCPport: 8080 # Permite tráfico solo al puerto 8080
Service Mesh: Anthos Service Mesh
Sección titulada «Service Mesh: Anthos Service Mesh»Las Network Policies cubren autorización L4 (¿qué pod puede hablar con qué pod?) pero NO cubren observabilidad L7, mTLS automático, retries inteligentes, traffic splitting o políticas de autorización por request. Para esto, HERA usa Anthos Service Mesh (ASM) — la implementación gestionada de Istio para GKE.
Por qué Service Mesh
Sección titulada «Por qué Service Mesh»| Capability | Sin Service Mesh | Con Anthos Service Mesh |
|---|---|---|
| mTLS entre servicios | Manual, requiere código en cada servicio | Automático, transparente al código |
| Observabilidad L7 | Cada servicio implementa logging/tracing manualmente | Métricas, logs y traces automáticos por request |
| Retries inteligentes | Lógica en cada cliente | Configuración declarativa central |
| Traffic splitting (canary, A/B) | Múltiples deployments con load balancers | Declarativo en VirtualService |
| Autorización por request | Cada servicio valida tokens | AuthorizationPolicy centralizada |
| Circuit breaking | Implementado en cada servicio | DestinationRule centralizada |
Por qué Anthos Service Mesh y no Istio open-source
Sección titulada «Por qué Anthos Service Mesh y no Istio open-source»| Criterio | Istio open-source | Anthos Service Mesh |
|---|---|---|
| Instalación | Compleja (manifiestos manuales) | gcloud container fleet mesh enable |
| Upgrades | Manuales y disruptivos | Gestionados por Google |
| Soporte | Comunidad | SLA enterprise de Google |
| Integración GCP | Manual | Nativa con Cloud Logging, Cloud Trace, IAM |
| Costo | ”Gratis” + 100% del costo operacional | Subscription + costo operacional reducido |
Decisión HERA: Anthos Service Mesh es el estándar para clusters PRD. El TCO es menor por el ahorro operacional.
Implementación en HERA
Sección titulada «Implementación en HERA»1. Habilitar ASM en el cluster
Sección titulada «1. Habilitar ASM en el cluster»# Habilitar Anthos Service Mesh con management automáticogcloud container fleet mesh enable --project=hera-prd
gcloud container fleet mesh update \ --management automatic \ --memberships=cluster-prd-us-central1 \ --project=hera-prd2. Habilitar inyección automática de sidecar en namespaces
Sección titulada «2. Habilitar inyección automática de sidecar en namespaces»# Inyectar el proxy Envoy automáticamente en todos los pods del namespacekubectl label namespace tienda-herdez istio-injection=enabledA partir de este momento, todo pod nuevo en tienda-herdez recibe automáticamente un sidecar Envoy sin tocar el código de la aplicación. mTLS, observabilidad y traffic management son transparentes.
3. Activar mTLS estricto
Sección titulada «3. Activar mTLS estricto»apiVersion: security.istio.io/v1kind: PeerAuthenticationmetadata: name: default namespace: tienda-herdezspec: mtls: mode: STRICT # Solo acepta tráfico mTLSCon esto, cualquier pod sin sidecar (sin mTLS) es rechazado automáticamente. Es Zero Trust dentro del cluster, sin código adicional.
4. Autorización por servicio
Sección titulada «4. Autorización por servicio»apiVersion: security.istio.io/v1kind: AuthorizationPolicymetadata: name: checkout-allow-bff namespace: tienda-herdezspec: selector: matchLabels: app: backend-checkout-service rules: - from: - source: principals: - "cluster.local/ns/tienda-herdez/sa/bff-web-store" - "cluster.local/ns/tienda-herdez/sa/bff-mobile-app" to: - operation: methods: ["GET", "POST"] paths: ["/api/orders", "/api/orders/*"]Esta policy dice: solo los BFFs identificados pueden llamar a backend-checkout-service con métodos GET/POST en paths específicos. Todo lo demás es rechazado.
5. Traffic splitting para canary deploys
Sección titulada «5. Traffic splitting para canary deploys»apiVersion: networking.istio.io/v1kind: VirtualServicemetadata: name: backend-checkout-service namespace: tienda-herdezspec: hosts: - backend-checkout-service http: - route: - destination: host: backend-checkout-service subset: stable weight: 90 - destination: host: backend-checkout-service subset: canary weight: 10 # 10% del tráfico al canaryCuándo NO usar Service Mesh
Sección titulada «Cuándo NO usar Service Mesh»| Situación | Recomendación |
|---|---|
| Cluster de DEV con < 10 servicios | No es necesario; el overhead de ASM no se justifica |
| POCs o sandboxes temporales | Network Policies son suficientes |
| Cluster monolítico (1-2 servicios) | Overhead innecesario |
ASM aplica para clusters PRD y QA con 10+ servicios donde la observabilidad y mTLS automático aportan valor real.
GitOps con ArgoCD
Sección titulada «GitOps con ArgoCD»Los pipelines de HERA siguen un patrón push-based: GitLab CI ejecuta kubectl apply o helm upgrade desde el pipeline hacia el cluster. Esto funciona pero tiene limitaciones:
- El cluster no es la fuente de verdad — Git lo es, pero el cluster puede divergir
- No hay drift detection automático (alguien puede cambiar manualmente con
kubectl edit) - Rollback requiere re-ejecutar pipeline
- La auditoría está distribuida entre Git y el cluster
GitOps invierte el modelo: el cluster observa Git y se sincroniza continuamente. Si alguien cambia algo manualmente, GitOps lo revierte automáticamente. Si Git cambia, el cluster lo aplica solo.
Por qué GitOps en HERA
Sección titulada «Por qué GitOps en HERA»| Aspecto | Pipeline push-based (HOY) | GitOps con ArgoCD (próxima fase) |
|---|---|---|
| Fuente de verdad | Git, pero el cluster puede divergir | Git es la única verdad — el cluster siempre se reconcilia |
| Drift detection | Manual o post-mortem | Automático y continuo |
| Rollback | Re-ejecutar pipeline | git revert y ArgoCD aplica solo |
| Auditoría | Distribuida (GitLab + cluster) | Centralizada en Git |
| Multi-cluster | Pipeline por cluster | Una sola configuración en Git, ArgoCD distribuye |
| Disaster recovery | Re-ejecutar pipelines en orden | Apuntar ArgoCD nuevo al mismo Git, sincronización automática |
Patrón GitOps en HERA
Sección titulada «Patrón GitOps en HERA»Flujo GitOps en HERA
El pipeline construye y escanea. ArgoCD observa Git y sincroniza el cluster automáticamente.
Estructura de repos para GitOps
Sección titulada «Estructura de repos para GitOps»HERA propone separar repos de código y de configuración:
| Repo | Contenido | Quién modifica |
|---|---|---|
backend-checkout-service (código) | Código fuente, Dockerfile, tests | Developers |
infra-helm-checkout-service (config) | Helm chart con valores por ambiente | Pipeline CI (auto) + Platform |
infra-argocd-applications (apps) | ArgoCD Application definitions | Platform Engineering |
Ejemplo de ArgoCD Application
Sección titulada «Ejemplo de ArgoCD Application»apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: backend-checkout-service-prd namespace: argocdspec: project: tienda-herdez source: repoURL: https://hera.gitlab.cloudherdez.com/products/ecommerce/tienda-herdez/_shared/infra-helm-checkout-service.git targetRevision: HEAD path: helm helm: valueFiles: - values-prd.yaml destination: server: https://kubernetes.default.svc namespace: tienda-herdez syncPolicy: automated: prune: true selfHeal: true # Si alguien cambia manualmente, ArgoCD lo revierte syncOptions: - CreateNamespace=false - PruneLast=trueCómo se ve el cambio operacional
Sección titulada «Cómo se ve el cambio operacional»| Operación | Pipeline push-based (HOY) | GitOps con ArgoCD |
|---|---|---|
| Deploy nuevo | Pipeline ejecuta helm upgrade | Pipeline modifica values.yaml en Git → ArgoCD sincroniza |
| Rollback | Re-ejecutar pipeline con versión anterior | git revert en repo de config → ArgoCD aplica |
Cambio manual con kubectl edit | Persiste hasta el próximo deploy | ArgoCD lo revierte automáticamente en segundos |
| Auditar qué corre en PRD | Inspeccionar cluster + comparar con Git | El repo de Git ES lo que corre |
| Multi-cluster (multi-región) | Pipeline distinto por cluster | Una sola Application, multiple destinations |
Estado en HERA
Sección titulada «Estado en HERA»GitOps con ArgoCD está en la hoja de ruta de plataforma. Hoy opera con pipelines push-based; la adopción de ArgoCD es parte del camino hacia self-service total.
Capacity Planning y Right-Sizing
Sección titulada «Capacity Planning y Right-Sizing»GKE auto-escala los nodos y pods, pero el auto-scaling no es magia. Si los requests están mal definidos, el cluster gasta de más o sufre throttling. Esta sección define el proceso de capacity planning de HERA.
Los 4 niveles de optimización
Sección titulada «Los 4 niveles de optimización»| Nivel | Qué se optimiza | Quién | Frecuencia |
|---|---|---|---|
| 1. Pod requests/limits | CPU y memoria por contenedor | Developer | Por release |
| 2. Cluster node pools | Tipo de máquina, mín/máx nodos | Platform Engineer | Trimestral |
| 3. Workload distribution | Bin packing entre nodos | Cluster Autoscaler | Continuo |
| 4. Commitment plans | Reserved capacity con descuento | FinOps | Anual |
Nivel 1 — Pod requests/limits (responsabilidad del Developer)
Sección titulada «Nivel 1 — Pod requests/limits (responsabilidad del Developer)»El error más común: definir requests igual a limits.
| Anti-pattern | Por qué es malo | Recomendación |
|---|---|---|
requests = limits = 2 CPU | Reserva 2 CPU aunque solo use 0.3 — cluster waste | requests = 0.5, limits = 2 |
Sin requests definidos | Cluster Autoscaler no puede planificar | Siempre definir requests |
limits muy bajos | OOM kills frecuentes | Definir limits con margen 2x sobre uso real |
| Sin VPA recomendaciones | No sabes cuánto usa realmente | Habilitar VPA en modo Off (solo recomendaciones) |
Cómo definir requests correctamente
Sección titulada «Cómo definir requests correctamente»- Habilita VPA en modo
Offpara que recomiende sin aplicar:
apiVersion: autoscaling.k8s.io/v1kind: VerticalPodAutoscalermetadata: name: backend-checkout-service-vpaspec: targetRef: apiVersion: apps/v1 kind: Deployment name: backend-checkout-service updatePolicy: updateMode: "Off" # Solo recomienda, no aplica-
Espera 7-14 días para que VPA aprenda los patrones reales
-
Consulta las recomendaciones:
kubectl describe vpa backend-checkout-service-vpa- Aplica las recomendaciones en el manifest del deployment:
resources: requests: cpu: 250m # Recomendación de VPA memory: 512Mi limits: cpu: 1000m # 4x el request — margen para picos memory: 1Gi # 2x el requestNivel 2 — Cluster node pools (responsabilidad del Platform Engineer)
Sección titulada «Nivel 2 — Cluster node pools (responsabilidad del Platform Engineer)»| Decisión | Cuándo aplica | Ahorro típico |
|---|---|---|
| Spot instances para batch/dev | Workloads tolerantes a interrupción | 60-80% |
| N2 vs E2 | E2 más barato pero menos performante | 30% para workloads no críticos |
| Right-sizing de node pools | Cuando hay nodos infrautilizados crónicos | 20-40% |
| Multi-zonal vs regional | Regional cuesta 3x pero da HA | (no es ahorro, es resiliencia) |
| GKE Autopilot vs Standard | Autopilot paga por pod, Standard por nodo | Variable según density |
Nivel 3 — Workload distribution (Cluster Autoscaler)
Sección titulada «Nivel 3 — Workload distribution (Cluster Autoscaler)»El Cluster Autoscaler hace bin packing, pero hay que ayudarlo:
# Hint para que pods relacionados vivan cercaaffinity: podAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app: backend-checkout-service topologyKey: kubernetes.io/hostname
# Hint para distribuir réplicas en nodos distintos (HA)topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app: backend-checkout-serviceNivel 4 — Commitment plans (responsabilidad del FinOps)
Sección titulada «Nivel 4 — Commitment plans (responsabilidad del FinOps)»Para workloads predecibles y de larga duración, los Committed Use Discounts (CUDs) ahorran 20-55%:
| Tipo | Descuento | Compromiso |
|---|---|---|
| Resource-based CUDs (CPU/RAM) | 20-25% | 1 año |
| Resource-based CUDs (CPU/RAM) | 37-55% | 3 años |
| Spend-based CUDs | Menor descuento, más flexibilidad | 1-3 años |
| Spot instances | 60-91% (descuento dinámico) | Sin compromiso, pueden ser interrumpidos |
Estrategia HERA: combinar baseline con CUDs (workloads críticos predecibles) + spot para batch/workers.
Métricas que debes monitorear
Sección titulada «Métricas que debes monitorear»| Métrica | Qué indica | Threshold de alerta |
|---|---|---|
| CPU request utilization | % del CPU reservado que se usa | > 80% sostenido = subir requests; < 30% = bajar requests |
| Memory request utilization | % de la memoria reservada que se usa | Mismo criterio |
| Pod pending count | Pods esperando nodo | > 0 sostenido = cluster underprovisioned |
| Node CPU/Memory | Saturación a nivel nodo | > 80% sostenido = aumentar node pool |
| Cost per service | Costo mensual por servicio | Cualquier cambio > 30% mes a mes requiere investigación |
QoS Classes: Cómo Kubernetes Prioriza Pods
Sección titulada «QoS Classes: Cómo Kubernetes Prioriza Pods»Kubernetes asigna automáticamente una Quality of Service class a cada pod basándose en sus requests y limits. Esto determina qué pods se sacrifican primero cuando un nodo se queda sin recursos.
| QoS Class | Condición | Prioridad de eviction | Uso en HERA |
|---|---|---|---|
| Guaranteed | requests == limits para CPU y memoria | Última — nunca se sacrifica si hay pods Burstable/BestEffort | Servicios Tier 1 (checkout, pagos, auth) |
| Burstable | requests definidos pero requests != limits | Media — se sacrifica después de BestEffort | Servicios Tier 2 y Tier 3 (default) |
| BestEffort | Sin requests ni limits | Primera — se sacrifica primero | Prohibido en HERA — todo pod debe tener requests |
# QoS Guaranteed — para Tier 1resources: requests: cpu: 500m memory: 512Mi limits: cpu: 500m # requests == limits → Guaranteed memory: 512Mi
# QoS Burstable — para Tier 2/3resources: requests: cpu: 250m memory: 256Mi limits: cpu: 1000m # requests != limits → Burstable (puede burst hasta 1 CPU) memory: 1GiLimitRange y ResourceQuota por Namespace
Sección titulada «LimitRange y ResourceQuota por Namespace»Para evitar que un equipo consuma recursos sin control, HERA define guardrails a nivel namespace:
LimitRange — límites por contenedor
Sección titulada «LimitRange — límites por contenedor»# limitrange.yaml — defaults y topes por contenedorapiVersion: v1kind: LimitRangemetadata: name: hera-default-limits namespace: tienda-herdezspec: limits: - type: Container default: # Limits por defecto si el pod no los especifica cpu: 500m memory: 512Mi defaultRequest: # Requests por defecto cpu: 100m memory: 128Mi max: # Máximo que un contenedor puede pedir cpu: 4 memory: 8Gi min: # Mínimo (evita requests irrisoriamente bajos) cpu: 50m memory: 64MiResourceQuota — tope por namespace
Sección titulada «ResourceQuota — tope por namespace»# resourcequota.yaml — cuota total para el namespaceapiVersion: v1kind: ResourceQuotametadata: name: hera-quota namespace: tienda-herdezspec: hard: requests.cpu: "20" # Máximo 20 CPUs en requests totales requests.memory: 40Gi # Máximo 40 GiB en requests totales limits.cpu: "40" # Máximo 40 CPUs en limits totales limits.memory: 80Gi pods: "100" # Máximo 100 pods en el namespace services.loadbalancers: "0" # CERO LoadBalancers — forzar uso de IngressObservabilidad del Clúster GKE
Sección titulada «Observabilidad del Clúster GKE»La instrumentación a nivel de servicio (logs, métricas RED/USE, traces) sigue los estándares de DevSecOps. Esta sección complementa con la observabilidad del clúster como infraestructura — lo que el equipo de plataforma necesita monitorear para que GKE funcione correctamente.
Métricas del Control Plane
Sección titulada «Métricas del Control Plane»El control plane de GKE (API Server, etcd, Scheduler, Controller Manager) es gestionado por Google, pero sus métricas son visibles y deben monitorearse:
| Componente | Métrica clave | Qué indica | Threshold de alerta |
|---|---|---|---|
| API Server | apiserver_request_duration_seconds | Latencia de llamadas a la API de Kubernetes | P99 mayor a 5s por 5 min |
| API Server | apiserver_request_total{code=~"5.."} | Errores del API Server | Mayor a 1% de requests totales |
| etcd | etcd_db_total_size_in_bytes | Tamaño de la base de datos de estado | Mayor a 6 GB (límite default: 8 GB) |
| etcd | etcd_request_duration_seconds | Latencia de lectura/escritura de estado | P99 mayor a 200ms |
| Scheduler | scheduler_pending_pods | Pods esperando scheduling | Mayor a 0 sostenido por 5 min |
| Scheduler | scheduler_scheduling_duration_seconds | Tiempo que tarda en schedulear un pod | P99 mayor a 10s |
Habilitar métricas del control plane
Sección titulada «Habilitar métricas del control plane»# Habilitar exportación de métricas del control plane a Cloud Monitoringgcloud container clusters update cluster-prd-us-central1 \ --enable-managed-prometheus \ --monitoring=SYSTEM,API_SERVER,SCHEDULER,CONTROLLER_MANAGER \ --project=hera-prdMétricas de Nodos y Recursos
Sección titulada «Métricas de Nodos y Recursos»| Métrica | Qué monitorear | Threshold |
|---|---|---|
| CPU allocatable vs requested | Qué % de CPU disponible está reservada | Mayor a 85% = cluster near-capacity |
| Memory allocatable vs requested | Qué % de memoria está reservada | Mayor a 85% = riesgo de OOM |
| Node readiness | Nodos en estado NotReady | Cualquier nodo NotReady por 2+ min |
| Disk pressure | Nodos con DiskPressure=True | Cualquier nodo — indica disco lleno |
| PID pressure | Nodos con PIDPressure=True | Cualquier nodo — indica process leak |
| Node count | Nodos activos vs esperados | Desviación mayor a 20% del baseline |
Dashboard GKE Platform (Cloud Monitoring)
Sección titulada «Dashboard GKE Platform (Cloud Monitoring)»HERA define un dashboard de plataforma con paneles organizados por capa:
HERA GKE Platform Dashboard
Paneles organizados por capa. El equipo de plataforma monitorea este dashboard continuamente.
- API Server P99
- API Server errors
- etcd DB size
- Scheduler pending
- Nodes ready / total
- CPU alloc vs requested
- Memory alloc vs requested
- Disk / PID pressure
- Pods running
- Pods pending
- Pod restarts
- OOMKilled events
- HPA current vs desired
- CA scale-up events
- Unschedulable pods
- Node pool size vs limits
- Ingress latency
- Ingress error rate
- DNS resolution
- Service Mesh P99
- Network Policy denies
- PSA violations
- Failed auth requests
- Audit log anomalies
Kubernetes Events como señal de problemas
Sección titulada «Kubernetes Events como señal de problemas»Los events de Kubernetes son una fuente valiosa de diagnóstico que muchas veces se ignora. HERA los exporta a Cloud Logging para retención y análisis:
# Ver events recientes de todo el clusterkubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -20
# Filtrar events problemáticoskubectl get events --all-namespaces --field-selector type=Warning --sort-by='.lastTimestamp'| Event tipo Warning | Qué indica | Acción |
|---|---|---|
FailedScheduling | Pod no puede ser asignado a un nodo | Ver sección Unschedulable Pods |
OOMKilled | Contenedor excedió su limit de memoria | Aumentar limits.memory o investigar memory leak |
BackOff (CrashLoopBackOff) | Pod falla repetidamente al arrancar | Revisar logs del contenedor: kubectl logs <pod> --previous |
FailedMount | Volumen no pudo montarse | Verificar PVC, StorageClass, permisos de SA |
Unhealthy (Liveness/Readiness) | Probes fallando | Ver sección Health Checks |
NodeNotReady | Nodo dejó de responder | Verificar con kubectl describe node, posible issue de VM |
Alertas de plataforma (SRE)
Sección titulada «Alertas de plataforma (SRE)»Estas alertas son responsabilidad del equipo de plataforma, no de los equipos de desarrollo:
| Alerta | Condición | Severidad | Canal |
|---|---|---|---|
| Cluster near capacity | CPU o memoria requested mayor a 85% de allocatable | P2 | Google Chat #hera-platform-alerts |
| Node NotReady | Cualquier nodo en estado NotReady por 2+ min | P1 | PagerDuty → SRE on-call |
| API Server degraded | API Server P99 mayor a 5s por 5 min | P1 | PagerDuty → SRE on-call |
| etcd approaching limit | etcd DB size mayor a 6 GB | P2 | Google Chat #hera-platform-alerts |
| Pod restart storm | Más de 10 pod restarts en un namespace en 5 min | P2 | Google Chat #hera-platform-alerts |
| Cluster Autoscaler stuck | Pods Pending + CA sin escalar por 10 min | P1 | PagerDuty → SRE on-call |
| Certificate expiring | TLS cert expira en menos de 14 días | P3 | Google Chat #hera-infra |
Exposición de Servicios: Del Pod al Usuario
Sección titulada «Exposición de Servicios: Del Pod al Usuario»Uno de los aspectos más críticos es cómo los servicios internos del cluster se exponen al tráfico externo. HERA sigue un modelo de capas donde cada nivel agrega control y seguridad.
Stack de exposición HERA
Sección titulada «Stack de exposición HERA»Stack de Exposición: del Usuario al Pod
Cada capa agrega control y seguridad al tráfico entrante antes de llegar a la aplicación.
LoadBalancer vs Ingress vs Gateway API
Sección titulada «LoadBalancer vs Ingress vs Gateway API»| Característica | Service LoadBalancer | Ingress (GKE) | Gateway API (GKE) |
|---|---|---|---|
| Capa | L4 (TCP/UDP) | L7 (HTTP/HTTPS) | L4-L7 (ambas) |
| 1 IP por servicio | Sí — 1 IP pública por Service | No — 1 IP comparte múltiples servicios | No — 1 Gateway comparte múltiples rutas |
| TLS termination | No (manual) | Sí (certificados gestionados) | Sí (certificados gestionados) |
| Routing por path/host | No | Sí (/api/v1 → Service A, /web → Service B) | Sí (más expresivo que Ingress) |
| WAF (Cloud Armor) | No soportado | Sí (via BackendConfig) | Sí (via Policy) |
| Costo | Costoso — 1 LB por Service (~$18/mes cada uno) | Eficiente — 1 LB para todos los Services | Eficiente — similar a Ingress |
| Estado en HERA | Prohibido para tráfico externo | Estándar actual | Próxima adopción (reemplaza Ingress) |
Configuración Ingress en HERA
Sección titulada «Configuración Ingress en HERA»apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: tienda-herdez-ingress namespace: tienda-herdez annotations: kubernetes.io/ingress.class: "gce" # Usa GKE Ingress Controller (Cloud LB) kubernetes.io/ingress.global-static-ip-name: "tienda-herdez-ip" networking.gke.io/managed-certificates: "tienda-herdez-cert" # Cloud Armor WAF cloud.google.com/backend-config: '{"default": "tienda-herdez-backend-config"}'spec: rules: - host: tienda.herdez.com.mx http: paths: - path: /api/* pathType: ImplementationSpecific backend: service: name: bff-web-store port: number: 8080 - path: /* pathType: ImplementationSpecific backend: service: name: frontend-tienda port: number: 3000Certificados TLS gestionados
Sección titulada «Certificados TLS gestionados»# managed-cert.yaml — Google gestiona la emisión y renovaciónapiVersion: networking.gke.io/v1kind: ManagedCertificatemetadata: name: tienda-herdez-cert namespace: tienda-herdezspec: domains: - tienda.herdez.com.mx - www.tienda.herdez.com.mxCloud Armor (WAF) integrado
Sección titulada «Cloud Armor (WAF) integrado»# backend-config.yaml — habilitar Cloud Armor en el IngressapiVersion: cloud.google.com/v1kind: BackendConfigmetadata: name: tienda-herdez-backend-config namespace: tienda-herdezspec: securityPolicy: name: hera-waf-policy # Referencia a la policy de Cloud Armor healthCheck: requestPath: /ready port: 8080 connectionDraining: drainingTimeoutSec: 30Comunicación interna: ClusterIP
Sección titulada «Comunicación interna: ClusterIP»Para comunicación entre servicios dentro del cluster, siempre usar Services tipo ClusterIP (el default):
# service-checkout.yaml — solo accesible dentro del clusterapiVersion: v1kind: Servicemetadata: name: backend-checkout-service namespace: tienda-herdezspec: type: ClusterIP # Default — no expone nada al exterior selector: app: backend-checkout-service ports: - port: 8080 targetPort: 8080Los BFFs llaman a backends internos por nombre DNS: http://backend-checkout-service.tienda-herdez.svc.cluster.local:8080.
Seguridad a Nivel Pod
Sección titulada «Seguridad a Nivel Pod»Más allá de Network Policies (L4) y Service Mesh (L7), la seguridad dentro del pod es la última línea de defensa. Si un atacante compromete un contenedor, estas configuraciones limitan el daño.
Pod Security Standards (PSS)
Sección titulada «Pod Security Standards (PSS)»Kubernetes define 3 niveles de seguridad para pods. HERA aplica el nivel Restricted en producción:
| Nivel | Qué permite | Uso en HERA |
|---|---|---|
| Privileged | Todo — contenedores root, host network, privileged mode | Prohibido — solo kube-system |
| Baseline | Bloquea lo más peligroso (hostPID, privileged), permite root | DEV/QA — balance entre seguridad y flexibilidad |
| Restricted | Solo non-root, read-only rootfs, sin capabilities extra | PRD — máxima seguridad |
Enforcement en namespaces
Sección titulada «Enforcement en namespaces»# namespace-prd.yaml — enforce Pod Security StandardsapiVersion: v1kind: Namespacemetadata: name: tienda-herdez labels: # Pod Security Admission — nivel Restricted pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/warn: restrictedCon este label, Kubernetes rechaza cualquier pod que no cumpla con el nivel Restricted. No es un warning — es un hard block.
SecurityContext completo (template HERA)
Sección titulada «SecurityContext completo (template HERA)»Este es el SecurityContext que todo Deployment en PRD debe usar:
# deployment-secure.yaml — template de seguridad HERAapiVersion: apps/v1kind: Deploymentmetadata: name: backend-catalogo-servicespec: template: spec: # Pod-level security securityContext: runAsNonRoot: true # NUNCA correr como root runAsUser: 1000 # UID no privilegiado runAsGroup: 1000 fsGroup: 1000 seccompProfile: type: RuntimeDefault # Seccomp profile por defecto del runtime containers: - name: catalogo image: us-docker.pkg.dev/hera-prd/hera/backend-catalogo-service:v2.1.0 # Container-level security securityContext: allowPrivilegeEscalation: false # No puede escalar privilegios readOnlyRootFilesystem: true # Sistema de archivos read-only capabilities: drop: - ALL # Eliminar TODAS las capabilities Linux # Volúmenes temporales para apps que necesitan escribir volumeMounts: - name: tmp mountPath: /tmp - name: cache mountPath: /app/.cache volumes: - name: tmp emptyDir: sizeLimit: 100Mi - name: cache emptyDir: sizeLimit: 500MiChecklist de seguridad por pod
Sección titulada «Checklist de seguridad por pod»| Control | Qué hace | Obligatorio en PRD |
|---|---|---|
runAsNonRoot: true | Rechaza contenedores que corran como root | Sí |
readOnlyRootFilesystem: true | Previene escritura en el filesystem del contenedor | Sí |
allowPrivilegeEscalation: false | Bloquea sudo, setuid y similares | Sí |
capabilities.drop: [ALL] | Elimina capabilities Linux innecesarias | Sí |
seccompProfile: RuntimeDefault | Limita syscalls disponibles al proceso | Sí |
automountServiceAccountToken: false | No monta token de SA si no se necesita | Recomendado |
Políticas de Admisión: Kyverno
Sección titulada «Políticas de Admisión: Kyverno»Pod Security Standards (PSS) cubren lo básico (non-root, capabilities), pero HERA necesita policies más específicas: validar que las imágenes estén firmadas, que vengan del registry autorizado, que tengan labels obligatorias, que los recursos estén definidos. Para esto usamos Kyverno — un motor de policies nativo de Kubernetes.
¿Por qué Kyverno y no OPA Gatekeeper?
Sección titulada «¿Por qué Kyverno y no OPA Gatekeeper?»| Criterio | Kyverno | OPA Gatekeeper |
|---|---|---|
| Lenguaje de policies | YAML nativo de Kubernetes | Rego (lenguaje propio de OPA) |
| Curva de aprendizaje | Baja — cualquier dev que conozca K8s YAML puede escribir policies | Alta — Rego es un lenguaje lógico-declarativo |
| Image verification | Nativo (verifyImages) | Requiere integración externa |
| Mutation | Sí — puede modificar recursos al admitirlos | Limitado — principalmente validación |
| Generate resources | Sí — puede crear NetworkPolicies, LimitRanges automáticamente | No |
| Ecosystem | Creciente, CNCF Incubating | Maduro, CNCF Graduated |
| Debugging | Policies legibles, errores claros | Rego puede ser críptico para no-expertos |
Decisión HERA: Kyverno como motor de admission policies en GKE. La razón principal es accesibilidad: los equipos de desarrollo (internos y partners) deben poder leer y entender las policies que bloquean sus deployments. YAML nativo elimina la barrera de aprender Rego.
Catálogo de Policies Estándar HERA
Sección titulada «Catálogo de Policies Estándar HERA»Estas policies se aplican a todos los clusters y son mantenidas por el equipo de plataforma:
Policies de Validación (bloquean si no cumplen)
Sección titulada «Policies de Validación (bloquean si no cumplen)»| Policy | Qué valida | Scope |
|---|---|---|
| require-signed-images | Imágenes deben estar firmadas con Cosign | PRD |
| restrict-image-registries | Solo imágenes de us-central1-docker.pkg.dev/hera-* | PRD, QA |
| require-labels | Labels obligatorias: app, team, tier, version | Todos |
| require-probes | Todo Deployment debe tener readinessProbe y livenessProbe | PRD, QA |
| require-resources | Todo contenedor debe tener requests y limits definidos | Todos |
| disallow-privileged | Rechaza contenedores privileged o con hostPID/hostNetwork | Todos |
| disallow-latest-tag | Rechaza imágenes con tag :latest | PRD, QA |
| restrict-service-type | Bloquea Services tipo LoadBalancer (forzar Ingress) | Todos |
| require-non-root | runAsNonRoot: true obligatorio | PRD |
| require-read-only-rootfs | readOnlyRootFilesystem: true obligatorio | PRD |
Policies de Mutación (corrigen automáticamente)
Sección titulada «Policies de Mutación (corrigen automáticamente)»| Policy | Qué hace | Scope |
|---|---|---|
| add-default-security-context | Agrega SecurityContext estándar si no está definido | DEV |
| add-default-network-policy | Genera NetworkPolicy default-deny al crear un namespace | Todos |
| inject-resource-defaults | Agrega requests default si no están definidos (via LimitRange) | DEV |
Policies de Generación (crean recursos asociados)
Sección titulada «Policies de Generación (crean recursos asociados)»| Policy | Qué genera | Cuándo |
|---|---|---|
| generate-network-policy | NetworkPolicy default-deny-all | Al crear un namespace con label hera.cloudherdez.com/managed=true |
| generate-resource-quota | ResourceQuota estándar por tier | Al crear un namespace con label tier |
Ejemplo: Policy de registry autorizado
Sección titulada «Ejemplo: Policy de registry autorizado»apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: restrict-image-registries annotations: policies.kyverno.io/title: Restrict Image Registries policies.kyverno.io/category: Security policies.kyverno.io/severity: high policies.kyverno.io/description: >- Solo permite imágenes del Artifact Registry de HERA. Imágenes de Docker Hub, quay.io u otros registries públicos son rechazadas en PRD y QA.spec: validationFailureAction: Enforce background: true rules: - name: validate-registries match: any: - resources: kinds: - Pod namespaces: "ns-*" # Solo namespaces de producto validate: message: >- La imagen {{ "{{request.object.spec.containers[].image}}" }} no proviene del registry autorizado. Solo se permiten imágenes de us-central1-docker.pkg.dev/hera-*/ pattern: spec: containers: - image: "us-central1-docker.pkg.dev/hera-*/*"Ejemplo: Policy de labels obligatorias
Sección titulada «Ejemplo: Policy de labels obligatorias»apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-labelsspec: validationFailureAction: Enforce rules: - name: require-deployment-labels match: any: - resources: kinds: - Deployment namespaces: "ns-*" validate: message: "El Deployment debe tener las labels: app, team, tier, version" pattern: metadata: labels: app: "?*" team: "?*" tier: "?*" spec: template: metadata: labels: version: "?*"Testing de policies antes de aplicar
Sección titulada «Testing de policies antes de aplicar»# 1. Instalar Kyverno CLIbrew install kyverno
# 2. Validar un manifest contra una policy (sin cluster)kyverno apply policies/restrict-registries.yaml \ --resource deployment.yaml
# 3. Test con un manifest que DEBE fallar (negative test)kyverno apply policies/restrict-registries.yaml \ --resource test/deployment-dockerhub.yaml \ --expected-result fail
# 4. Audit mode antes de enforce (ver qué fallaría sin bloquear)# Cambiar validationFailureAction a "Audit" temporalmentekubectl get policyreport -A # Ver violaciones sin bloqueoBinary Authorization: Posición de HERA
Sección titulada «Binary Authorization: Posición de HERA»Binary Authorization es el servicio de GCP que verifica que las imágenes de contenedor estén firmadas por autoridades de confianza antes de permitir su despliegue en GKE. Es el equivalente nativo de GCP a lo que Kyverno + Cosign hacen a nivel Kubernetes.
Decisión: Cosign + Kyverno como estándar (no Binary Authorization)
Sección titulada «Decisión: Cosign + Kyverno como estándar (no Binary Authorization)»| Criterio | Binary Authorization (GCP) | Cosign + Kyverno (HERA actual) |
|---|---|---|
| Vendor lock-in | Alto — solo funciona en GCP (GKE) | Bajo — Cosign es CNCF, Kyverno es CNCF |
| Portabilidad | Si migramos de GCP, hay que reemplazar | Funciona en cualquier cluster Kubernetes |
| Granularidad | Permite/rechaza imagen completa | Puede validar firma + labels + registry + policies adicionales |
| Integración con pipeline | Requiere Attestors de GCP + KMS de GCP | Cosign keyless con OIDC de GitLab (ya implementado) |
| Costo | Incluido en GKE pero requiere Cloud KMS ($) | Open source |
| Complejidad | Configuración de attestors, KMS keys, policy YAML | Cosign sign en pipeline + Kyverno ClusterPolicy |
| Scope | Solo validación de imágenes | Kyverno cubre imágenes + 15 policies adicionales |
Decisión formal: HERA usa Cosign (firma) + Kyverno (enforcement) como mecanismo de verificación de integridad de imágenes. Binary Authorization queda como opción documentada pero no adoptada por las siguientes razones:
- Portabilidad — Cosign + Kyverno funcionan en cualquier cluster K8s, no solo GKE
- Consolidación — Kyverno ya es el motor de admission policies; agregar Binary Authorization como segundo motor crea complejidad sin beneficio adicional
- Pipeline integrado — Cosign keyless con OIDC de GitLab ya está implementado y funcional
- Costo — Binary Authorization requiere Cloud KMS para las keys; Cosign keyless elimina esa necesidad
Cuándo reconsiderar Binary Authorization
Sección titulada «Cuándo reconsiderar Binary Authorization»| Escenario | Acción |
|---|---|
| Requisito regulatorio que exija Binary Authorization específicamente | Evaluar adopción como capa adicional (no reemplazo) |
| Multi-cloud con clusters fuera de GCP | Cosign + Kyverno se confirma como la opción correcta |
| GCP ofrece Binary Authorization con soporte Cosign nativo | Evaluar consolidación |
Protección del Runtime: Falco
Sección titulada «Protección del Runtime: Falco»Las herramientas de seguridad anteriores (SAST, SCA, container scanning, Kyverno) protegen antes y durante el despliegue. Pero una vez que el pod está corriendo, ¿quién detecta comportamiento anómalo? Esa es la función de Falco — un motor de detección de amenazas en runtime, proyecto CNCF Graduated.
Qué detecta Falco
Sección titulada «Qué detecta Falco»Falco monitorea syscalls del kernel en tiempo real y genera alertas cuando detecta actividad sospechosa:
| Categoría | Regla | Qué detecta | Severidad |
|---|---|---|---|
| Shell access | Terminal shell in container | Alguien abrió un shell (/bin/sh, /bin/bash) dentro de un contenedor | Critical |
| Process execution | Unexpected spawned process | Proceso no esperado ejecutándose en el contenedor | High |
| File access | Read sensitive file untrusted | Lectura de /etc/shadow, /etc/passwd, keys | Critical |
| File modification | Write below binary dir | Escritura en /bin, /sbin, /usr/bin | Critical |
| Network | Unexpected outbound connection | Conexión saliente a IP/puerto no autorizado | High |
| Network | Inbound connection to unexpected port | Proceso escuchando en puerto no declarado | Medium |
| Privilege | Container with sensitive mount | Contenedor con mount de /proc, /sys del host | Critical |
| Privilege | Change namespace privileges | Intento de cambiar namespaces de Linux (escape de contenedor) | Critical |
| Crypto mining | Detect crypto miners | Procesos conocidos de minería o conexiones a mining pools | Critical |
| Package management | Package management in container | apt-get, yum, pip install ejecutado en runtime | High |
Reglas personalizadas HERA
Sección titulada «Reglas personalizadas HERA»Además de las reglas predefinidas de Falco, HERA agrega reglas específicas al contexto enterprise:
- rule: HERA - Unauthorized external API call desc: > Detecta llamadas a APIs externas no autorizadas desde pods de producción. Solo se permite tráfico a dominios whitelisted. condition: > outbound and container and fd.sip.name != "*.googleapis.com" and fd.sip.name != "*.cloudherdez.com" and fd.sip.name != "*.herdez.com.mx" and k8s.ns.name startswith "ns-" output: > Conexión externa no autorizada desde pod HERA (pod=%k8s.pod.name ns=%k8s.ns.name dest=%fd.sip.name:%fd.sport command=%proc.cmdline user=%user.name) priority: WARNING tags: [network, hera-custom]
- rule: HERA - kubectl exec in production desc: > Detecta kubectl exec a pods de producción. Esto debería ser excepcional y requiere justificación. condition: > spawned_process and container and k8s.ns.name startswith "ns-" and proc.pname = "runc:[2:INIT]" and proc.name in (sh, bash, ash) output: > Shell interactivo en pod de producción (pod=%k8s.pod.name ns=%k8s.ns.name user=%user.name command=%proc.cmdline) priority: CRITICAL tags: [shell, hera-custom]
- rule: HERA - Secret file accessed desc: > Detecta lectura de archivos montados desde secrets de Kubernetes. condition: > open_read and container and fd.directory = "/var/run/secrets" and not proc.name in (node, java, python3, dotnet) output: > Acceso a secret file por proceso no esperado (pod=%k8s.pod.name file=%fd.name process=%proc.name user=%user.name) priority: HIGH tags: [secrets, hera-custom]Despliegue de Falco en GKE
Sección titulada «Despliegue de Falco en GKE»Falco se despliega como DaemonSet (un pod por nodo) usando el Helm chart oficial:
# Instalación con Helmhelm repo add falcosecurity https://falcosecurity.github.io/chartshelm repo update
helm install falco falcosecurity/falco \ --namespace falco-system \ --create-namespace \ --set driver.kind=ebpf \ --set falcosidekick.enabled=true \ --set falcosidekick.config.googlechat.webhookurl="https://chat.googleapis.com/v1/spaces/HERA_ALERTS/messages?key=..." \ --set falcosidekick.config.googlechat.minimumpriority=high \ --values falco-values-hera.yamlIntegración con alerting
Sección titulada «Integración con alerting»Falco se integra con el stack de observabilidad de HERA via Falcosidekick:
| Severidad Falco | Canal de notificación | SLA de respuesta |
|---|---|---|
| Critical | PagerDuty → SRE on-call + Google Chat #hera-security-alerts | 5 min |
| High | Google Chat #hera-security-alerts | 1 hora |
| Warning | Cloud Logging (análisis posterior) | Siguiente día hábil |
| Notice/Info | Cloud Logging solo | No requiere acción |
Respuesta automatizada
Sección titulada «Respuesta automatizada»Para eventos críticos, Falco + Falcosidekick pueden ejecutar respuestas automatizadas:
| Evento | Respuesta automática | Justificación |
|---|---|---|
| Shell in container (PRD) | Aislar pod con NetworkPolicy deny-all | Contener posible intrusión sin matar el pod (preservar evidencia) |
| Crypto miner detected | Kill pod + alerta Critical | No hay caso legítimo para minería en producción |
| Write to binary directory | Kill pod + alerta Critical | Indica posible compromiso del contenedor |
| Package management in PRD | Alerta + log para análisis | No matar — puede ser un proceso legítimo mal configurado |
# falcosidekick — respuesta automática para crypto mining- rule: HERA - Auto-response crypto miner action: kubernetes: delete: pod: name: "{{ .Output.k8s.pod.name }}" namespace: "{{ .Output.k8s.ns.name }}" notification: googlechat: priority: critical message: "Pod eliminado automáticamente por detección de crypto mining"Estado en HERA
Sección titulada «Estado en HERA»| Componente | Estado | Fase |
|---|---|---|
| Falco DaemonSet en PRD | Implementado | Fase 2 (actual) |
| Reglas predefinidas | Activas (audit mode) | Fase 2 |
| Reglas custom HERA | En desarrollo | Fase 2 → 3 |
| Respuestas automatizadas | Solo crypto mining | Fase 3 (próxima) |
| Falco en DEV/QA | No desplegado | Fase 3 |