Simulating Network Partitioning in Docker: How to Test Service Resilience with Pumba
Learn how to perform robust docker network testing by using Pumba to inject latency, packet loss, and partitions into your containerized services.
Introduction
In modern distributed systems, the network is rarely a reliable constant. While developers often focus on optimizing code paths or database queries, the reality of production environments involves intermittent latency, dropped packets, and complete network partitions. If your services are not built to handle these failures, a minor network hiccup can cascade into a total system outage. Performing rigorous docker network testing is the most effective way to validate that your application’s retry logic, circuit breakers, and timeout configurations actually work as intended.
Chaos engineering is the practice of intentionally introducing failures into a system to observe how it responds. Pumba is a specialized tool for this purpose, designed specifically for the Docker ecosystem. Unlike manual network manipulation using iptables or tc (traffic control) inside individual containers, Pumba acts as a sidecar or a standalone orchestrator that can manipulate network traffic for any running container without requiring you to modify your application code or container images.
Understanding Network Failure Modes
Before diving into the tooling, it is important to define what we are testing. In a Docker environment, network failures generally manifest in three ways:
- Latency: The time taken for a packet to travel between two points increases significantly. This often triggers timeouts in synchronous HTTP calls or RPC frameworks.
- Packet Loss: Packets are dropped before reaching their destination. This tests the robustness of your TCP stack and the effectiveness of your application-level retry mechanisms.
- Network Partitioning: A container becomes completely unreachable from others. This is the ultimate test for service discovery and failover mechanisms.
By simulating these conditions, you can verify if your system fails gracefully or if it hangs indefinitely, potentially consuming all available worker threads or memory.
Installing and Configuring Pumba
Pumba is distributed as a Docker image, which makes it incredibly easy to integrate into your existing development or CI/CD pipeline. Because Pumba needs to interact with the Docker daemon to manipulate container network namespaces, you must mount the Docker socket into the Pumba container.
To run Pumba, you can use the following command structure:
docker run -d --name pumba \
-v /var/run/docker.sock:/var/run/docker.sock \
gaiaadm/pumba:master \
--interval 10s \
netem --duration 5s delay --time 3000 re2:my-service-container
In this example, Pumba targets any container matching the regex my-service-container. It waits for 10 seconds, then injects a 3000ms delay into the network traffic for 5 seconds. This is a non-destructive way to observe how your application handles sudden, high-latency spikes.
Practical Scenarios for Docker Network Testing
1. Simulating High Latency
High latency is often more dangerous than a total outage because it can lead to "zombie" requests that hold connections open, eventually exhausting your connection pool. To test this, you can use Pumba to inject a delay:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
gaiaadm/pumba:master netem --duration 30s delay --time 500ms my-app
This command forces a 500ms delay on all outgoing traffic from the my-app container for 30 seconds. Monitor your application logs during this window. Are your requests timing out? Are they retrying? Does the application remain responsive to other health checks?
2. Simulating Packet Loss
Packet loss is common in congested cloud networks. You can simulate this to test the resilience of your TCP connections:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
gaiaadm/pumba:master netem --duration 60s loss --percent 20 my-app
By setting a 20% packet loss rate, you will quickly see if your application handles partial data streams or if it crashes when a packet is dropped. This is particularly useful for testing services that communicate over gRPC or custom binary protocols.
3. Simulating Network Partitioning
To simulate a total partition, you can use the drop command. This effectively isolates the container from the network.
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
gaiaadm/pumba:master netem --duration 10s drop my-app
This is an excellent way to test how your service discovery mechanism (like Consul or internal Docker DNS) reacts when a service suddenly disappears from the network. Does the client-side load balancer remove the instance immediately, or does it continue attempting to route traffic to a dead node?
Integrating Pumba into Your Workflow
For effective testing, you should treat chaos experiments as part of your automated test suite. If you are using docker-compose, you can add a Pumba service to your docker-compose.yml file:
version: '3.8'
services:
app:
image: my-app:latest
networks:
- backend
chaos:
image: gaiaadm/pumba:master
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: netem --duration 10s delay --time 1000ms app
depends_on:
- app
By defining the chaos experiment as a service, you ensure that every time you spin up your environment for integration testing, the network resilience of your services is automatically validated. This prevents regressions where a developer might accidentally remove a timeout configuration or a retry policy.
Diagnosing Failures
When your application fails during a Pumba test, it is vital to have the right observability in place. If you are using tools like architecting-resilient-prometheus-docker-monitoring, you should see a spike in error rates or latency metrics immediately upon starting the Pumba container.
Common failure modes to look for include:
- Connection Pool Exhaustion: If your app uses a database or cache, look for errors related to connection timeouts. This usually means your pool size is too small to handle the backlog created by the injected latency.
- Thread Starvation: If your service stops responding to health checks, it may be because all available worker threads are blocked waiting for network I/O.
- Unbounded Queues: If you use message queues, check if they are growing rapidly because the consumer is unable to process messages due to network instability.
Operational Considerations and Safety
While Pumba is powerful, it should be used with caution. Never run Pumba against production environments unless you have a mature chaos engineering practice and automated safety switches. In a development or staging environment, Pumba is safe, but be aware that it affects the entire container, including its ability to communicate with the Docker daemon or other sidecars.
Always ensure that your Pumba commands have a defined --duration. If you run a command without a duration, the network degradation will persist until you manually remove the tc rules from the container, which can be difficult to debug if you forget which container is being throttled.
Conclusion
Docker network testing is no longer an optional activity for teams building distributed systems. By using Pumba to simulate real-world network conditions like latency, packet loss, and partitions, you can identify and fix resilience issues long before they impact your users. Start by injecting simple delays into your non-critical services, observe how your application handles the stress, and gradually increase the complexity of your experiments to cover more failure scenarios.
Frequently Asked Questions
Does Pumba require changes to my application code?
No, Pumba does not require any changes to your application code or Dockerfile. It works by manipulating the network traffic at the Linux kernel level for the target container, making it completely transparent to your application.
Can I use Pumba to test multiple containers at once?
Yes, Pumba supports regex matching for container names, allowing you to target a group of containers simultaneously. You can use this to simulate a network partition that affects an entire service cluster rather than just a single instance.
Is it safe to run Pumba in a production environment?
It is generally not recommended to run Pumba in production unless you have a highly controlled chaos engineering program with established blast radius limitations. Pumba is best suited for development, staging, or CI/CD pipelines where you can safely observe how your system handles failure without affecting real users.
How do I verify that Pumba is actually affecting my network?
You can verify the network degradation by running a ping or curl command from another container within the same Docker network to the target container. You should see the increased latency or connection failures reflected in the command output immediately after the Pumba command starts.