YAML in Kubernetes — Writing Kubernetes Manifests
Kubernetes configurations are YAML files called manifests. Here's how Kubernetes YAML is structured, the required fields for common resources (Deployment, Service, ConfigMap),...
Kubernetes uses YAML for all resource definitions — called manifests. Every Kubernetes object (Pod, Deployment, Service, ConfigMap) is described as a YAML file and applied with kubectl apply -f.
Use the YAML to JSON Converter to validate your Kubernetes YAML before applying.
Required fields in every Kubernetes manifest
All Kubernetes resources share four required top-level fields:
apiVersion: apps/v1 # API group and version
kind: Deployment # resource type
metadata:
name: my-app # resource name (must be unique in namespace)
namespace: default # optional, defaults to "default"
spec: # resource-specific configuration
# ...
Deployment manifest
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
namespace: production
labels:
app: api-server
team: backend
spec:
replicas: 3
selector:
matchLabels:
app: api-server # must match template labels
template:
metadata:
labels:
app: api-server # must match selector
spec:
containers:
- name: api
image: myregistry/api:v1.2.3
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secrets
key: url
resources:
requests:
cpu: 100m # 0.1 CPU core
memory: 128Mi # 128 megabytes
limits:
cpu: 500m
memory: 512Mi
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 30
Service manifest
apiVersion: v1
kind: Service
metadata:
name: api-server
namespace: production
spec:
selector:
app: api-server # routes traffic to pods with this label
ports:
- protocol: TCP
port: 80 # service port (cluster-internal)
targetPort: 3000 # container port
type: ClusterIP # internal only (default)
Service types:
ClusterIP— internal cluster access onlyNodePort— expose on each node’s IP at a static portLoadBalancer— provision a cloud load balancerExternalName— map to an external DNS name
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
# Key-value pairs:
NODE_ENV: production
LOG_LEVEL: info
# Multi-line value (for config files):
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://backend:3000;
}
}
app-config.json: |
{
"featureFlags": {
"newUI": true,
"betaFeatures": false
}
}
Secret manifest
apiVersion: v1
kind: Secret
metadata:
name: db-secrets
namespace: production
type: Opaque
data:
# Values must be base64 encoded:
username: dXNlcm5hbWU= # echo -n 'username' | base64
password: cGFzc3dvcmQ= # echo -n 'password' | base64
url: cG9zdGdyZXNxbDovLy4uLg==
Referencing a secret in a Deployment:
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secrets
key: url
Multi-document YAML files
Use --- to separate multiple resources in one file:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
# ...
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
Apply all at once: kubectl apply -f all-resources.yaml
Common YAML mistakes in Kubernetes
Indentation errors
# WRONG: selector must be under spec
apiVersion: apps/v1
kind: Deployment
spec:
selector: # indentation error!
matchLabels:
app: web
# CORRECT:
apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app: web
String vs integer ports
# YAML might parse port as integer or string:
containerPort: 3000 # integer — correct
containerPort: "3000" # string — may cause errors in some fields
Label mismatches
# WRONG: selector doesn't match template labels
spec:
selector:
matchLabels:
app: web # looks for this label
template:
metadata:
labels:
app: website # different label!
The pod template’s labels must include all labels specified in selector.matchLabels.
Applying and managing manifests
# Apply (create or update):
kubectl apply -f deployment.yaml
kubectl apply -f ./k8s/ # apply all YAML in directory
# Check what would change (dry run):
kubectl apply -f deployment.yaml --dry-run=client
# Delete:
kubectl delete -f deployment.yaml
# View current config:
kubectl get deployment api-server -o yaml
# Diff current vs file:
kubectl diff -f deployment.yaml
Related tools
- YAML to JSON Converter — validate and convert YAML
- YAML Syntax Guide — YAML syntax reference
- YAML Anchors and Aliases — reduce Kubernetes YAML repetition
Related posts
- YAML vs JSON: Which to Use When (and Why It Matters) — JSON is for machines, YAML is for humans, and choosing the wrong one quietly cos…
- YAML Anchors and Aliases — Reusing Values with & and * — YAML anchors (&) define a reusable value; aliases (*) reference it. This elimina…
- YAML Config Best Practices — Structure, Validation, and Environment Variables — YAML is the dominant format for configuration files in modern software. Here's h…
- YAML Syntax Guide — Indentation, Types, and Common Patterns — YAML syntax uses indentation to define structure. Here's how YAML handles scalar…
Related tool
Convert between YAML and JSON formats with full fidelity.
Written by Mian Ali Khalid. Part of the Data & Format pillar.