Kubernetes Skill
When to activate
- Writing Kubernetes manifests (Deployments, Services, ConfigMaps, Secrets, Ingress)
- Configuring Helm charts or values files for an application
- Debugging a failing Pod, CrashLoopBackOff, or OOMKilled container
- Setting up horizontal pod autoscaling (HPA) or vertical pod autoscaling (VPA)
- Defining resource requests and limits for containers
- Writing or reviewing RBAC policies (Roles, ClusterRoles, RoleBindings)
- Setting up liveness, readiness, and startup probes
- Configuring persistent volumes and persistent volume claims
- Writing network policies to control pod-to-pod traffic
- Setting up namespaces and multi-tenant isolation
When NOT to use
- Docker Compose setups that aren't being migrated to Kubernetes
- Serverless (Cloud Run, Lambda, Fargate) — different deployment model
- Simple single-container apps that don't need orchestration
- Local development environments where Docker alone suffices
- Nomad, Mesos, or other non-Kubernetes orchestrators
Instructions
Manifest structure
Always set these fields in every Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-name
namespace: production # Always explicit — never rely on default namespace
labels:
app: app-name
version: "1.0.0"
spec:
replicas: 3
selector:
matchLabels:
app: app-name
template:
metadata:
labels:
app: app-name
version: "1.0.0"
spec:
containers:
- name: app-name
image: registry/app-name:tag # Never use :latest in production
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
Resource requests and limits
- Always set both
requests and limits — never omit
requests = guaranteed resources (used for scheduling)
limits = maximum allowed (OOMKilled if memory exceeded)
- CPU limits are optional in clusters with CPU throttling disabled — but memory limits are mandatory
- Start conservative: requests at ~25% of expected, limits at 2x expected, then tune with actual metrics
Health probes
All production containers must have probes:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
livenessProbe failure → container restart
readinessProbe failure → removed from Service load balancer (no traffic, no restart)
- Never point both at the same endpoint — readiness should check dependencies, liveness should not
Secrets management
- Never put secrets in ConfigMaps — use Secrets
- Never commit Secret manifests with real values — use sealed-secrets, external-secrets-operator, or Vault
- Reference secrets as env vars, not volumes, unless the app specifically requires file-based secrets:
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
Namespace conventions
default namespace: dev/testing only
- Production workloads always in named namespaces
- Use
ResourceQuota and LimitRange on every production namespace
- RBAC: developers get edit in dev namespaces, view in production
Common CrashLoopBackOff causes and fixes
- Missing env var → check
kubectl describe pod Events section
- Failed healthcheck → logs show the real error, probe just detects it
- OOMKilled → increase memory limit or fix memory leak
- Image pull error → check imagePullPolicy and registry credentials
- Init container failure →
kubectl logs pod-name -c init-container-name
Example
User: Deploy a FastAPI app with PostgreSQL connection, 3 replicas, resource limits, and health checks.
Expected output structure:
- Namespace manifest
- Secret for
DATABASE_URL
- Deployment with 3 replicas, resource requests/limits, liveness + readiness probes pointing to
/healthz and /ready
- Service (ClusterIP) exposing port 80 → container port 8080
- HorizontalPodAutoscaler targeting 70% CPU utilization, min 3 / max 10 replicas
1---2name: kubernetes3description: Kubernetes manifests, resource limits, health probes, secrets, RBAC, HPA, CrashLoopBackOff diagnosis4---56# Kubernetes Skill78## When to activate9- Writing Kubernetes manifests (Deployments, Services, ConfigMaps, Secrets, Ingress)10- Configuring Helm charts or values files for an application11- Debugging a failing Pod, CrashLoopBackOff, or OOMKilled container12- Setting up horizontal pod autoscaling (HPA) or vertical pod autoscaling (VPA)13- Defining resource requests and limits for containers14- Writing or reviewing RBAC policies (Roles, ClusterRoles, RoleBindings)15- Setting up liveness, readiness, and startup probes16- Configuring persistent volumes and persistent volume claims17- Writing network policies to control pod-to-pod traffic18- Setting up namespaces and multi-tenant isolation1920## When NOT to use21- Docker Compose setups that aren't being migrated to Kubernetes22- Serverless (Cloud Run, Lambda, Fargate) — different deployment model23- Simple single-container apps that don't need orchestration24- Local development environments where Docker alone suffices25- Nomad, Mesos, or other non-Kubernetes orchestrators2627## Instructions2829### Manifest structure30Always set these fields in every Deployment:31```yaml32apiVersion: apps/v133kind: Deployment34metadata:35 name: app-name36 namespace: production # Always explicit — never rely on default namespace37 labels:38 app: app-name39 version: "1.0.0"40spec:41 replicas: 342 selector:43 matchLabels:44 app: app-name45 template:46 metadata:47 labels:48 app: app-name49 version: "1.0.0"50 spec:51 containers:52 - name: app-name53 image: registry/app-name:tag # Never use :latest in production54 resources:55 requests:56 cpu: "100m"57 memory: "128Mi"58 limits:59 cpu: "500m"60 memory: "512Mi"61```6263### Resource requests and limits64- Always set both `requests` and `limits` — never omit65- `requests` = guaranteed resources (used for scheduling)66- `limits` = maximum allowed (OOMKilled if memory exceeded)67- CPU limits are optional in clusters with CPU throttling disabled — but memory limits are mandatory68- Start conservative: requests at ~25% of expected, limits at 2x expected, then tune with actual metrics6970### Health probes71All production containers must have probes:72```yaml73livenessProbe:74 httpGet:75 path: /healthz76 port: 808077 initialDelaySeconds: 1578 periodSeconds: 2079 failureThreshold: 38081readinessProbe:82 httpGet:83 path: /ready84 port: 808085 initialDelaySeconds: 586 periodSeconds: 1087 failureThreshold: 388```89- `livenessProbe` failure → container restart90- `readinessProbe` failure → removed from Service load balancer (no traffic, no restart)91- Never point both at the same endpoint — readiness should check dependencies, liveness should not9293### Secrets management94- Never put secrets in ConfigMaps — use Secrets95- Never commit Secret manifests with real values — use sealed-secrets, external-secrets-operator, or Vault96- Reference secrets as env vars, not volumes, unless the app specifically requires file-based secrets:97```yaml98env:99 - name: DATABASE_URL100 valueFrom:101 secretKeyRef:102 name: app-secrets103 key: database-url104```105106### Namespace conventions107- `default` namespace: dev/testing only108- Production workloads always in named namespaces109- Use `ResourceQuota` and `LimitRange` on every production namespace110- RBAC: developers get edit in dev namespaces, view in production111112### Common CrashLoopBackOff causes and fixes1131. Missing env var → check `kubectl describe pod` Events section1142. Failed healthcheck → logs show the real error, probe just detects it1153. OOMKilled → increase memory limit or fix memory leak1164. Image pull error → check imagePullPolicy and registry credentials1175. Init container failure → `kubectl logs pod-name -c init-container-name`118119## Example120121**User:** Deploy a FastAPI app with PostgreSQL connection, 3 replicas, resource limits, and health checks.122123**Expected output structure:**124- Namespace manifest125- Secret for `DATABASE_URL`126- Deployment with 3 replicas, resource requests/limits, liveness + readiness probes pointing to `/healthz` and `/ready`127- Service (ClusterIP) exposing port 80 → container port 8080128- HorizontalPodAutoscaler targeting 70% CPU utilization, min 3 / max 10 replicas129130---