Kubernetes Cheatsheet

Your complete quick reference for kubectl commands, YAML templates, and troubleshooting

Easy 10 min read Reference

Essential kubectl Commands

Quick reference for the most common kubectl operations

These commands cover 90% of daily Kubernetes work. Bookmark this page for fast access.

Cluster Management

cluster-info.sh
# Cluster info
kubectl cluster-info
kubectl get nodes
kubectl describe node NODE_NAME
kubectl top nodes

# Context & config
kubectl config view
kubectl config current-context
kubectl config use-context CONTEXT_NAME
kubectl config set-context --current --namespace=NAMESPACE

Resource Management

resource-crud.sh
# Create resources
kubectl create -f FILE.yaml
kubectl apply -f FILE.yaml
kubectl apply -f DIR/
kubectl create deployment NAME --image=IMAGE

# Get resources
kubectl get all
kubectl get pods -o wide
kubectl get svc --all-namespaces
kubectl get pods -l app=nginx

# Update resources
kubectl edit TYPE/NAME
kubectl patch TYPE NAME -p '{"spec":{"replicas":3}}'
kubectl set image deployment/NAME CONTAINER=IMAGE:TAG
kubectl scale deployment NAME --replicas=5

# Delete resources
kubectl delete -f FILE.yaml
kubectl delete TYPE NAME
kubectl delete pods --all
kubectl delete ns NAMESPACE

Pod Operations

pod-operations.sh
# Pod interaction
kubectl exec -it POD_NAME -- /bin/bash
kubectl exec POD_NAME -- COMMAND
kubectl attach POD_NAME -c CONTAINER
kubectl cp POD_NAME:/path/file ./local/path

# Pod logs
kubectl logs POD_NAME
kubectl logs -f POD_NAME
kubectl logs POD_NAME -c CONTAINER
kubectl logs --previous POD_NAME

# Port forwarding
kubectl port-forward POD_NAME 8080:80
kubectl port-forward svc/SERVICE 8080:80
kubectl port-forward deployment/NAME 8080:80
kubectl proxy

# Debug & describe
kubectl describe pod POD_NAME
kubectl get events --sort-by='.lastTimestamp'
kubectl debug POD_NAME -it --image=busybox
kubectl top pod POD_NAME

Deployments and Rollouts

deployments.sh
# Deployment management
kubectl create deployment NAME --image=IMAGE
kubectl expose deployment NAME --port=80 --type=LoadBalancer
kubectl autoscale deployment NAME --min=2 --max=10
kubectl rollout status deployment/NAME

# Rollout operations
kubectl rollout history deployment/NAME
kubectl rollout undo deployment/NAME
kubectl rollout undo deployment/NAME --to-revision=2
kubectl rollout pause/resume deployment/NAME

Pro Tips

  • Use -o yaml to get YAML output of any resource
  • Use --dry-run=client -o yaml to generate YAML templates
  • Use -w to watch resources for changes
  • Use --all-namespaces or -A for cluster-wide operations
  • Set default namespace: kubectl config set-context --current --namespace=NAMESPACE

Kubernetes Resources Reference

Workload Resources

Resource Short Name API Group Namespaced Kind
pods po core/v1 Yes Pod
deployments deploy apps/v1 Yes Deployment
replicasets rs apps/v1 Yes ReplicaSet
statefulsets sts apps/v1 Yes StatefulSet
daemonsets ds apps/v1 Yes DaemonSet
jobs job batch/v1 Yes Job
cronjobs cj batch/v1 Yes CronJob

Service and Networking

Resource Short Name API Group Namespaced Kind
services svc core/v1 Yes Service
ingresses ing networking.k8s.io/v1 Yes Ingress
networkpolicies netpol networking.k8s.io/v1 Yes NetworkPolicy
endpoints ep core/v1 Yes Endpoints
ingressclasses - networking.k8s.io/v1 No IngressClass

Config and Storage

Resource Short Name API Group Namespaced Kind
configmaps cm core/v1 Yes ConfigMap
secrets - core/v1 Yes Secret
persistentvolumes pv core/v1 No PersistentVolume
persistentvolumeclaims pvc core/v1 Yes PersistentVolumeClaim
storageclasses sc storage.k8s.io/v1 No StorageClass

Cluster Resources

Resource Short Name API Group Namespaced Kind
nodes no core/v1 No Node
namespaces ns core/v1 No Namespace
serviceaccounts sa core/v1 Yes ServiceAccount
roles - rbac.authorization.k8s.io/v1 Yes Role
clusterroles - rbac.authorization.k8s.io/v1 No ClusterRole
rolebindings - rbac.authorization.k8s.io/v1 Yes RoleBinding
clusterrolebindings - rbac.authorization.k8s.io/v1 No ClusterRoleBinding

Resource Quotas and Limits

