SkillByAIOpen interactive version →

Lesson 23 / 25

Linting Manifests

Catch risky settings before they reach a cluster.

Automated policy checks

Many problems are visible in the YAML: missing requests, missing probes, latest image tags, privileged containers, running as root, single replicas. Check manifests in CI with tools such as kube-linter, Polaris, kubeconform (schema validation) or Conftest, and enforce rules in the cluster with admission policies (Pod Security Admission, Kyverno, OPA Gatekeeper). A small script shows the idea.

Safe defaults, checked automatically

Least-privilege access, hardened pods, network policies and automated checks make clusters safer.

Figure 8.1 — Linting, security and checklist.

A tiny manifest linter, run

I ran this with Python 3. It is a simplified model of Kubernetes behaviour for learning, not the real controller code. Parsing a deliberately bad Deployment with PyYAML finds 7 issues: a single replica, a latest tag, no resources, no probes, a privileged container and no runAsNonRoot. Real tools check many more rules.

import yaml
manifest = """
apiVersion: apps/v1
kind: Deployment
metadata: {name: web}
spec:
  replicas: 1
  selector: {matchLabels: {app: web}}
  template:
    metadata: {labels: {app: web}}
    spec:
      containers:
      - name: web
        image: ghcr.io/example/web:latest
        securityContext: {privileged: true}
"""
rules = []
for doc in yaml.safe_load_all(manifest):
    spec = doc["spec"]; pod = spec["template"]["spec"]
    if spec.get("replicas", 1) < 2: rules.append("replicas < 2: no redundancy during node loss or rollouts")
    for c in pod["containers"]:
        if c["image"].endswith(":latest") or ":" not in c["image"]: rules.append(f"{c['name']}: image tag is latest or missing; pin a version or digest")
        if "resources" not in c: rules.append(f"{c['name']}: no resources.requests/limits")
        if "readinessProbe" not in c: rules.append(f"{c['name']}: no readinessProbe")
        if "livenessProbe" not in c: rules.append(f"{c['name']}: no livenessProbe")
        if c.get("securityContext", {}).get("privileged"): rules.append(f"{c['name']}: privileged container")
        if not c.get("securityContext", {}).get("runAsNonRoot"): rules.append(f"{c['name']}: runAsNonRoot not set")
for r in rules: print("WARN", r)
print(len(rules), "findings")

Output:

WARN replicas < 2: no redundancy during node loss or rollouts
WARN web: image tag is latest or missing; pin a version or digest
WARN web: no resources.requests/limits
WARN web: no readinessProbe
WARN web: no livenessProbe
WARN web: privileged container
WARN web: runAsNonRoot not set
7 findings

Lint in CI and enforce in the cluster

CI checks give fast feedback; admission policies stop anything that bypasses CI.

Quick check: Which setting should a manifest linter flag?

  • An image tag of latest
  • A pinned image digest
  • A readiness probe
  • Memory requests
Answer

An image tag of latest — Unpinned images make deployments unpredictable.