K

Kubernetes metrics

Observability collectors available

Collect pod/node metrics from the Kubernetes metrics API during a run.

Install
$ loadr plugin install k8s-metrics
examples/plugins/k8s-metrics.yaml
# Overlay Kubernetes pod CPU/memory on the load timeline, driven by the
# `loadr-plugin-k8s-metrics` native SERVICE plugin.
#
# A service plugin has a start/stop lifecycle: loadr calls `start(config)` once
# before the run and `stop()` once after. On start this plugin resolves its
# bearer token + cluster CA from the mounted service account, builds a pure-Rust
# hyper + rustls HTTPS client (no kubectl, no client SDK, no C dep), then spawns
# a background poller that scrapes the Kubernetes metrics API on `interval_ms`:
#
#   GET /apis/metrics.k8s.io/v1beta1/namespaces/<namespace>/pods?labelSelector=...
#
# Each matched pod's summed container CPU/memory becomes a system-metric series
# (`k8s_pod_cpu_cores`, `k8s_pod_mem_bytes`, `k8s_scrapes`) aligned to the run
# window. A slow or unreachable scrape is counted, never fatal — the affected
# series just shows a gap. The service binds a tiny local endpoint and start()
# returns its bound address, e.g.:
#
#   → k8s-metrics collector at 127.0.0.1:41881
#
# For the in-cluster defaults to work, run the loadr controller inside the same
# cluster (e.g. a Job) with the projected service-account token mounted, and give
# its service account read access to `pods.metrics.k8s.io`. To collect from
# outside the cluster, set `api_url`, `token` and `ca_cert` (or `insecure: true`).
#
# Build + install the plugin, then run:
#   cargo build -p loadr-plugin-k8s-metrics --release
#   mkdir -p dist && cp plugins/loadr-plugin-k8s-metrics/plugin.toml dist/ \
#     && cp target/release/libloadr_plugin_k8s_metrics.so dist/
#   loadr plugin install dist
#   loadr run examples/plugins/k8s-metrics.yaml
#
# Or point the plan's `plugins:` entry at the built artifact directly (below).
name: k8s-metrics
description: Overlay Kubernetes pod CPU/memory on the load timeline

plugins:
  # Resolve `k8s-metrics` by name from the plugins dir (after
  # `loadr plugin install`). To run straight from a build tree instead, set:
  #   path: target/release/libloadr_plugin_k8s_metrics.so
  - name: k8s-metrics
    config:
      # Namespace to scrape pods from.
      namespace: app
      # Label selector narrowing which pods are collected. Empty = all pods in
      # the namespace. Passed through as the metrics API `labelSelector`.
      selector: app=api
      # Poll period (ms). Each tick is one scrape of the metrics API. Match it to
      # your snapshot interval; metrics-server samples on its own ~15s cadence.
      interval_ms: 5000
      # Kubernetes API server. Defaults to the in-cluster service address.
      # api_url: https://kubernetes.default.svc
      # Bearer token + cluster CA default to the mounted service account. To run
      # off-cluster, supply them explicitly (never inline a token in a plan):
      # token: ${env.K8S_TOKEN}
      # ca_cert: /etc/loadr/cluster-ca.pem
      # insecure: false            # skip TLS verification (off-cluster only)

defaults:
  http:
    base_url: https://api.example.com

scenarios:
  # A steady read flow against the target service; the collector overlays the
  # backing pods' CPU/memory on the same x-axis, so a throughput plateau and a
  # CPU ceiling line up on one chart.
  load:
    executor: constant-vus
    vus: 25
    duration: 10m
    flow:
      - request:
          name: list
          url: /api/items
          checks: [ { type: status, equals: 200 } ]
      - request:
          name: detail
          url: /api/items/1
          checks: [ { type: status, equals: 200 } ]

thresholds:
  http_req_duration: [ "p(95)<400" ]
  # Gate the run on the target staying healthy, not just the client SLO:
  "k8s_pod_cpu_cores{namespace:app}": [ "value<3.5" ]

A real run: install from the signed index, then watch the plugin work.

A runtime plugin, never in the binary

Installing pulls a per-platform driver from the signed index, verifies its SHA-256 and checks its ABI before it ever loads. Remove it any time with loadr plugin remove k8s-metrics.