---
name: k8s-manifest-review
description: "Reviews a Kubernetes workload manifest (Deployment/StatefulSet/DaemonSet and its Pod spec) for production readiness — the reliability and availability settings that decide whether it survives a node drain, a crash-looping process, a slow start, an OOM neighbor, and a bad rollout. Checks resource requests and limits, liveness/readiness/startup probes, replicas>1 paired with a PodDisruptionBudget and spreading, a bounded RollingUpdate strategy, graceful shutdown, a pinned image, and a non-root securityContext. Names each gap and the exact field that fixes it. Use when asked whether an existing manifest is production-ready or what to harden before it ships. Do NOT use for reviewing IaC/containers for security exploitability (a separate misconfiguration review), for writing a manifest from scratch, or for debugging a workload already running in the cluster."
metadata:
  decimalai-skill-id: "19172034-08ff-4a80-a030-671506cd9daf"
  decimalai-version-id: "28b8fbb8-d006-4f6a-9913-f4ae87244901"
  decimalai-version: "1"
  decimalai-body-sha256: "a3e57189456fee265c57bf651e07ffb19b5f0cd926932ff0fce1e544a2f209d8"
  decimalai-name: "k8s-manifest-review"
  decimalai-format: "1"
  decimalai-invocation: "model"
  decimalai-category: "devops"
  decimalai-source: "https://app.decimal.ai/s/k8s-manifest-review@1/SKILL.md"
---
# Kubernetes Manifest Prod-Readiness Review

A Kubernetes manifest that applies cleanly and schedules a running pod has proven exactly one
thing: it is *valid*. It has proven nothing about what happens when the cluster does its
normal job — drains a node for an upgrade, restarts a wedged process, shifts a rollout, or
reclaims memory from a noisy neighbor. Production readiness is almost entirely about the
fields that are **absent**. A Deployment with no `resources` schedules fine and then gets
evicted first under memory pressure. One with no probes stays in the Service endpoints while
it deadlocks. One with `replicas: 1` and no PodDisruptionBudget goes fully dark the moment
someone drains its node. None of these *look* broken — they look empty. This skill reviews a
workload manifest against a fixed readiness catalog and, for each gap, names **what** is
missing, **what fails** in production because of it, and the **exact field** that fixes it.

## When to activate

Activate when the request hands you an **existing Kubernetes workload manifest** — a
Deployment, StatefulSet, DaemonSet, ReplicaSet, or bare Pod, plus any PodDisruptionBudget or
HorizontalPodAutoscaler shipped alongside it — and asks whether it is **production-ready**,
safe to roll out, or what to harden before it ships.

Do **not** activate for: reviewing IaC or a container config for **security exploitability**
(privileged containers, host namespace escapes, plaintext secrets, world-open ports — that is
a misconfiguration/security review on a different axis); writing a fresh manifest from scratch
(an authoring task); or debugging a workload that is **already running** and misbehaving in
the cluster (that is live triage, not a pre-ship review).

## How to review

Go through the catalog surface by surface against the Pod template and the workload's
top-level fields. Treat an **absent** readiness field as a finding whenever its default is
unsafe for production — do not wait for a wrong value. For each finding report: **what** is
missing, **what breaks** in one clause, and the **exact field/value** that fixes it. Do not
manufacture findings on a manifest that already sets a surface correctly, and calibrate to the
workload: a `replicas: 1` singleton flagged for no PDB is right for a stateless API but is
expected for a genuine single-writer job — say which case you are assuming.

## Catalog — review every surface

### 1. Resource requests and limits
- **No `resources.requests`.** The scheduler treats the pod as near-zero cost, overpacks the
  node, and evicts this pod first under pressure. Fix: set `resources.requests.cpu` and
  `resources.requests.memory` to the steady-state need.
- **No `resources.limits.memory`.** Nothing caps the container; a leak lets it consume the
  node and OOM-kills neighbors. Fix: set `resources.limits.memory` (for memory, set it equal
  to the request so the pod is Guaranteed and not a target for reclaim).
