Quickstart: 15 minutes to a protected node
The shortest path from an empty namespace to kernel-enforced QoS with live telemetry and the management dashboard. Nothing here changes your workloads until you assign a PriorityClass in the final step.
0. Requirements
| Requirement | Why |
|---|---|
| Kubernetes ≥ 1.33 on standard node pools | Autopilot-style managed modes forbid the privileged DaemonSet. |
Node kernel ≥ 6.12 with CONFIG_SCHED_CLASS_EXT=y + BTF | sched_ext is the enforcement mechanism. Verified today: GKE ≥1.36 (COS-129), EKS AL2023 + Bottlerocket ≥1.33. See platform support. |
helm ≥ 3.8, kubectl, cluster-admin | The chart installs RBAC and PriorityClasses. |
Network access to ghcr.io | Prebuilt, signed multi-arch images (amd64 + arm64). Building from source remains supported — see the appendix below. |
1. Install
One command. Images are prebuilt, multi-arch (amd64 + arm64), signed with keyless cosign, and ship with SPDX SBOM attestations:
helm install temper oci://ghcr.io/byte-lab/charts/temper \
--namespace temper --create-namespace \
--set dashboard.enabled=true \
--set priorityClasses.enabled=true
This deploys the node agent DaemonSet (which loads the kernel scheduler on each node), the
management dashboard, RBAC, and the recommended temper-* PriorityClasses. The
scheduler plugin, controller, and overcommit webhook are off by default — that is
complement mode. Enable them later with
scheduler.enabled, controller.enabled, and webhook.enabled.
2. Verify the node is protected
kubectl -n temper get pods # agent Running on every node
kubectl get node <node> -o jsonpath='{.metadata.annotations.temper\.codes/agent-status}'
# "ready" — the scheduler is attached and enforcing
If a node’s kernel lacks sched_ext, the agent says so loudly in its logs and the node simply stays on the stock scheduler — Temper never degrades a node it cannot protect.
3. Protect your first workload
Give one latency-critical workload a PriorityClass and watch it land in a protected tier:
kubectl patch deployment my-service --type merge \
-p '{"spec":{"template":{"spec":{"priorityClassName":"temper-critical"}}}}'
Then open the dashboard:
TOKEN=$(kubectl -n temper get secret temper-temper-dashboard-token -o jsonpath='{.data.token}' | base64 -d)
kubectl -n temper port-forward svc/temper-temper-dashboard 8090:8090
# → http://localhost:8090 — paste the token at the login page
You get the hierarchy explorer (cluster → node → pod with live perf, logs, and manifests), the savings view, and audit-logged actions. Tour: management plane.
4. The kill switch (know it before you need it)
Fleet-wide instant revert to the stock kernel scheduler:
kubectl annotate node --all temper.codes/safe-mode-requested=true
Nodes revert to CFS in milliseconds — it is kernel-native sched_ext behavior, and the failover has been measured under load. Remove the annotation to re-engage.
Appendix: building from source
Everything above also works with images you build yourself — the repository ships
every Dockerfile. Build with docker build -f docker/agent/Dockerfile . (and
docker/dashboard/Dockerfile), push to your registry, and override
agent.image.repository/dashboard.image.repository at install. This
is also the air-gap path: mirror the images into your internal registry and point the same
values at it.
Where next
- QoS tiers — how priorities map to kernel scheduler layers
- Workload profiles — per-thread-group tuning inside a pod
- Density & overcommit — turning protection into capacity
- Safety & rollback — failure modes and the honest disclosures