Resource Short Name API Group Namespaced Kind
resourcequotas quota core/v1 Yes ResourceQuota
limitranges limits core/v1 Yes LimitRange
horizontalpodautoscalers hpa autoscaling/v2 Yes HorizontalPodAutoscaler
verticalpodautoscalers vpa autoscaling.k8s.io/v1 Yes VerticalPodAutoscaler
poddisruptionbudgets pdb policy/v1 Yes PodDisruptionBudget

YAML Templates

Pod Template

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
      name: http
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    livenessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 30
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5

Deployment Template

deployment-with-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: myapp:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: ENV_VAR
          value: "production"
        - name: SECRET_KEY
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: api-key
        volumeMounts:
        - name: config
          mountPath: /etc/config
      volumes:
      - name: config
        configMap:
          name: app-config
---
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: myapp
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

StatefulSet Template

statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-headless
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx-headless"
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 1Gi

Job and CronJob Template

job-cronjob.yaml
# Job
apiVersion: batch/v1
kind: Job
metadata:
  name: batch-job
spec:
  completions: 3
  parallelism: 2
  backoffLimit: 4
  template:
    spec:
      containers:
      - name: worker
        image: busybox
        command: ['sh', '-c', 'echo "Processing..." && sleep 30']
      restartPolicy: Never
---
# CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
  name: scheduled-job
spec:
  schedule: "*/5 * * * *"  # Every 5 minutes
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: task
            image: busybox
            command:
            - /bin/sh
            - -c
            - date; echo "Running scheduled task"
          restartPolicy: OnFailure

ConfigMap and Secret Template

configmap-secret.yaml
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  database_url: "postgres://localhost:5432/mydb"
  app.properties: |
    server.port=8080
    logging.level=INFO
---
# Secret
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  username: YWRtaW4=  # base64 encoded 'admin'
  password: cGFzc3dvcmQ=  # base64 encoded 'password'
---
# Or using stringData (automatically base64 encoded)
apiVersion: v1
kind: Secret
metadata:
  name: app-secret-string
type: Opaque
stringData:
  username: admin
  password: password

Ingress Template

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80

Troubleshooting Guide

Systematic Debugging Approach

Always start with kubectl describe and kubectl logs before diving deeper. Most issues are caught at this level.

Pod Not Starting

  1. Check pod status: kubectl get pod POD_NAME -o wide
  2. Describe pod for events: kubectl describe pod POD_NAME
  3. Check logs: kubectl logs POD_NAME --previous
  4. Check resource availability: kubectl describe nodes / kubectl top nodes
  5. Check image pull: kubectl get events --field-selector involvedObject.name=POD_NAME

Service Not Accessible

  1. Check service endpoints: kubectl get endpoints SERVICE_NAME
  2. Test service DNS: kubectl run tmp --image=busybox -it --rm -- nslookup SERVICE_NAME
  3. Check service selector: kubectl get svc SERVICE_NAME -o yaml
  4. Test connectivity: kubectl run tmp --image=nicolaka/netshoot -it --rm -- curl SERVICE_NAME:PORT

Common Issues and Solutions

Issue Possible Cause Solution
ImagePullBackOff Image not found or auth failed Check image name, registry auth, imagePullSecrets
CrashLoopBackOff Application crashing Check logs, fix application error, check resources
Pending No resources or node selector Check node resources, PVC binding, node affinity
OOMKilled Out of memory Increase memory limits, optimize application
Evicted Node pressure Check node disk/memory pressure, clean up

Debugging Commands

debug-commands.sh
# Resource investigation
kubectl get events --sort-by='.lastTimestamp'
kubectl get pods --all-namespaces -o wide
kubectl describe node NODE_NAME | grep -A 5 "Allocated resources"
kubectl top pods --all-namespaces

# Network debugging
kubectl exec -it POD -- nslookup kubernetes.default
kubectl exec -it POD -- ping SERVICE_NAME
kubectl exec -it POD -- curl -v http://SERVICE:PORT
kubectl get networkpolicies

# Storage issues
kubectl get pv
kubectl get pvc --all-namespaces
kubectl describe pvc PVC_NAME
kubectl get storageclass

# RBAC debugging
kubectl auth can-i VERB RESOURCE
kubectl auth can-i --list
kubectl get rolebindings,clusterrolebindings --all-namespaces
kubectl describe sa SERVICE_ACCOUNT

JSONPath and Output Formatting

JSONPath Examples

jsonpath-queries.sh
# Basic JSONPath
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}'
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'

# Custom columns
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.capacity.cpu
kubectl get pv -o custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage

# Filtering & sorting
kubectl get pods --field-selector status.phase=Running
kubectl get events --sort-by='.metadata.creationTimestamp'
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'

