Saltar al contenido

Kubernetes en produccion: lecciones de 3 anos operando clusters

A
abemon
| | 12 min de lectura | Escrito por profesionales
Compartir

La pregunta que deberias hacerte primero

Antes de hablar de como operar Kubernetes, hay una pregunta que demasiados equipos se saltan: deberia usar Kubernetes?

La respuesta no es automaticamente si. K8s resuelve un problema especifico: orquestar cargas de trabajo containerizadas a escala, con alta disponibilidad, despliegues declarativos y autoescalado. Si tienes 3 servicios con trafico predecible, Kubernetes es probablemente overengineering. Un par de VMs con Docker Compose y un load balancer te dan el 80% del beneficio con una fraccion de la complejidad.

Nuestra regla practica: Kubernetes empieza a justificarse a partir de 8-10 servicios, o cuando necesitas autoescalado real, o cuando tus requisitos de disponibilidad exigen zero-downtime deployments sistematicos. Por debajo de eso, las alternativas mas simples (ECS, Cloud Run, incluso Railway o Render) cubren la mayoria de necesidades con menos overhead operativo.

Dicho esto, cuando K8s es la respuesta correcta, es una herramienta extraordinaria. Estas son las lecciones de operarlo durante tres anos.

Dimensionamiento de cluster: el error del dia uno

El primer cluster que ayudamos a poner en produccion estaba sobredimensionado un 300%. Tres nodos m5.2xlarge (8 vCPU, 32GB RAM cada uno) para una carga que cabia holgadamente en un unico m5.xlarge. El motivo era el clasico: “por si acaso necesitamos escalar.”

El problema del sobredimensionamiento en cloud no es solo el coste (que lo es: esos tres nodos costaban 850 EUR/mes y la carga real necesitaba 280 EUR/mes). El problema es que enmascara errores de configuracion. Cuando tienes 96GB de RAM, no notas que un pod tiene un memory leak de 500MB. Cuando tienes 24 vCPUs, no notas que un servicio consume 4 CPUs por un bucle ineficiente. Los recursos sobrados esconden problemas que explotan cuando realmente necesitas escalar.

Lo que funciona: empezar con nodos right-sized, activar el Cluster Autoscaler desde el dia uno, y usar nodos de diferentes tamanos. Una combinacion de nodos small para cargas base y nodos medium/large que el autoscaler anade y elimina segun demanda. En EKS, Karpenter ha reemplazado al Cluster Autoscaler clasico y hace esto mucho mejor: selecciona automaticamente el tipo de instancia optimo para los pods pendientes.

Requests y limits: la configuracion mas importante y la mas ignorada. Los requests determinan cuanta CPU y memoria le garantiza el scheduler a un pod. Los limits determinan cuanto puede consumir como maximo. Sin requests, el scheduler no puede tomar buenas decisiones de placement. Sin limits, un pod con un leak puede tumbar un nodo entero.

La regla que seguimos: requests al 70-80% del consumo medio observado, limits al 150-200% del pico observado. Y revisamos estas cifras trimestralmente, porque el consumo cambia con cada release.

Networking: donde viven los dragones

El networking de Kubernetes es la fuente de mas incidentes en nuestra experiencia. No porque sea mal diseñado, sino porque es complejo y la mayoria de los equipos no lo entiende a fondo.

CNI (Container Network Interface). La eleccion de CNI importa mas de lo que parece. Calico es el mas comun y el mas versatile. Cilium esta ganando terreno rapido gracias a eBPF, que le da visibilidad y rendimiento superiores. AWS VPC CNI asigna IPs reales de la VPC a los pods, lo que simplifica la integracion con servicios AWS pero limita el numero de pods por nodo (depende del tipo de instancia y del numero de ENIs soportadas).

Hemos tenido un incidente en produccion causado por alcanzar el limite de IPs de la subnet en un cluster con VPC CNI. Los pods quedaban en Pending indefinidamente y el error era críptico. Desde entonces, siempre dimensionamos las subnets con un margen de 3x sobre la capacidad esperada.

Ingress. Nginx Ingress Controller sigue siendo el estandar para la mayoria de cargas. Pero atención al dimensionamiento: un unico ingress controller con los defaults es un single point of failure. Corremos dos o tres replicas con anti-affinity para distribuirlas en nodos diferentes, y monitorizamos la latencia del ingress como metrica primaria.

Service mesh. Istio sigue siendo potente pero pesado. Para equipos que necesitan observabilidad de red y mTLS entre servicios, Linkerd es mas ligero y mas facil de operar. Para la mayoria de los casos que vemos en mid-market, no se necesita un service mesh completo. Las Network Policies nativas de Kubernetes cubren la microsegmentacion basica.

DNS. CoreDNS es el componente invisible que causa problemas visibles. En clusters con cientos de pods, la resolucion DNS puede convertirse en cuello de botella. Dos ajustes que siempre aplicamos: ndots:2 en la configuracion de pods (para reducir queries innecesarias) y NodeLocal DNSCache (un cache DNS local en cada nodo).

Seguridad: lo minimo que no es negociable

La seguridad en Kubernetes tiene capas. Estas son las que consideramos obligatorias:

