Resiliencia · Kubernetes

Ingeniería del caos: cómo construimos un operador en Go para Kubernetes

Traducción al español del artículo original, con el diseño, los tipos de experimentos y las medidas de seguridad del operador.

Por Jorge Lozano · 12 oct 2025 · Ingeniería de resiliencia

En el mundo de los sistemas distribuidos y las arquitecturas de microservicios, la pregunta no es si algo va a fallar, sino cuándo. Las pruebas unitarias, de integración y de extremo a extremo son esenciales, pero a menudo no capturan los fallos en cascada ni los comportamientos inesperados que aparecen en un entorno dinámico de producción como Kubernetes.

Ahí es donde entra Chaos Engineering: la disciplina de experimentar con un sistema para ganar confianza en su capacidad de soportar condiciones turbulentas en producción. Pero ¿cómo inyectamos fallos de forma segura, repetible y automatizada en un entorno tan complejo? La respuesta es un operador de Kubernetes.

En este artículo exploramos los fundamentos de Chaos Engineering, el reto de aplicarlo en Kubernetes y cómo construimos nuestro propio operador de Chaos Engineering en Go para abordar el problema directamente.

El reto: caos controlado en un mundo orquestado

Los principios de Chaos Engineering son claros:

  1. Definir un estado estable: entender cuál es el comportamiento normal de los sistemas.
  2. Formular una hipótesis: predecir qué ocurrirá al introducir un fallo. Por ejemplo: “Si una réplica de la base de datos deja de funcionar, el servicio seguirá operando sin perder datos”.
  3. Inyectar fallos: introducir variables del mundo real, como fallos de red, picos de CPU o terminaciones de Pods.
  4. Verificar y aprender: comparar los resultados con la hipótesis y reforzar el sistema para hacerlo más resiliente.

Hacerlo manualmente en Kubernetes no es sostenible. Implica ejecutar comandos complejos de kubectl, escribir scripts frágiles y arriesgarse a un “radio de impacto” incontrolado que podría derribar todo el entorno de producción. Necesitamos un enfoque que sea:

  • Declarativo: describir el qué (el experimento), no el cómo (los comandos que hay que ejecutar).
  • Automatizado: integrar los experimentos en pipelines de CI/CD y ejecutarlos de forma recurrente.
  • Seguro: limitar el impacto para evitar catástrofes y asegurar que los experimentos se detengan si el sistema se vuelve inestable.
  • Nativo de Kubernetes: aprovechar su ecosistema, incluidas sus APIs, etiquetas y observabilidad.

Este es precisamente el tipo de problema para el que se diseñó el patrón Operator de Kubernetes. Un operador extiende la API de Kubernetes con Custom Resource Definitions (CRDs), lo que permite administrar aplicaciones y operaciones complejas como si fueran recursos nativos, por ejemplo Pods o Deployments.

Nuestra solución: el operador de Chaos Engineering

Para resolver estos retos, desarrollamos un operador de Chaos Engineering escrito en Go y basado en el framework controller-runtime. El operador introduce un conjunto de CRDs que permite a equipos de SRE, DevOps e ingeniería definir, ejecutar y observar experimentos de caos de forma sencilla y declarativa.

El objetivo es transformar Chaos Engineering, de una práctica esotérica y riesgosa, en una herramienta accesible y segura para validar la resiliencia de cualquier equipo que opere en Kubernetes.

Tipos de caos admitidos: un arsenal para la resiliencia

Nuestro operador ofrece un conjunto amplio de herramientas para simular los fallos más comunes en sistemas distribuidos. Cada una está representada por su propia CRD:

PodChaos

Simula fallos a nivel de Pod, piedra angular de cualquier aplicación en Kubernetes.

  • Acciones: pod-kill (elimina Pods), pod-failure (simula el estado de fallo de un Pod) y container-kill (termina un contenedor específico dentro de un Pod).
  • Caso de uso: validar si el Deployment se recupera correctamente después de perder réplicas.
apiVersion: chaos.engineering.io/v1alpha1
kind: PodChaos
metadata:
  name: kill-one-nginx-pod
spec:
  mode: one # Afecta a un solo Pod
  selector:
    labelSelectors:
      app: nginx
  action: pod-kill
  duration: "30s"

NetworkChaos

Inyecta fallos en la capa de red para probar la tolerancia de los servicios a la latencia, la pérdida de paquetes o las particiones de red.

  • Acciones: delay, loss, partition y bandwidth.
  • Caso de uso: probar cómo se comporta el frontend si el microservicio de backend responde con 100 ms adicionales de latencia.
