Production engineering guide for infrastructure testing covering patterns, implementation strategies, and operational best practices.
Infrastructure testing verifies that systems operate correctly under expected conditions and fail gracefully when they don't. This applies to network connectivity, service availability, resource constraints, and state consistency across components. Testing infrastructure requires validation of both static configurations and dynamic behaviors in test environments that mirror production.
Use ping with specific flags to test basic reachability:
ping -c 3 -W 5 example.com
The -c flag controls packet count, while -W sets timeout in seconds. A timeout of 5 seconds is appropriate for most internal services.
For TCP port testing, use nc (netcat) with explicit protocol flags:
nc -zv -w 5 database.example.com 5432
The -z flag enables scan mode without data transfer, -v shows verbose output, and -w sets connection timeout. This command returns exit code 0 for success, 1 for connection timeout, or 2 for port unreachable.
Test HTTP endpoints with curl using specific headers:
curl -f -s -o /dev/null -w "%{http_code}" --connect-timeout 5 https://api.example.com/health
The -f flag makes curl fail silently on HTTP errors, -s suppresses progress meter, -o /dev/null discards response body, and -w "%{http_code}" outputs only the HTTP status code. The --connect-timeout flag sets connection timeout.
Monitor CPU usage with top or htop using specific flags:
top -p 1234 -n 5 -d 2
The -p flag specifies process ID, -n sets update count, and -d sets delay between updates in seconds. For automated testing, combine with grep to extract values:
top -b -n 1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
The -b flag runs top in batch mode for scripting.
Test memory consumption using free with specific output format:
free -m | grep Mem | awk '{print $3}'
This command shows used memory in megabytes. For consistent testing, use vmstat to monitor system load:
vmstat 1 5 | tail -n +3 | head -n 1
The first 1 sets interval seconds, 5 sets sample count, and the pipeline filters out headers.
Compare running configuration with stored baseline using diff:
diff /etc/nginx/nginx.conf /tmp/baseline-nginx.conf
If files differ, the command outputs lines that differ. For service-specific validation, test reload without restart:
systemctl reload nginx && systemctl is-active nginx
This command reloads configuration and checks if service remains active. If reload fails, the service continues running with old config.
Validate database connection strings with psql:
psql -h db.example.com -p 5432 -U appuser -d appdb -c "SELECT version();" --set=ON_ERROR_STOP=on
The --set=ON_ERROR_STOP=on flag ensures command stops on any error. The -c flag executes a single command.
Check service health with custom endpoints:
curl -f -s -o /dev/null https://service.example.com/healthz
This endpoint must return HTTP 200 for healthy status. For more detailed checks, use:
curl -f -s -H "Accept: application/json" https://service.example.com/healthz | jq '.status'
The jq command parses JSON output to extract health status.
Test inter-service communication with a simple loopback test:
for i in {1..5}; do
curl -f -s -o /dev/null --connect-timeout 3 http://service.example.com/api/echo
if [ $? -eq 0 ]; then echo "Success on attempt $i"; break; fi
sleep 1
done
This loop retries up to five times with one-second delays. If all attempts fail, the script exits with non-zero status.
Check disk space usage:
df -h | grep '/$' | awk '{print $5}' | cut -d'%' -f1
This command shows percentage of root filesystem usage. For specific mount points:
df -h /var/lib/docker | awk 'NR==2 {print $5}'
Test write performance to storage:
dd if=/dev/zero of=testfile bs=1M count=100 oflag=direct
The oflag=direct flag bypasses OS cache, testing actual storage performance.
Validate container startup with docker inspect:
docker inspect --format='{{.State.Running}}' mycontainer
This command returns true when container is running. For health check validation:
docker inspect --format='{{.State.Health.Status}}' mycontainer
The health status can be healthy, unhealthy, or starting.
Check container logs for errors:
docker logs --tail=100 mycontainer | grep -i error
This command shows last 100 lines of logs and filters for error messages.
Test Kubernetes deployment health:
kubectl get pods -l app=myapp -o jsonpath='{.items[*].status.phase}'
This command returns pod phases like Running, Pending, or Failed. For readiness checks:
kubectl get pods -l app=myapp -o jsonpath='{.items[*].status.containerStatuses[*].ready}'
This shows readiness status of containers within pods.
Monitor service endpoints:
kubectl get svc myservice -o jsonpath='{.spec.ports[*].port}'
This returns port numbers exposed by the service.
Many tests silently fail when they should report failure. For example, ping without -W may hang indefinitely:
# BAD: Silent timeout
ping -c 3 example.com
# GOOD: Explicit timeout
ping -c 3 -W 5 example.com
The -W flag is essential for test reliability.
Network tools like nc do not fail on timeout unless explicitly configured:
# BAD: Silent success
nc -zv database.example.com 5432
# GOOD: Explicit error handling
if ! nc -zv -w 5 database.example.com 5432; then
echo "Connection failed"
exit 1
fi
Storage tests may pass even when they should fail:
# BAD: File size check only
df -h /var/lib/docker
# GOOD: Size and usage validation
if [ $(df -m /var/lib/docker | awk 'NR==2 {print $5}' | cut -d'%' -f1) -gt 90 ]; then
echo "Disk usage over 90%"
exit 1
fi
Use structured output for automated testing:
curl -f -s -o /dev/null -w "%{http_code} %{time_total}s" https://api.example.com/health
This command outputs both HTTP status code and total request time. For more detailed metrics:
curl -f -s -w "@curl-format.txt" https://api.example.com/health
Where curl-format.txt contains:
HTTP: %{http_code}
Time: %{time_total}s
Size: %{size_download} bytes
Validate configuration changes without service interruption:
# Test nginx config syntax
nginx -t
# If syntax is good, reload
if [ $? -eq 0 ]; then
systemctl reload nginx
fi
The nginx -t command validates configuration and returns exit code 0 for success. For services that do not support graceful reloads:
systemctl restart service-name
This command stops and starts the service, ensuring new configuration takes effect.
Test rollback procedures before deployment:
# Save current config
cp /etc/service.conf /etc/service.conf.backup
# Apply test config
cp test-config.conf /etc/service.conf
# Test functionality
curl -f -s -o /dev/null https://service.example.com/healthz
# If test fails, restore backup
if [ $? -ne 0 ]; then
cp /etc/service.conf.backup /etc/service.conf
systemctl restart service-name
fi
This pattern ensures configuration changes can be reverted without downtime.
Infrastructure testing requires careful attention to timeouts, exit codes, and structured output. Tests must fail fast when they detect issues rather than silently continuing with incorrect assumptions. The key is to validate both static configurations and dynamic behaviors in ways that closely mirror production conditions.
This page was rewritten on 15 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy