Skip to main content

Chaos Engineering

Key Takeaways for AI & Readers
  • Proactive Resilience Testing: Chaos Engineering is a disciplined practice of intentionally introducing controlled failures into distributed systems to discover weaknesses before they cause real outages. It goes beyond traditional testing by validating system behavior under turbulent conditions.
  • Scientific Method: Chaos engineering follows the scientific method -- define a steady state hypothesis, introduce a variable (the failure), observe the impact, and draw conclusions. Every experiment should have a clear hypothesis and measurable success criteria.
  • Chaos Mesh: A powerful, Kubernetes-native chaos engineering platform that uses CRDs to define experiments (PodChaos, NetworkChaos, StressChaos, IOChaos) and leverages eBPF and sidecar injection for low-overhead fault injection without modifying application code.
  • LitmusChaos: An alternative Kubernetes-native platform that provides a ChaosHub of pre-built experiments, a workflow engine, and a web UI for managing chaos experiments at scale.
  • Safety First: Chaos experiments must be conducted with guardrails -- namespaced scope, abort conditions, blast radius controls, and stakeholder communication. The goal is learning, not breaking production.
  • Continuous Chaos: Mature organizations integrate chaos experiments into CI/CD pipelines and schedule regular GameDays to continuously validate resilience as the system evolves.

"Everything fails all the time." -- Werner Vogels (CTO, Amazon).

In a distributed system, you should not ask if a component will fail, but how your system will react when it does. Chaos Engineering is the discipline of experimenting on a system to build confidence in its ability to withstand turbulent conditions in production. It is not about randomly breaking things -- it is about running controlled experiments with clear hypotheses and measurable outcomes.

1. Chaos Engineering Principles​

The discipline of chaos engineering, as codified by Netflix (the pioneers of the practice with Chaos Monkey), rests on four principles:

Define Steady State​

Before you inject failure, you must define what "normal" looks like in measurable terms. This is your steady state hypothesis. Examples: "Request latency at p99 is below 200ms," "Error rate is below 0.1%," "All health check endpoints return 200." If you cannot define steady state, you are not ready for chaos engineering -- you need observability first.

Introduce a Variable​

Inject a single, controlled failure into the system. Kill a pod, add network latency, exhaust CPU, corrupt a disk. The key is to change one variable at a time so you can attribute any deviation from steady state to the injected failure.

Observe the Impact​

Monitor your steady state metrics during and after the experiment. Did latency spike? Did error rates increase? Did auto-scaling kick in? Did alerts fire? The difference between your hypothesis and reality is where the learning happens.

Minimize Blast Radius​

Start small. Run experiments in staging first. Target a single pod before targeting a deployment. Set time limits and abort conditions. Chaos engineering should be constructive, not destructive.

2. Try It: Injecting Failure​

Try killing a pod below. Does your service stay available?

📦
📦
📦
Chaos Mesh allows you to programmatically break your cluster to verify your apps' resilience. If your Service is properly configured, killing 1 pod should result in 0% downtime for users.

3. Chaos Mesh Deep Dive​

Chaos Mesh is a Cloud Native Computing Foundation (CNCF) incubating project that provides a comprehensive chaos engineering platform for Kubernetes. It defines experiments as Kubernetes Custom Resources, making them declarative, version-controllable, and GitOps-friendly.

Architecture​

Chaos Mesh consists of:

  • chaos-controller-manager: Watches for chaos experiment CRs and orchestrates the injection and recovery of faults.
  • chaos-daemon: A DaemonSet running on every node with privileged access. It performs the actual fault injection using Linux kernel features, network namespaces, and eBPF.
  • chaos-dashboard: An optional web UI for creating, managing, and observing experiments.

PodChaos​

PodChaos experiments target pod lifecycle and availability:

# pod-kill-experiment.yaml
# Kill random pods matching the selector every 60 seconds
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: pod-kill-backend
namespace: chaos-testing
spec:
action: pod-kill # Options: pod-kill, pod-failure, container-kill
mode: one # Options: one, all, fixed, fixed-percent, random-max-percent
selector:
namespaces:
- production
labelSelectors:
app: backend-api
scheduler:
cron: "@every 60s" # Repeat the experiment every 60 seconds
duration: "30s" # Each injection lasts 30 seconds

