Kubernetes Manifest Rules
These are the enforceable rules for writing production Kubernetes manifests - the workload spec fields that keep a service healthy, scheduled correctly, and hardened.
Search across all documentation pages
These are the enforceable rules for writing production Kubernetes manifests - the workload spec fields that keep a service healthy, scheduled correctly, and hardened.
The through-line: every workload declares its resource footprint, its health, its identity, and its security posture. Nothing is left implicit for the scheduler or an attacker to decide.
Validate structure with kubeconform -strict, then enforce the security-critical items with an admission policy (Kyverno or Gatekeeper) and Pod Security Standards.
Each item is a gate. A manifest that cannot pass it should fail CI or be rejected at admission.
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
memory: "256Mi"replicas >= 2 - a single replica has no availability during a node drain or crash.topologySpreadConstraints so one node or zone loss does not take the service down.readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /livez
port: 8080
periodSeconds: 15
failureThreshold: 3app.kubernetes.io/name, instance, version, part-of, and managed-by for selection and observability.image: registry/api@sha256:...; never :latest in a cluster.imagePullPolicy - IfNotPresent with digest pinning; avoid Always surprises.maxUnavailable and maxSurge so rollouts respect capacity.restricted on the namespace - label pod-security.kubernetes.io/enforce: restricted.apiVersion: v1
kind: Namespace
metadata:
name: payments
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latestrunAsNonRoot: true and a numeric runAsUser - refuse to start as UID 0.allowPrivilegeEscalation: false - block setuid escalation inside the container.capabilities.drop: ["ALL"], add back only what is proven necessary.readOnlyRootFilesystem: true - mount an emptyDir for any writable path the app needs.seccompProfile.type: RuntimeDefault - required by the restricted profile.securityContext:
runAsNonRoot: true
runAsUser: 10001
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefaultautomountServiceAccountToken: false when the pod does not call the API.terminationGracePeriodSeconds and handle SIGTERM - so pods drain connections cleanly on rollout.Remember the runtime boundary: these manifests are executed by containerd through the CRI on each node. Docker is not the in-cluster runtime, so nothing here depends on a Docker daemon running on the node.
Should I always set a CPU limit? Not always. CPU limits throttle and can hurt tail latency; set requests for scheduling and reserve hard CPU limits for tenancy isolation cases.
Why is a memory limit safer than a CPU limit? Memory is incompressible - exceeding it triggers an OOM kill. A limit contains a leak to one pod instead of taking down the node.
Do I need all three probe types? Readiness is essential. Add liveness carefully, and a startup probe only when initialization is slow enough to trip liveness.
What does PSS restricted actually block?
Privilege escalation, running as root, host namespaces, most capabilities, and writable root filesystems - the common container escape vectors.
Is a default-deny NetworkPolicy disruptive to roll out? Roll it out per namespace after mapping required flows; start in a non-critical namespace and add allow rules from observed traffic.
How do I pin images and still get patches? Pin by digest for reproducibility and use an automation (Argo CD Image Updater or a bot) to propose digest bumps through Git.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 19, 2026