apiVersion: chaos.engineering.io/v1alpha1
kind: NetworkChaos
metadata:
  name: frontend-network-delay
spec:
  mode: all # Afecta a todos los Pods seleccionados
  selector:
    labelSelectors:
      app: frontend
  action: delay
  delay:
    latency: "100ms"
  duration: "10m"

StressChaos

Genera estrés artificial de CPU o memoria en los contenedores para descubrir cuellos de botella y verificar el comportamiento del autoscaling (HPA).

  • Caso de uso: simular un pico de tráfico que lleve al 90 % el uso de CPU de la API y comprobar si el HPA escala correctamente las réplicas.

HTTPChaos

Intercepta y manipula tráfico HTTP para inyectar fallos en la capa de aplicación, como códigos de error 503 o latencia en respuestas específicas.

  • Caso de uso: verificar si un servicio cliente implementa correctamente reintentos con backoff exponencial cuando un servicio del que depende empieza a devolver errores 503 en el 25 % de las solicitudes.

Arquitectura y diseño: construir para el futuro

Una herramienta tan crítica como un operador de caos debe ser robusta, mantenible y extensible. Por eso basamos su diseño en los principios de Clean Architecture y en patrones de diseño probados.

Capas separadas

  1. Dominio (internal/domain): contiene la lógica de negocio pura, independiente de la infraestructura. Aquí viven interfaces como ChaosExecutor y TargetSelector, que definen qué es un experimento sin conocer cómo se ejecuta en Kubernetes.
  2. Infraestructura (internal/infrastructure): implementa las interfaces del dominio interactuando con sistemas externos. Por ejemplo, KubernetesPodKiller implementa la interfaz PodChaosExecutor usando un cliente de Kubernetes.
  3. Interfaz (controllers): el reconciliador de Kubernetes actúa como pegamento. Observa las CRDs, usa la lógica del dominio para decidir qué hacer y delega la ejecución a la capa de infraestructura.

Patrones de diseño clave

  • Patrón Strategy: cada tipo de acción de caos —pod-kill, delay, cpu-stress— es una estrategia diferente. Esto permite añadir nuevos tipos de fallo sin modificar el código existente.
  • Patrón Factory: se usa para construir el ChaosExecutor apropiado a partir de la especificación de la CRD.
  • Patrón Repository: abstrae el acceso a Pods y otros recursos de Kubernetes, lo que facilita las pruebas unitarias al permitir simular el cliente de Kubernetes.

Este enfoque no solo hace que el código sea altamente comprobable; también facilita añadir nuevos tipos de caos en el futuro.

La seguridad como prioridad: controlar el radio de impacto

La principal preocupación al ejecutar experimentos de caos es provocar una interrupción no prevista. Nuestro operador integra la seguridad desde el diseño:

  • Selectores flexibles y específicos: permite seleccionar Pods mediante etiquetas, anotaciones e incluso namespaces específicos.
  • Límites configurables: la especificación permite definir maxPods o maxPercentage para asegurar que un experimento nunca afecte más réplicas de las deseadas.
  • Namespaces protegidos: de forma predeterminada, el operador no actúa sobre namespaces críticos como kube-system, para proteger el plano de control del clúster.
  • Seguridad a nivel del Pod: el Pod del propio operador se ejecuta con privilegios mínimos, sin acceso root y con un sistema de archivos de solo lectura, siguiendo las buenas prácticas de seguridad de Kubernetes.

Conclusión: integrar Chaos Engineering en sistemas y plataformas

Chaos Engineering no debería ser una actividad manual y aterradora, reservada para gigantes tecnológicos. Al encapsular su lógica dentro de un operador de Kubernetes, la convertimos en una práctica de ingeniería sistemática, automatizada y segura.

Nuestro operador de Chaos Engineering proporciona una plataforma declarativa y extensible para que los equipos validen proactivamente la resiliencia de sus aplicaciones. Al seguir principios de diseño sólidos, como Clean Architecture, construimos una herramienta que no solo es potente hoy, sino que también está preparada para evolucionar según las necesidades futuras de los ecosistemas cloud-native.

Al adoptar una herramienta como esta, los equipos pueden pasar de reaccionar ante los fallos a anticiparlos y construir sistemas más sólidos y confiables que deleiten a los usuarios, incluso cuando se avecina el caos. Aunque actualmente se encuentra en una sólida etapa de MVP, estamos dando los últimos retoques a nuestra primera versión alpha pública, que se publicará pronto. Te animamos a darle una estrella al repositorio y prepararte para transformar el enfoque de tu equipo hacia la confiabilidad. El poder de dominar el caos casi está en tus manos; prepárate para reclamarlo.