Pod-failure mode is subtler than pod-kill -- it makes pods enter an unready state without deleting them, testing whether your readiness probes and load balancers correctly route traffic away from unhealthy pods.

NetworkChaos​

NetworkChaos experiments simulate network failures that are common in distributed systems:

# network-latency-experiment.yaml
# Add 200ms latency with 50ms jitter to traffic between frontend and backend
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: backend-latency
namespace: chaos-testing
spec:
action: delay # Options: delay, loss, duplicate, corrupt, partition, bandwidth
mode: all
selector:
namespaces:
- production
labelSelectors:
app: backend-api
delay:
latency: "200ms" # Base latency to add
correlation: "50" # Correlation with previous packet (0-100)
jitter: "50ms" # Random variation around the base latency
direction: to # Options: to, from, both
target:
selector:
namespaces:
- production
labelSelectors:
app: frontend
mode: all
duration: "5m" # Run for 5 minutes
# network-partition-experiment.yaml
# Simulate a network partition between the app and its database
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: db-partition
namespace: chaos-testing
spec:
action: partition # Completely block traffic
mode: all
selector:
namespaces:
- production
labelSelectors:
app: backend-api
direction: both
target:
selector:
namespaces:
- production
labelSelectors:
app: postgres
mode: all
duration: "2m" # Partition lasts 2 minutes

StressChaos​

StressChaos experiments simulate resource pressure to test auto-scaling, eviction, and resource limit behavior:

# stress-cpu-experiment.yaml
# Consume CPU resources in target pods to trigger HPA or test degradation
apiVersion: chaos-mesh.org/v1alpha1
kind: StressChaos
metadata:
name: cpu-stress-backend
namespace: chaos-testing
spec:
mode: one
selector:
namespaces:
- production
labelSelectors:
app: backend-api
stressors:
cpu:
workers: 2 # Number of CPU stress workers
load: 80 # Target CPU load percentage per worker
memory:
workers: 1
size: "512MB" # Amount of memory to consume
duration: "3m"

IOChaos​

IOChaos experiments inject filesystem-level faults to test how applications handle disk errors:

# io-latency-experiment.yaml
# Add latency to filesystem operations for database pods
apiVersion: chaos-mesh.org/v1alpha1
kind: IOChaos
metadata:
name: io-latency-postgres
namespace: chaos-testing
spec:
action: latency # Options: latency, fault, attrOverride
mode: one
selector:
namespaces:
- production
labelSelectors:
app: postgres
delay: "100ms" # Add 100ms to every I/O operation
volumePath: /var/lib/postgresql/data # Target specific mount path
path: "**/*" # Affect all files
percent: 50 # Affect 50% of I/O operations
duration: "5m"

4. LitmusChaos Overview​

LitmusChaos is another CNCF project that provides a complete chaos engineering platform with some distinct advantages:

  • ChaosHub: A public and private repository of pre-built chaos experiments (called "faults") covering Kubernetes, AWS, GCP, Azure, and application-level scenarios.
  • ChaosWorkflows: Orchestrate multiple faults in sequence or parallel, with steady-state validation probes between steps.
  • Probes: Built-in mechanisms to validate steady state -- HTTP probes, command probes, Prometheus probes, and Kubernetes probes that assert conditions during the experiment.
  • Web UI: A comprehensive dashboard for managing experiments, viewing results, and collaborating across teams.

Litmus is a strong choice when you need a managed experiment catalog and a web UI for non-CLI-native team members.

5. GameDays and Runbooks​

A GameDay is a scheduled event where a team intentionally runs chaos experiments against their systems to test resilience. It is the chaos engineering equivalent of a fire drill.

