Laravel Packages

Health for Laravel: Kubernetes Probes and Prometheus Metrics

Published
Health for Laravel: Kubernetes Probes and Prometheus Metrics image

Health for Laravel is a health check package from Sylvester Damgaard. It registers separate endpoints for the three Kubernetes probe types, and a /health/metrics endpoint that Prometheus can scrape. New Laravel applications include the /up health route, which reports whether the application booted. With this package, you assign a different set of checks to each probe.

Here is what the package gives you:

  • Kubernetes probes: /health, /health/ready, and /health/startup, each with its own list of checks
  • 10 built-in checks: database, cache, queue, storage, Redis, environment, schedule, CPU, memory, and disk space
  • Prometheus metrics: check status and duration, plus load, memory, disk, and network gauges
  • Container awareness: reads cgroup v1 and v2 limits, so memory numbers come from the container and not the host
  • JSON metrics: the same system data at /health/metrics/json, with the hostname or pod name that served the request
  • health:check: runs the checks from the terminal and exits non-zero on a failure
  • Response caching: check results are cached for 10 seconds by default
  • HTML dashboard: a status page at /health/ui, disabled by default

Separate Checks for Each Kubernetes Probe

You assign checks to probes in config/health.php:

use Cbox\LaravelHealth\Checks\{
CacheCheck, DatabaseCheck, EnvironmentCheck,
QueueCheck, RedisCheck, StorageCheck
};
 
'checks' => [
'liveness' => [
DatabaseCheck::class,
],
'readiness' => [
DatabaseCheck::class,
CacheCheck::class,
RedisCheck::class,
QueueCheck::class,
StorageCheck::class,
],
'startup' => [
EnvironmentCheck::class,
],
],

Kubernetes restarts a container when its liveness probe fails. When the readiness probe fails, Kubernetes stops routing traffic to the pod and leaves it running. A probe endpoint returns 200 when every check is ok or warning, and 503 when any check is critical or unknown. The deployment manifest points each probe at its path:

livenessProbe:
httpGet:
path: /health
port: 80
periodSeconds: 15
readinessProbe:
httpGet:
path: /health/ready
port: 80
periodSeconds: 10
startupProbe:
httpGet:
path: /health/startup
port: 80
failureThreshold: 30
periodSeconds: 5

The /health/status endpoint returns every check result along with the hostname, which in Kubernetes is the pod name. The three probe endpoints leave the hostname out.

Prometheus Metrics

The /health/metrics endpoint returns two gauges per health check. app_health_check_status is 1.0 for ok, 0.5 for a warning, and 0.0 for critical or unknown. app_health_check_duration_seconds records how long the check took. The app prefix comes from HEALTH_PROMETHEUS_NAMESPACE.

System metrics come from the author's cboxdk/system-metrics package, which works on Linux and macOS. You get load averages, memory, disk usage per mount point, network bytes per interface, and uptime. Inside a container, the endpoint adds five more metrics:

Metric Type
app_container_memory_limit_bytes gauge
app_container_memory_usage_bytes gauge
app_container_cpu_quota gauge
app_container_cpu_throttled_total counter
app_container_oom_kills_total counter

You can learn more about all the capabilities provided in the Prometheus Metrics documentation.

Checking That the Scheduler Runs

ScheduleCheck reads a heartbeat timestamp from the cache. Schedule the health:heartbeat command in routes/console.php to write it:

use Illuminate\Support\Facades\Schedule;
 
Schedule::command('health:heartbeat')->everyMinute();

The check returns critical when the heartbeat is older than max_age_minutes, which defaults to 5. It returns warning when no heartbeat exists yet. Add the check to the readiness list, and the endpoint returns 503 when the task scheduler has not run for five minutes.

Writing a Custom Check

A check implements the HealthCheck contract, which has a name() method and a run() method that returns a CheckResult. Extend BaseCheck and the name comes from the class name, so PaymentGatewayCheck becomes payment_gateway:

namespace App\Health;
 
use Cbox\LaravelHealth\Checks\BaseCheck;
use Cbox\LaravelHealth\DataTransferObjects\CheckResult;
use Illuminate\Support\Facades\Http;
 
class PaymentGatewayCheck extends BaseCheck
{
public function run(): CheckResult
{
try {
$response = Http::timeout(5)->get('https://payments.example.com/health');
} catch (\Throwable $e) {
return CheckResult::critical($this->name(), $e->getMessage());
}
 
if ($response->successful()) {
return CheckResult::ok($this->name());
}
 
return CheckResult::critical($this->name(), "HTTP {$response->status()}");
}
}

Add the class to the readiness array in config/health.php. CheckResult has four constructors: ok(), warning(), critical(), and unknown(). Each accepts a metadata array as its third argument, and the status and JSON responses include it. The built-in QueueCheck uses the metadata to report queue_size.

Installation

Version 2.0.0 requires PHP 8.3 and Laravel 11, 12, or 13:

composer require cboxdk/laravel-health
php artisan vendor:publish --tag="health-config"

Run the checks from the terminal to confirm the setup:

php artisan health:check
php artisan health:check --endpoint=readiness

Without the option, the command runs the liveness and readiness checks. The HEALTH_PREFIX environment variable changes the /health prefix, and each endpoint has its own path and enabled keys if you prefer /readyz.

The source and the full documentation are on GitHub.

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

acquaintsoft logo
Acquaint Softtech

Hire Laravel developers with AI expertise at $20/hr. Get started in 48 hours.

Visit Acquaint Softtech

The latest

View all →
Fast Excel 5.x Adds Streaming Imports and Safer Exports image

Fast Excel 5.x Adds Streaming Imports and Safer Exports

Read article
What We Know About Laravel 14 image

What We Know About Laravel 14

Read article
Difflock: Lint Laravel Migrations and Diff Your Schema image

Difflock: Lint Laravel Migrations and Diff Your Schema

Read article
Fresh Package: Laravel Package Skeleton with Testbench, CI, and Boost Integration image

Fresh Package: Laravel Package Skeleton with Testbench, CI, and Boost Integration

Read article
Inertia DevTools Now Available for Firefox image

Inertia DevTools Now Available for Firefox

Read article
Laravel Scalpel Scans for Filesystem Intrusion Evidence image

Laravel Scalpel Scans for Filesystem Intrusion Evidence

Read article