RBAC. Ningun usuario ni servicio deberia tener permisos cluster-admin excepto el equipo de plataforma. Cada equipo tiene un namespace con roles limitados: pueden desplegar en su namespace, leer logs, pero no pueden modificar recursos de otros equipos ni recursos globales del cluster. Esto parece obvio, pero hemos encontrado clusters en produccion donde todos los service accounts tenian permisos de admin.

Pod Security Standards. Desde Kubernetes 1.25, los Pod Security Standards (PSS) reemplazan a los PodSecurityPolicies. El nivel “restricted” deberia ser el default: no root, no host network, no privileged containers, no escalation de privilegios. Las excepciones se documentan y se auditan.

Escaneo de imagenes. Trivy o Grype en el pipeline de CI/CD. Cada imagen que entra al cluster pasa un escaneo de vulnerabilidades. Las criticas bloquean el despliegue. Las altas generan un issue que hay que resolver en 7 dias. Esto suena restrictivo hasta que descubres que el 40% de las imagenes base en Docker Hub tienen vulnerabilidades criticas conocidas.

Secrets. Los Secrets de Kubernetes nativos estan codificados en base64, no cifrados. Para produccion usamos External Secrets Operator que sincroniza secretos desde AWS Secrets Manager o HashiCorp Vault. Asi los secretos reales nunca viven en etcd.

Network Policies. Por defecto, todos los pods de un cluster Kubernetes pueden hablar con todos los demas. Esto es terrible para seguridad. Implementamos network policies de deny-all por defecto en cada namespace, y luego abrimos explicitamente solo las comunicaciones necesarias. Si, es trabajo adicional. Pero un pod comprometido en un namespace no deberia poder alcanzar la base de datos de otro namespace.

Despliegues que no despiertan a nadie a las 3am

El patron de despliegue por defecto de Kubernetes (RollingUpdate) funciona bien para la mayoria de los casos. Pero hay detalles que marcan la diferencia entre un despliegue tranquilo y un incidente:

Readiness probes bien configuradas. La readiness probe debe verificar que la aplicacion esta realmente lista para recibir trafico, no solo que el proceso esta corriendo. Si tu aplicacion necesita 30 segundos para calentar la cache, la readiness probe debe reflejar eso. De lo contrario, Kubernetes envia trafico a pods que todavia no estan listos y los usuarios ven errores 5xx.

PodDisruptionBudgets. Un PDB garantiza que siempre haya un numero minimo de pods disponibles durante actualizaciones de nodos o despliegues. Sin PDB, una actualizacion de nodo puede tumbar todas las replicas de un servicio simultaneamente. Siempre configuramos PDB con al menos maxUnavailable: 1 para servicios criticos.

Canary deployments. Para servicios de alto trafico o cambios arriesgados, usamos Argo Rollouts para canary deployments: el 5% del trafico va a la nueva version, monitorizamos metricas durante 10 minutos, y si todo esta bien, incrementamos progresivamente. Si las metricas se degradan, rollback automatico. Esto ha evitado incidentes en produccion que habriamos detectado demasiado tarde con un rolling update tradicional.

Optimizacion de costes: el ciclo continuo

Kubernetes en cloud no es barato. Un cluster EKS con 10 nodos m5.xlarge cuesta aproximadamente 1.400 EUR/mes solo en compute (sin contar el fee de EKS, networking, storage). Optimizar costes es un proceso continuo, no un proyecto puntual.

Spot instances para cargas tolerantes. Workloads batch, jobs de CI/CD, y entornos de desarrollo corren en nodos spot, que cuestan un 60-70% menos que on-demand. Karpenter gestiona automaticamente la mezcla de spot y on-demand. Lo critico es que las cargas en spot deben tolerar interrupciones: graceful shutdown, checkpointing, y la logica de retry adecuada.

Vertical Pod Autoscaler (VPA). VPA analiza el consumo real de los pods y recomienda (u opcionalmente aplica) ajustes de requests y limits. Es la herramienta mas infrautilizada del ecosistema. En un cluster de 80 pods, VPA identifico que el 60% tenia requests de CPU sobredimensionados entre 2x y 5x. Ajustarlos nos permitio reducir el numero de nodos de 12 a 8.

Namespaces de desarrollo con TTL. Los entornos de desarrollo en Kubernetes tienden a acumularse. Un namespace creado para probar una feature que se mergeo hace tres meses sigue consumiendo recursos. Implementamos un sistema de TTL que marca namespaces de desarrollo para borrado automatico despues de 7 dias de inactividad, con una notificacion previa al equipo.

Revision mensual de costes. Kubecost o OpenCost proporcionan visibilidad de coste por namespace, por deployment, por label. Revisamos estos datos mensualmente y los compartimos con los equipos de desarrollo. Cuando un equipo ve que su servicio cuesta 200 EUR/mes en compute, toma decisiones de optimizacion que antes ni se planteaba.

Kubernetes bien operado es una plataforma que multiplica la productividad de los equipos de desarrollo. Mal operado, es una fuente inagotable de incidentes y costes. La diferencia esta en invertir el tiempo necesario en los fundamentos: dimensionamiento, networking, seguridad y observabilidad. No hay atajos.

Sobre el autor

A

abemon engineering

Equipo de ingenieria

Equipo multidisciplinar de ingenieria, datos e IA con sede en Canarias. Construimos, desplegamos y operamos soluciones de software a medida para empresas de cualquier escala.