Health Checks
Health Checks
Cbox Init provides health monitoring with TCP, HTTP, and exec-based health checks. Health checks prevent restart loops, enable dependency verification, and support both readiness and liveness modes.
Overview
Features:
- 🌐 TCP Health Checks - Port connectivity testing
- 📡 HTTP Health Checks - Endpoint validation with status codes
- ⚙️ Exec Health Checks - Custom command validation
- 🎯 Success Thresholds - Prevent flapping with consecutive-success requirements
- 🔄 Failure Thresholds - Configurable tolerance before marking unhealthy
- 📊 Prometheus Metrics - Health check duration and status tracking
Quick Start
processes:
nginx:
enabled: true
command: ["nginx", "-g", "daemon off;"]
health_check:
type: http
url: "http://127.0.0.1:80/health"
period: 10
timeout: 5
failure_threshold: 3
success_threshold: 2
Health Check Types
1. TCP Health Check
Tests port connectivity - Useful for databases, caches, and services without HTTP endpoints.
processes:
redis:
enabled: true
command: ["redis-server", "/etc/redis/redis.conf"]
health_check:
type: tcp
address: "127.0.0.1:6379"
period: 5
timeout: 2
failure_threshold: 3
success_threshold: 1
Configuration:
type: tcp- Requiredaddress- Format:host:port(e.g.,127.0.0.1:6379,localhost:3306)- Tests if the port accepts connections
Use cases: MySQL 127.0.0.1:3306, PostgreSQL 127.0.0.1:5432, Redis 127.0.0.1:6379, PHP-FPM 127.0.0.1:9000, Memcached 127.0.0.1:11211.
2. HTTP Health Check
Tests HTTP endpoints - Validates the HTTP status code.
processes:
nginx:
enabled: true
command: ["nginx", "-g", "daemon off;"]
health_check:
type: http
url: "http://127.0.0.1:80/health"
period: 10
timeout: 5
failure_threshold: 3
success_threshold: 2
expected_status: 200
Configuration:
type: http- Requiredurl- Full URL (e.g.,http://localhost:80/health)expected_status- Required status code (default200)- The check performs a
GETand passes only when the status equalsexpected_status. There is no response-body matching.
PHP health endpoint example:
// Simple health endpoint (works with any framework)
<?php
http_response_code(200);
header('Content-Type: application/json');
echo json_encode(['status' => 'healthy']);
3. Exec Health Check
Runs custom commands - Maximum flexibility for complex health validation.
processes:
horizon:
enabled: true
command: ["php", "artisan", "horizon"]
health_check:
type: exec
command: ["php", "artisan", "horizon:status"]
period: 30
timeout: 10
failure_threshold: 2
success_threshold: 1
Configuration:
type: exec- Requiredcommand- Array of command and arguments- Passes on exit code 0; fails on non-zero exit or timeout
Configuration Parameters
health_check:
type: http # Required: tcp | http | exec
url: "..." # Required for http
address: "..." # Required for tcp (host:port)
command: [...] # Required for exec
initial_delay: 5 # Seconds before the first check (default: 5)
period: 10 # Seconds between checks (default: 10)
timeout: 3 # Max wait per check (default: 3)
failure_threshold: 3 # Consecutive failures before unhealthy (default: 3)
success_threshold: 1 # Consecutive successes before healthy (default: 1)
expected_status: 200 # HTTP only (default: 200)
mode: both # liveness | readiness | both (default: both)
Parameter Details
initial_delay - Grace period after start before the first check runs. Default 5s.
period - Time between checks. Default 10s. Recommendation: 10-30s for most applications.
timeout - Maximum wait per check. Default 3s. Should be less than period.
failure_threshold - Consecutive failures before marking unhealthy. Default 3.
success_threshold - Consecutive successes before marking healthy. Default 1. Use 2-3 for flaky services to prevent flapping.
mode - How the result is used:
liveness- failures trigger a restart (per the restart policy)readiness- result gates dependents (depends_on) but does not restartboth(default) - used for both
Success Threshold Pattern
Prevents restart flapping by requiring multiple consecutive successes after a failure.
health_check:
type: http
url: "http://127.0.0.1:80/health"
failure_threshold: 3
success_threshold: 3 # Require 3 consecutive successes to be healthy again
Integration with Restart Policies
Health checks with a liveness mode work with restart policies to control process lifecycle:
processes:
worker:
enabled: true
command: ["php", "artisan", "queue:work"]
restart: on-failure # Only restart on failures
health_check:
type: exec
command: ["pgrep", "-f", "queue:work"]
period: 30
failure_threshold: 3
mode: liveness
Restart policy behaviors:
always- The unhealthy instance is killed and restartedon-failure- The unhealthy instance is killed and restarted (the kill counts as a failure)never- Health checks run and report, but the process is left alone. Killing it would end the workload for the life of the container, since nothing would bring it back.
Note that a liveness kill is a hard SIGKILL to the process group: it does not
run the process's pre_stop_hook and does not use its configured
shutdown.signal. A queue worker killed this way loses whatever job it was
holding. If your workload needs a graceful drain, prefer mode: readiness and
let the process be taken out of rotation rather than killed.
Prometheus Metrics
Health check metrics are exported when metrics_enabled: true. Labels are
name (the process) and type (the check type):
# Health check status (1=healthy, 0=unhealthy)
cbox_init_health_check_status{name="nginx", type="http"}
# Health check duration in seconds (histogram)
cbox_init_health_check_duration_seconds{name="nginx", type="http"}
# Total checks performed, by result (status="success"|"failure")
cbox_init_health_check_total{name="nginx", type="http", status="failure"}
# Current consecutive failures (gauge; label: name)
cbox_init_health_check_consecutive_fails{name="nginx"}
Grafana alerts:
- alert: HealthCheckFailing
expr: cbox_init_health_check_status == 0
for: 5m
annotations:
summary: "Process {{$labels.name}} health check failing"
- alert: SlowHealthCheck
expr: cbox_init_health_check_duration_seconds > 5
for: 5m
annotations:
summary: "Slow health check for {{$labels.name}}"
Best Practices
1. Match Check Type to Service
# ✅ TCP for database
redis:
health_check:
type: tcp
address: "127.0.0.1:6379"
# ✅ HTTP for web server
nginx:
health_check:
type: http
url: "http://127.0.0.1:80/health"
# ✅ Exec for queue worker
worker:
health_check:
type: exec
command: ["pgrep", "-f", "queue:work"]
2. Set Appropriate Timeouts
# ✅ Fast services - low timeout
health_check:
type: tcp
address: "127.0.0.1:6379"
timeout: 2
# ✅ Slow services - higher timeout
health_check:
type: exec
command: ["./complex-health-check.sh"]
timeout: 30
3. Use Success Thresholds for Flaky Services
health_check:
type: http
url: "http://127.0.0.1:80/health"
success_threshold: 3
4. Combine with Dependencies
processes:
php-fpm:
enabled: true
command: ["php-fpm", "-F"]
health_check:
type: tcp
address: "127.0.0.1:9000"
nginx:
enabled: true
command: ["nginx", "-g", "daemon off;"]
depends_on: [php-fpm] # Waits for PHP-FPM readiness
health_check:
type: http
url: "http://127.0.0.1:80/health"
Troubleshooting
Health Checks Always Failing
- Verify endpoint is reachable:
curl -v http://127.0.0.1:80/health # HTTP nc -z 127.0.0.1 6379 # TCP ./healthcheck.sh && echo ok || echo fail # Exec - Increase timeout:
timeout: 10 - Give the process more time to start:
initial_delay: 20,failure_threshold: 5 - Add a success threshold:
success_threshold: 2
Process Not Restarting on Failure
- Check the restart policy:
restart: always(oron-failure). - Ensure the health check has a liveness mode:
mode: bothormode: liveness. - Check logs:
journalctl -u cbox-init -f | grep health.
Examples
PHP Application
processes:
php-fpm:
enabled: true
command: ["php-fpm", "-F", "-R"]
health_check:
type: tcp
address: "127.0.0.1:9000"
period: 10
timeout: 5
nginx:
enabled: true
command: ["nginx", "-g", "daemon off;"]
depends_on: [php-fpm]
health_check:
type: http
url: "http://127.0.0.1:80/health"
period: 10
timeout: 5
failure_threshold: 3
success_threshold: 2
horizon:
enabled: true
command: ["php", "artisan", "horizon"]
health_check:
type: exec
command: ["php", "artisan", "horizon:status"]
period: 30
timeout: 10
failure_threshold: 2
Next Steps
- Configuration Reference - Complete configuration options
- Restart Policies - Process restart strategies
- Prometheus Metrics - Metrics and monitoring