Key Takeaways
- ✓Every Kubernetes manifest requires apiVersion, kind, metadata.name and spec
- ✓6 resource types covered: Pod, Deployment, Service, ConfigMap, Secret, Ingress
TL;DR: This guide gives you the essential YAML templates for Pod, Deployment, Service, ConfigMap, Secret, and Ingress. Copy, adapt, deploy. Each block includes required fields and common options you'll use daily in production.
This skill is at the heart of the LFD459 Kubernetes for Developers training.
Basic Manifest Structure
Every Kubernetes manifest follows this structure. Memorize it:
apiVersion: v1|apps/v1|networking.k8s.io/v1
kind: Pod|Deployment|Service|ConfigMap|Secret|Ingress
metadata:
name: my-resource # Required
namespace: default # Optional, default if omitted
labels: # Recommended for filtering
app: my-app
spec:
# Kind-specific configuration
| Field | Description | Required |
|---|---|---|
apiVersion | Kubernetes API version | Yes |
kind | Resource type | Yes |
metadata.name | Unique name in namespace | Yes |
metadata.labels | Key-value pairs for filtering | No |
spec | Resource configuration | Yes |
Key takeaway: Always verify apiVersion with kubectl api-resources | grep . Versions change between Kubernetes releases.
Pod: Basic Unit
You rarely create Pods directly. Prefer Deployments. But here's the reference syntax:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 3
periodSeconds: 10
Quick command: kubectl run nginx --image=nginx:1.27 --dry-run=client -o yaml > pod.yaml
Deployment: Declarative Management
82% of container users run Kubernetes in production (CNCF Annual Survey 2025). You'll use Deployments in 90% of cases.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-backend
labels:
app: api
spec:
replicas: 3
selector:
matchLabels:
app: api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: my-registry/api:v2.1.0
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "1000m"
| Strategy | Usage | Parameters |
|---|---|---|
RollingUpdate | Zero-downtime (default) | maxSurge, maxUnavailable |
Recreate | Stateful apps, version incompatibility | None |
Key takeaway: Always define resources. Without limits, your pods can consume all node memory and trigger OOMKill.
For deeper learning about containerized application design, consult our complete guide.
Service: Network Exposure
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
type: ClusterIP # ClusterIP | NodePort | LoadBalancer
selector:
app: api # Must match Pod labels
ports:
- port: 80 # Exposed port
targetPort: 8080 # Container port
protocol: TCP
Service Types
| Type | Accessibility | Use Case |
|---|---|---|
ClusterIP | Internal cluster only | Inter-service communication |
NodePort | Node_IP:30000-32767 | Testing, direct access |
LoadBalancer | External IP (cloud) | Production, external traffic |
ExternalName | DNS alias | External services |
Check your endpoints: kubectl get endpoints api-service
ConfigMap and Secret
ConfigMap for Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
LOG_LEVEL: "info"
config.json: |
{
"feature_flags": {
"new_ui": true
}
}
Secret for Sensitive Data
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData: # Plain text, automatically encoded
username: admin
password: "p@ssw0rd!"
data: # Pre-encoded Base64
api-key: YXBpLWtleS12YWx1ZQ==
Injection into a Pod:
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-credentials
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
Key takeaway: Secrets are not encrypted by default. Enable at-rest encryption or use an external manager (Vault, Sealed Secrets).
Consult the essential kubectl commands to manipulate your ConfigMaps and Secrets.
Ingress: HTTP Routing
Traefik has over 3.4 billion downloads (Traefik Labs). 70% of organizations use Helm to deploy their Ingress Controllers (Orca Security 2025).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 80
| pathType | Behavior |
|---|---|
Prefix | /api matches /api, /api/users, /api/v1 |
Exact | /api matches only /api |
ImplementationSpecific | Depends on controller |
To master Helm with your Ingress, refer to the Helm Charts cheatsheet.
Common Errors and Fixes
Selector Mismatch
# ❌ ERROR: selector doesn't match template.labels
spec:
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: backend # Should be "api"
Port Confusion
# ❌ ERROR: targetPort != containerPort
# Service
spec:
ports:
- port: 80
targetPort: 3000 # Container listens on 8080
# Pod
spec:
containers:
- ports:
- containerPort: 8080 # Mismatch!
Missing Resources
67% of organizations delay their Kubernetes deployments due to security issues (Mend.io). Always define your limits.
# ✅ CORRECT: requests and limits defined
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
Key takeaway: Validate your manifests before deployment with kubectl apply --dry-run=server -f manifest.yaml
Quick Validation Commands
# Check YAML syntax
kubectl apply --dry-run=client -f deployment.yaml
# Server-side validation (checks quotas, policies)
kubectl apply --dry-run=server -f deployment.yaml
# Generate template from command
kubectl create deployment nginx --image=nginx:1.27 \
--dry-run=client -o yaml > deployment.yaml
# Diff before applying
kubectl diff -f deployment.yaml
# Apply with tracking
kubectl apply -f deployment.yaml && kubectl rollout status deployment/nginx
For deeper learning about monitoring your applications, 75% of teams use Prometheus and Grafana (Grafana Labs).
Additional Resources
Explore the Complete Kubernetes Training Guide and the Kubernetes Security section to secure your manifests.
Put It Into Practice
Want to master YAML manifest creation in real conditions and prepare for CKAD certification? For deeper learning, consult our Kubernetes software engineer training. For deeper exploration, consult our Kubernetes system administrator.
- LFD459 Kubernetes for Developers training: 3 days to create, deploy and manage applications on Kubernetes
- LFS458 Kubernetes Administration training: 4 days to administer your clusters in production
- Kubernetes Fundamentals: 1 day to discover essential concepts