Writing a Kubernetes Deployment by hand means remembering the nesting of selectors, pod templates, probes, and resource blocks — and getting any of it wrong produces an error that is often difficult to interpret. This builder generates a correct, apply-ready manifest — plus an optional Service — from a few inputs.
How it works
A Deployment wraps a pod template. The top-level selector.matchLabels must
match template.metadata.labels, which is how the Deployment tracks its pods.
The container spec carries the image, ports, env vars, resource bounds, and
health probes:
resources:
requests: { cpu: 250m, memory: 256Mi }
limits: { cpu: 500m, memory: 512Mi }
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
initialDelaySeconds: 10
readinessProbe:
httpGet: { path: /ready, port: 8080 }
CPU uses millicores (1000m = 1 core) and memory uses binary suffixes (Mi,
Gi). The readiness probe gates traffic; the liveness probe restarts a hung
container. The optional Service selects the same app label and exposes the
container port inside the cluster.
Understanding the generated structure
The manifest has three distinct sections that work together:
Deployment metadata and selector. The name and selector.matchLabels define the Deployment itself. The selector is immutable after creation — you cannot change it without deleting and recreating the Deployment. The builder uses a single app: <name> label, which is the conventional minimal label set.
Pod template. Inside spec.template, the metadata.labels must exactly match the selector. This is not optional — the Deployment finds its pods by matching these labels. The builder keeps them in sync automatically.
Container spec. The image, ports, environment variables, resource requests/limits, and probes all live under spec.template.spec.containers[0]. Multiple containers per pod are possible (sidecars) but the builder generates the most common single-container case.
Resource sizing guidelines
| Workload type | Example requests | Example limits |
|---|---|---|
| Lightweight API (Go, Rust) | 50m CPU, 64Mi RAM | 200m CPU, 128Mi RAM |
| Node.js / Python app | 100m CPU, 128Mi RAM | 500m CPU, 256Mi RAM |
| Java / JVM app | 250m CPU, 512Mi RAM | 1000m CPU, 1Gi RAM |
| Data processing batch | 500m CPU, 1Gi RAM | 2000m CPU, 2Gi RAM |
These are illustrative starting points. Tune based on actual profiling, not
guesses — kubectl top pods shows live consumption.
Tips for applying the manifest
Always set both requests and limits — without requests the scheduler can pack
pods badly, and without a memory limit a memory leak can starve the node. Keep
initialDelaySeconds long enough for slow-starting apps so the liveness probe
does not kill them during boot. A common mistake is setting initialDelaySeconds
to 5 seconds for a JVM app that takes 30 seconds to start, causing repeated
restart loops.
Apply with kubectl apply -f deployment.yaml, and use kubectl rollout status deployment/<name> to watch the rolling update complete. Roll back with
kubectl rollout undo deployment/<name> if needed.