- **CPU limit far below request, or a hard CPU limit on a latency-sensitive service.** A tight
  `limits.cpu` throttles the container under load and spikes tail latency. Fix: size the CPU
  limit to real burst need, or omit the CPU limit and rely on the request for scheduling.

### 2. Health probes — all three are distinct
- **No `readinessProbe`.** The pod joins the Service the instant the container starts, so
  traffic hits it before it can serve — and a wedged pod keeps receiving traffic. Fix: add a
  `readinessProbe` that checks the app can actually serve.
- **No `livenessProbe`.** A deadlocked process is never restarted; it just sits there failing.
  Fix: add a `livenessProbe` that a healthy process always passes (keep it cheap and
  dependency-free so a slow dependency does not trigger a restart storm).
- **Slow-starting app with only a `livenessProbe` (no `startupProbe`).** The liveness probe
  fires during boot and kills the container before it finishes starting, crash-looping it.
  Fix: add a `startupProbe` with a generous `failureThreshold × periodSeconds`; liveness and
  readiness do not run until it passes.
- **Readiness and liveness pointed at the same deep endpoint.** A slow dependency then both
  drops the pod from the Service *and* restarts it. Fix: keep liveness shallow (process is
  alive) and readiness dependency-aware (can serve).

### 3. Replicas, disruption budget, and spreading
- **`replicas: 1` for a service expected to stay available.** A node drain, upgrade, or
  eviction takes the whole service down with no standby. Fix: set `replicas: 2` or more (for a
  genuine single-writer StatefulSet, say so instead of flagging it).
- **`replicas > 1` but no PodDisruptionBudget.** A voluntary disruption (node drain, cluster
  upgrade) can evict every replica at once, because nothing tells the cluster a minimum must
  stay up. Fix: add a `PodDisruptionBudget` with `minAvailable` (or `maxUnavailable`) covering
  this workload's selector.
- **All replicas free to land on one node.** A single node failure takes the whole service
  down despite `replicas > 1`. Fix: add `topologySpreadConstraints` (or pod anti-affinity)
  across `kubernetes.io/hostname` and, ideally, zones.

### 4. Rollout strategy and graceful shutdown
- **No `strategy` / unbounded `RollingUpdate`.** A rollout that does not bound `maxUnavailable`
  can drop capacity below what the load needs mid-deploy; `Recreate` takes the service fully
  down between versions. Fix: set `strategy.type: RollingUpdate` with an explicit
  `maxUnavailable` and `maxSurge` sized to the replica count.
- **No graceful shutdown handling.** On termination the pod can be removed from the Service and
  SIGTERM'd while still serving in-flight requests, dropping them. Fix: set a realistic
  `terminationGracePeriodSeconds` and, if the app needs draining, a `preStop` hook so
  connections finish before the process exits.

### 5. Image pinning
- **`:latest` or no tag.** The running code is mutable — a restart or reschedule can pull
  different bytes than what was reviewed, and rollbacks are not reproducible. Fix: pin a
  specific immutable tag, and ideally the image digest (`@sha256:…`).
- **`imagePullPolicy: Always` with a mutable tag.** Compounds the above — every restart may
  change the code. Fix: pin the tag/digest and let the pull policy default.

### 6. Pod securityContext (readiness baseline, not a full security audit)
- **No `securityContext` / runs as root.** Absent `runAsNonRoot: true`, the container runs as
  UID 0, which most hardened clusters and admission policies reject at deploy time. Fix: set
  `runAsNonRoot: true`, a non-root `runAsUser`, and `allowPrivilegeEscalation: false`.
- **No dropped capabilities.** The container keeps the default Linux capability set it does not
  need. Fix: `securityContext.capabilities.drop: ["ALL"]`, adding back only what is required.

For deep security exploitability review (privileged mode, host namespaces, secrets, open
ports), that is a separate misconfiguration review — this skill covers only the securityContext
fields that gate a production deploy.
