Containers Rules Best Practices
This page distills the container and Kubernetes rule set into practices you can adopt, in the order that a platform team usually adopts them.
The single most important idea: automate rules with policy engines wherever possible, so compliance is the default and not a review-time argument.
How to Use This List
Read this after the checklist. The checklist tells you what to enforce; this page tells you how to roll it out without stalling every team.
Adopt the groups roughly top to bottom. Each practice is written as an action with the reasoning attached.
A - Codify and Version the Rules
- Store rules as code in one repository. Policies, linter configs, and golden-path templates live in version control with a changelog, not on a wiki.
- Pin rules to stack versions. State the Kubernetes, Docker Engine, and Helm versions a rule targets so "correct" is never ambiguous as the platform moves.
- Give every rule an owner and a rationale. A rule without a named failure mode is a candidate for deletion, not enforcement.
- Review the rule set on a cadence. Prune rules whose failure mode no longer exists and deprecate anything tied to removed APIs.
B - Automate Enforcement, Left to Right
- Lint and scan in developer tooling first.
hadolint,kubeconform, and Trivy in pre-commit and CI give fast, friendly feedback before code lands. - Enforce security-critical rules at admission. Use Kyverno or Gatekeeper (OPA) so no path into the cluster can bypass non-root, PSS, or registry policy.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
rules:
- name: require-digest-or-tag
match:
any:
- resources:
kinds: [Pod]
validate:
message: "Images must not use the :latest tag"
pattern:
spec:
containers:
- image: "!*:latest"- Lean on Pod Security Standards for pod hardening. Labeling a namespace
restrictedenforces a large class of rules with zero custom policy code. - Prefer engine enforcement over documentation. A rule a machine checks is real; a rule only humans check is aspirational.
C - Roll Out Without Blocking Teams
- Ship every new policy in audit mode first. Set
validationFailureAction: Audit, publish the violations, and let teams see the impact before you enforce. - Fix the golden-path templates before enforcing. When the default Helm chart or Kustomize base already passes, most services comply for free.
- Enforce in a low-risk namespace first. Prove a default-deny NetworkPolicy or PSS
restrictedin a non-critical namespace, then expand. - Communicate deadlines and provide migration help. A policy that flips to enforce with no warning burns trust; a staged rollout builds it.
D - Handle Exceptions Explicitly
- Make exceptions scoped, owned, and time-boxed. Track them in the rules repo with an expiry, not as silent overrides in a manifest.
- Use policy exclusions, not disabled policies. Kyverno exceptions and Gatekeeper constraint exclusions keep the rule on for everyone else.
- Review exceptions on expiry. An exception that renews forever is really a rule that needs rewriting.
E - Keep Images and Supply Chain Trustworthy
- Pin bases and deployed images by digest. Immutable, content-addressed references make builds reproducible and rollbacks exact.
- Scan on build and admission. Trivy or Grype in CI, plus an admission check that blocks unsigned or unscanned images.
- Sign and verify with cosign. Require a valid signature so only attested images from your pipeline can run.
- Automate base-image bumps. A bot proposes digest updates so pinning does not mean shipping stale, vulnerable bases.
F - Close the Loop with GitOps and Observability
- Deploy declaratively with Argo CD or Flux. Git is the source of truth; drift is detected and reconciled automatically.
- Alert on policy violations and drift. Route audit-mode findings and reconciliation failures to the owning team, not a silent dashboard.
- Instrument with OpenTelemetry and Prometheus/Grafana. You cannot prove a rule prevents incidents without the signals to measure it.
When You Are Done
You should be able to point at a repository that defines every rule, a CI pipeline that catches most violations early, and an admission layer that makes the critical ones impossible to bypass.
New services should pass by default because the golden path already complies. Exceptions should be visible, owned, and expiring.
If any of those is missing, that gap is your next highest-leverage piece of work.
FAQs
Kyverno or Gatekeeper? Kyverno uses Kubernetes-native YAML policies and is quick to adopt; Gatekeeper uses OPA/Rego and suits teams already invested in Rego. Either satisfies these practices.
Do policy engines replace Pod Security Standards? No. Use PSS for baseline pod hardening and a policy engine for everything PSS cannot express, like registry allow-lists or required labels.
How do I introduce enforcement without an outage? Always start in audit mode, fix golden-path templates, roll out per namespace, and only then switch to enforce.
Where do these practices stop and design decisions begin? When a team wants to deviate from a rule for architectural reasons, capture it in an ADR rather than a quiet exception.
How many policies are too many? When exception volume and false positives outweigh the incidents prevented. Measure, then prune.
Can I enforce image signing gradually? Yes - verify in audit mode, onboard pipelines to cosign, then flip signature verification to enforce once coverage is high.
Related
- Why Rules Beat Tribal Knowledge
- Containers Rules Checklist
- Dockerfile Rules
- Kubernetes Manifest Rules
- ADR Template
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).