Kubernetes Guardrails
Enforce Kubernetes best practices including manifest validation, resource limits, probes, PodDisruptionBudgets, and HPA configurations for production readiness.
k8s to your lunar-config.yml:uses: github://earthly/lunar-lib/policies/k8s@v1.0.5
Included Guardrails
This policy includes 11 guardrails that enforce standards for your deployment and infrastructure.
valid
Validates that all Kubernetes manifests in the repository are syntactically correct and conform to K8s schema. Invalid manifests will fail deployment.
requests-and-limits
Ensures all containers have CPU and memory requests and limits defined. Missing resource specs can cause scheduling failures and noisy neighbor issues.
probes
Requires liveness and readiness probes on all containers. Probes enable Kubernetes to detect unhealthy pods and route traffic correctly.
min-replicas
Enforces minimum replica counts on HorizontalPodAutoscalers. Ensures services maintain capacity during scaling events and failures.
pdb
Requires PodDisruptionBudgets for Deployments and StatefulSets. PDBs protect availability during voluntary disruptions like node drains.
non-root
Requires containers to run as non-root users via securityContext. Running as root inside containers violates least privilege principles.
host-users
Requires workload PodSpecs to set hostUsers: false. User Namespaces
(GA in Kubernetes v1.36) map container UIDs to unprivileged host UIDs
so that a container escape no longer hands the attacker root on the
node. Complements non-root — that check drops privilege inside the
container; this one isolates UIDs across the kernel boundary. Target
cluster must be on K8s >=1.36; workloads that legitimately need host
UIDs (e.g. log shippers reading host paths) can be opted out via
include/exclude in lunar-config.yml.
host-network
Fails when workload PodSpecs set hostNetwork: true. Sharing the host's
network namespace bypasses NetworkPolicy enforcement, exposes node-local
services to the pod, and gives a compromised container direct access to
the node's interfaces (and any cleartext traffic on them). Legitimate
hostNetwork users (CNI agents, node-local proxies, host-bound exporters)
can opt out via include/exclude in lunar-config.yml.
host-pid
Fails when workload PodSpecs set hostPID: true. Sharing the host's
PID namespace lets the container see, signal, and (with the right
capabilities) attach to every process on the node, undermining process
isolation and aiding lateral movement after a container compromise.
Workloads that need it (e.g. node-level monitoring agents) can opt out
via include/exclude in lunar-config.yml.
host-ipc
Fails when workload PodSpecs set hostIPC: true. Sharing the host's
IPC namespace exposes node-wide System V IPC and POSIX shared memory
to the container, which can be abused to read or tamper with other
workloads' shared-memory state. Workloads that genuinely need host IPC
can opt out via include/exclude in lunar-config.yml.
min-kubectl-version
Ensures the kubectl version used in CI meets the minimum required version. Old kubectl clients may miss security fixes or lack support for current cluster APIs.
How Guardrails Fit into Lunar
Lunar guardrails define your engineering standards as code. They evaluate data collected by integrations and produce pass/fail checks with actionable feedback.
Policies support gradual enforcement—from silent scoring to blocking PRs or deployments—letting you roll out standards at your own pace without disrupting existing workflows.
Learn How Lunar Works →Required Integrations
This policy evaluates data gathered by one or more of the following integration(s).
Make sure to enable them in your lunar-config.yml.
Configuration
Configure this policy in your lunar-config.yml.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
min_replicas
|
Optional |
3
|
Minimum replicas required for HPAs (default 3) |
max_limit_to_request_ratio
|
Optional |
4
|
Maximum ratio of limits to requests for CPU/memory (default 4) |
min_kubectl_version
|
Optional |
1.28
|
Minimum kubectl version required in CI (semver, e.g. "1.28") |
Documentation
View on GitHubKubernetes Guardrails
Enforces Kubernetes best practices for production-ready workloads.
Overview
This policy validates Kubernetes manifests against industry best practices including resource limits, health probes, PodDisruptionBudgets, and security configurations. It helps ensure your K8s workloads are production-ready and resilient.
Policies
This policy provides the following guardrails (use include to select a subset):
| Policy | Description | Failure Meaning |
|---|---|---|
valid |
Validates K8s manifest syntax | Manifest has YAML or schema errors |
requests-and-limits |
Checks CPU/memory requests and limits | Container missing resource specs |
probes |
Requires liveness and readiness probes | Container missing health probes |
min-replicas |
Enforces minimum HPA replicas | HPA minReplicas below threshold |
pdb |
Requires PodDisruptionBudgets | Deployment/StatefulSet missing PDB |
non-root |
Requires non-root security context | Container may run as root |
host-users |
Requires PodSpecs to set hostUsers: false (K8s ≥1.36 user namespaces) |
Container UIDs are not isolated from host UIDs — a container escape gives the attacker root on the node |
host-network |
Forbids hostNetwork: true on PodSpecs |
Workload shares the host network namespace — bypasses NetworkPolicy and exposes node interfaces |
host-pid |
Forbids hostPID: true on PodSpecs |
Workload shares the host PID namespace — can see, signal, and potentially attach to processes on the node |
host-ipc |
Forbids hostIPC: true on PodSpecs |
Workload shares the host IPC namespace — can read or tamper with node-wide shared memory |
min-kubectl-version |
Enforces minimum kubectl version in CI | kubectl client used in CI is below threshold |
Required Data
This policy reads from the following Component JSON paths:
| Path | Type | Provided By |
|---|---|---|
.k8s.manifests[] |
array | k8s collector |
.k8s.workloads[] |
array | k8s collector |
.k8s.hpas[] |
array | k8s collector |
.k8s.pdbs[] |
array | k8s collector |
.k8s.cicd.cmds[] |
array | k8s collector (cicd sub-collector) |
Note: Ensure the k8s collector is configured before enabling this policy.
Installation
Add to your lunar-config.yml:
collectors:
- uses: github://earthly/lunar-lib/collectors/k8s@v1.0.0
on: [kubernetes]
policies:
- uses: github://earthly/lunar-lib/policies/k8s@v1.0.0
on: [kubernetes]
enforcement: report-pr
# include: [valid, requests-and-limits, probes] # Only run specific checks
# with:
# min_replicas: "3"
# max_limit_to_request_ratio: "4"
# min_kubectl_version: "1.28"
Examples
Passing Example
A compliant component with proper resource specs, probes, and security context:
{
"k8s": {
"manifests": [
{"path": "deploy/deployment.yaml", "valid": true}
],
"workloads": [
{
"kind": "Deployment",
"name": "payment-api",
"namespace": "payments",
"path": "deploy/deployment.yaml",
"host_users": false,
"host_network": false,
"host_pid": false,
"host_ipc": false,
"containers": [
{
"name": "api",
"has_resources": true,
"has_requests": true,
"has_limits": true,
"has_liveness_probe": true,
"has_readiness_probe": true,
"runs_as_non_root": true
}
]
}
],
"pdbs": [
{"name": "payment-api-pdb", "target_workload": "payment-api"}
]
}
}
Failing Example
A component missing resources, probes, and security configuration:
{
"k8s": {
"workloads": [
{
"kind": "Deployment",
"name": "my-app",
"namespace": "default",
"path": "deploy/app.yaml",
"host_users": true,
"host_network": true,
"host_pid": true,
"host_ipc": true,
"containers": [
{
"name": "app",
"has_resources": false,
"has_requests": false,
"has_limits": false,
"has_liveness_probe": false,
"has_readiness_probe": false,
"runs_as_non_root": false
}
]
}
],
"pdbs": []
}
}
Failure messages:
deploy/app.yaml: Deployment default/my-app container 'app' missing resource requestsdeploy/app.yaml: Deployment default/my-app container 'app' missing livenessProbedeploy/app.yaml: Deployment default/my-app container 'app' should set securityContext.runAsNonRoot: truedeploy/app.yaml: Deployment default/my-app should set spec.hostUsers: false (Kubernetes user namespaces, GA in v1.36)deploy/app.yaml: Deployment default/my-app should not set spec.hostNetwork: true (workload shares the host network namespace)deploy/app.yaml: Deployment default/my-app should not set spec.hostPID: true (workload shares the host PID namespace)deploy/app.yaml: Deployment default/my-app should not set spec.hostIPC: true (workload shares the host IPC namespace)
Remediation
When this policy fails, resolve it by:
- For
validfailures: Fix YAML syntax errors or invalid K8s fields in the manifest - For
requests-and-limitsfailures: Addresources.requestsandresources.limitsfor CPU and memory - For
probesfailures: AddlivenessProbeandreadinessProbeto each container - For
min-replicasfailures: Increasespec.minReplicasin your HPA to meet the threshold - For
pdbfailures: Create a PodDisruptionBudget that selects your workload's pods - For
non-rootfailures: AddsecurityContext.runAsNonRoot: trueto the container or pod spec - For
host-usersfailures: Addspec.hostUsers: falseto the PodSpec (orspec.template.spec.hostUsers: falsefor Deployments/StatefulSets/DaemonSets/Jobs/CronJobs). Requires Kubernetes ≥1.36 in the target cluster. Privileged workloads that must share the host user namespace (e.g. log shippers reading host paths, kubelets, container-runtime sidecars) can useinclude/excludeinlunar-config.ymlto opt out. - For
host-networkfailures: Removespec.hostNetwork: truefrom the PodSpec. Workloads that legitimately need the host network (CNI agents, node-local proxies, host-bound metrics exporters) can opt out viainclude/excludeinlunar-config.yml. - For
host-pidfailures: Removespec.hostPID: truefrom the PodSpec. Node-level monitoring agents that need a host-wide process view can opt out viainclude/excludeinlunar-config.yml. - For
host-ipcfailures: Removespec.hostIPC: truefrom the PodSpec. Workloads that genuinely need host IPC (rare — usually legacy shared-memory consumers) can opt out viainclude/excludeinlunar-config.yml. - For
min-kubectl-versionfailures: Upgrade the kubectl client in your CI pipeline (e.g., pinazure/setup-kubectl@v4orsetup-kubectlaction to a newer version, or update the installed kubectl on self-hosted runners)
Consumers who want any of these surfaced without blocking can pin enforcement: report-pr at config time — but that's a consumer-side knob; the checks themselves just pass or fail.
Open Source
This policy is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.
Common Use Cases
Explore how individual guardrails work with specific integrations.
Ready to Automate Your Standards?
See how Lunar can turn your AGENTS.md, engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 200+ built-in guardrails.