Running an Effective GameDay​

  1. Prepare: Choose 3-5 failure scenarios relevant to recent incidents or architectural changes. Write a hypothesis for each. Notify stakeholders.
  2. Establish baseline: Capture current steady-state metrics (latency, error rates, throughput) before injecting any faults.
  3. Execute: Run experiments one at a time. Have all team members monitor dashboards. Record observations in real time.
  4. Evaluate: Compare observed behavior against hypotheses. For each failure: Did alerts fire? Did auto-healing work? Was customer impact within acceptable bounds?
  5. Document: Write up findings, create tickets for discovered weaknesses, and update runbooks with new recovery procedures.

Chaos Runbook Template​

For each experiment, maintain a runbook that documents: the hypothesis, the injection method, expected behavior, actual behavior, blast radius, rollback procedure, and action items discovered.

6. Automating Chaos in CI/CD​

Mature organizations run chaos experiments automatically as part of their deployment pipelines:

# In a CI/CD pipeline (e.g., GitHub Actions):
# After deploying to staging, run chaos experiments before promoting to production
steps:
- name: Deploy to staging
run: kubectl apply -k overlays/staging/

- name: Wait for rollout
run: kubectl rollout status deployment/backend -n staging --timeout=120s

- name: Run chaos experiment
run: |
kubectl apply -f chaos-experiments/pod-kill-backend.yaml
sleep 120 # Let the experiment run
# Validate steady state held
ERROR_RATE=$(curl -s "http://prometheus:9090/api/v1/query?query=rate(http_errors_total[2m])" | jq '.data.result[0].value[1]' -r)
if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then
echo "Chaos experiment failed: error rate $ERROR_RATE exceeds threshold"
kubectl delete -f chaos-experiments/pod-kill-backend.yaml
exit 1
fi

- name: Cleanup chaos
if: always()
run: kubectl delete -f chaos-experiments/pod-kill-backend.yaml --ignore-not-found

Common Pitfalls​

  • Running chaos without observability: If you cannot measure your steady state, you cannot evaluate experiment results. Invest in monitoring, tracing, and alerting before starting chaos engineering.
  • Starting in production: Always validate experiments in staging or a dedicated chaos environment first. Graduate to production only when you are confident in your abort conditions.
  • Injecting too many faults simultaneously: Change one variable at a time. Multiple concurrent faults make it impossible to attribute observed behavior to a specific failure.
  • No abort conditions: Every experiment must have a clear abort condition (e.g., "if error rate exceeds 5%, immediately stop the experiment"). Chaos Mesh supports this with duration and manual pause.
  • Chaos without buy-in: Running chaos experiments without management and team buy-in leads to blame when things go wrong. Chaos engineering is a team practice, not a rogue activity.
  • Treating chaos engineering as "testing": Chaos engineering is not about finding bugs in code -- it is about discovering systemic weaknesses in architectures, processes, and operational practices.

Best Practices​

  1. Start with known weaknesses: Begin your chaos engineering practice by validating that known recovery mechanisms (HPA, PDB, circuit breakers, retries) actually work as documented.
  2. Use PodDisruptionBudgets: Before running PodChaos experiments, ensure your workloads have PDBs configured. This validates that chaos respects availability guarantees.
  3. Namespace your experiments: Use Chaos Mesh's namespace selectors to restrict the blast radius of experiments. Never use cluster-wide selectors in production.
  4. Correlate with alerts: Verify that your alerting rules fire during chaos experiments. If you kill a pod and no alert fires, your monitoring has a gap.
  5. Track experiments over time: Maintain a log of all chaos experiments, their hypotheses, and outcomes. This builds institutional knowledge about system resilience.
  6. Schedule regular GameDays: Monthly or quarterly GameDays keep the practice alive and continuously validate resilience as the system evolves.

What's Next?​

  • Service Mesh: Service meshes provide built-in resilience features (circuit breaking, retries, timeouts) that chaos engineering validates.
  • Security Policies: Network policies complement chaos engineering by defining and enforcing allowed communication paths.
  • Disaster Recovery: Chaos engineering helps validate that your disaster recovery procedures actually work under real failure conditions.