# Complex queries
kubectl get pods -o jsonpath='{.items[?(@.status.phase!="Running")].metadata.name}'
kubectl get svc -o jsonpath='{.items[?(@.spec.type=="LoadBalancer")].status.loadBalancer.ingress[0].ip}'
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'

Output Formats

Format Flag Description Example
Wide -o wide Additional columns kubectl get pods -o wide
YAML -o yaml YAML format kubectl get pod nginx -o yaml
JSON -o json JSON format kubectl get pods -o json
Name only -o name Resource type/name kubectl get pods -o name
Custom columns -o custom-columns= Custom output kubectl get pods -o custom-columns=NAME:.metadata.name
Go template -o go-template= Go template format kubectl get pods -o go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'

Shortcuts and Productivity Tips

kubectl Aliases

kubectl-aliases.sh
# Basic aliases
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgd='kubectl get deployment'
alias kaf='kubectl apply -f'
alias kdel='kubectl delete'
alias kdes='kubectl describe'
alias klog='kubectl logs'
alias kex='kubectl exec -it'

# Namespace aliases
alias kgpa='kubectl get pods --all-namespaces'
alias kgsw='kubectl get svc --all-namespaces -o wide'
alias kn='kubectl config set-context --current --namespace'

# Quick commands
alias krun='kubectl run tmp --image=busybox -it --rm --restart=Never --'
alias kdebug='kubectl run debug --image=nicolaka/netshoot -it --rm --restart=Never --'
alias kport='kubectl port-forward'
alias ktop='kubectl top'

# Context management
alias kctx='kubectl config current-context'
alias kuse='kubectl config use-context'

# Resource watching
alias kwatch='kubectl get pods -w'

Shell Completion

shell-completion.sh
# Bash
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

# Zsh
source <(kubectl completion zsh)
echo "source <(kubectl completion zsh)" >> ~/.zshrc

# Fish
kubectl completion fish | source
echo "kubectl completion fish | source" >> ~/.config/fish/config.fish

# PowerShell
kubectl completion powershell | Out-String | Invoke-Expression

Quick Tips

Dry Run

--dry-run=client -o yaml - Generate YAML without creating

Force Delete

--grace-period=0 --force - Force delete stuck resources

All Namespaces

-A or --all-namespaces - Work across all namespaces

Watch Changes

-w or --watch - Watch for resource changes

Label Selector

-l app=nginx - Filter by labels

Preview Changes

kubectl diff -f FILE.yaml - See what would change before applying

Useful Tools

k9s

Terminal UI for managing Kubernetes clusters interactively

kubectx / kubens

Fast context and namespace switching

stern

Multi-pod and container log tailing

krew

kubectl plugin manager

kustomize

Template-free configuration management

Helm

The package manager for Kubernetes

Power User Tips

  • Use kubectl explain RESOURCE for inline documentation
  • Set KUBE_EDITOR environment variable for preferred editor
  • Use kubectl diff -f FILE.yaml to preview changes
  • Use kubectl api-resources to list all available resources
  • Use kubectl api-versions to check available API versions

Practice Problems

Easy Deploy an Nginx Pod

Create a single Nginx pod using kubectl without writing a YAML file, then verify it is running.

Use kubectl run with the --image flag, then check with kubectl get pods.

# Create the pod
kubectl run nginx --image=nginx:1.21

# Verify it is running
kubectl get pods nginx
kubectl describe pod nginx

Easy Generate YAML Without Creating

Generate a Deployment YAML manifest for an app called "web" using the httpd image, with 3 replicas, without actually creating it.

Combine --dry-run=client with -o yaml to output the manifest.

kubectl create deployment web \
  --image=httpd \
  --replicas=3 \
  --dry-run=client -o yaml

Medium Debug a CrashLoopBackOff Pod

A pod named "broken-app" is in CrashLoopBackOff. List the sequence of commands you would use to diagnose and identify the root cause.

Start with describe, then check logs (current and previous), then check events.

# Step 1: Get pod status details
kubectl describe pod broken-app

# Step 2: Check current logs
kubectl logs broken-app

# Step 3: Check previous container logs
kubectl logs broken-app --previous

# Step 4: Check events
kubectl get events --field-selector involvedObject.name=broken-app

# Step 5: If needed, run a debug container
kubectl debug broken-app -it --image=busybox

Hard Extract Specific Data with JSONPath

Write a single kubectl command that lists all pods NOT in Running state, showing their name, namespace, and current phase in a tabular format.

Use -o jsonpath with a filter expression ?(@.status.phase!="Running") and range iteration.

# Using JSONPath with range and filter
kubectl get pods -A -o jsonpath='{range .items[?(@.status.phase!="Running")]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'

# Alternative: using custom-columns with field-selector
kubectl get pods -A \
  --field-selector status.phase!=Running \
  -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,STATUS:.status.phase