All topics
DevOps · Learning hub

kubectl notes for developers

Master kubectl with a curated set of 3 developer notes — core concepts, patterns, and interview prep. Maintained by the DevRecall team.

Save this stack to your DevRecallMore DevOps notes
kubectl

Core Commands & Resource Management

kubectl: Core Commands & Resource Management kubectl is the Kubernetes command-line tool. It communicates with the cluster API server to manage workloads, inspe

kubectl: Core Commands & Resource Management

kubectl is the Kubernetes command-line tool. It communicates with the cluster API server to manage workloads, inspect resources, and apply configuration. All kubectl commands follow a pattern: kubectl <verb> <resource> [name] [flags].

Getting Resources

# List resources
kubectl get pods                          # pods in current namespace
kubectl get pods -n kube-system           # pods in specific namespace
kubectl get pods -A                       # all namespaces
kubectl get pods -o wide                  # extra info (node, IP)
kubectl get pods -o yaml                  # full YAML spec
kubectl get pods -o json                  # JSON output
kubectl get pods -l app=nginx             # filter by label
kubectl get pods --field-selector status.phase=Running

# Common resource types (short names work too)
kubectl get pods / po
kubectl get deployments / deploy
kubectl get services / svc
kubectl get configmaps / cm
kubectl get secrets
kubectl get namespaces / ns
kubectl get nodes / no
kubectl get ingress / ing
kubectl get persistentvolumes / pv
kubectl get persistentvolumeclaims / pvc
kubectl get statefulsets / sts
kubectl get daemonsets / ds
kubectl get replicasets / rs
kubectl get jobs
kubectl get cronjobs / cj
kubectl get serviceaccounts / sa

# Describe (detailed info + events)
kubectl describe pod my-pod
kubectl describe deployment my-deploy
kubectl describe node worker-1

# Watch for changes
kubectl get pods -w
kubectl get pods --watch

Creating & Applying Resources

# Apply manifest (create or update)
kubectl apply -f deployment.yaml
kubectl apply -f ./manifests/              # apply all files in directory
kubectl apply -f https://example.com/app.yaml

# Create (fails if already exists)
kubectl create deployment nginx --image=nginx:1.25
kubectl create service clusterip my-svc --tcp=80:80
kubectl create configmap my-config --from-literal=key=value
kubectl create configmap my-config --from-file=config.properties
kubectl create secret generic my-secret --from-literal=password=s3cr3t
kubectl create secret docker-registry regcred   --docker-server=registry.example.com   --docker-username=user   --docker-password=pass

# Quick pod for testing
kubectl run tmp --image=busybox --rm -it --restart=Never -- sh
kubectl run nginx --image=nginx --port=80

# Expose a deployment as a service
kubectl expose deployment nginx --port=80 --type=ClusterIP
kubectl expose deployment nginx --port=80 --type=LoadBalancer

Updating & Deleting

# Edit live resource
kubectl edit deployment my-deploy      # opens in $EDITOR
kubectl edit cm my-config

# Patch (non-interactive update)
kubectl patch deployment my-deploy -p '{"spec":{"replicas":3}}'
kubectl patch deployment my-deploy --type=merge   -p '{"spec":{"template":{"spec":{"terminationGracePeriodSeconds":30}}}}'

# Set image (rolling update)
kubectl set image deployment/my-deploy container=nginx:1.26

# Delete
kubectl delete pod my-pod
kubectl delete -f deployment.yaml
kubectl delete deployment my-deploy
kubectl delete pod my-pod --grace-period=0 --force   # force delete

# Delete all pods matching label
kubectl delete pods -l app=nginx

# Scale
kubectl scale deployment my-deploy --replicas=5

# Rollout
kubectl rollout status deployment/my-deploy
kubectl rollout history deployment/my-deploy
kubectl rollout undo deployment/my-deploy              # rollback
kubectl rollout undo deployment/my-deploy --to-revision=2

Labels & Annotations

# Add/update label
kubectl label pod my-pod env=production
kubectl label pod my-pod env=staging --overwrite

# Remove label (trailing dash)
kubectl label pod my-pod env-

# Add annotation
kubectl annotate deployment my-deploy kubernetes.io/change-cause="update to v2"

# Select by label
kubectl get pods -l app=nginx,env=production
kubectl get pods -l 'env in (production, staging)'
kubectl get pods -l 'env notin (development)'
kubectl

Namespaces, Contexts & Configuration

kubectl: Namespaces, Contexts & Configuration Namespaces Namespaces partition cluster resources between multiple users or teams. Most resources are namespace-sc

kubectl: Namespaces, Contexts & Configuration

Namespaces

Namespaces partition cluster resources between multiple users or teams. Most resources are namespace-scoped; a few (nodes, PVs, namespaces themselves) are cluster-scoped.

# List namespaces
kubectl get namespaces

# Create namespace
kubectl create namespace staging

# Work in a specific namespace
kubectl get pods -n staging
kubectl apply -f app.yaml -n staging

# Set default namespace for current context
kubectl config set-context --current --namespace=staging

# Delete namespace (deletes all resources inside!)
kubectl delete namespace staging

# Namespace-scoped vs cluster-scoped resources
kubectl api-resources --namespaced=true    # namespace-scoped
kubectl api-resources --namespaced=false   # cluster-scoped

Contexts & kubeconfig

A context is a named triple of (cluster, namespace, user). kubeconfig stores credentials and contexts — typically at ~/.kube/config.

# View current config
kubectl config view
kubectl config view --minify           # only current context
kubectl config view --raw              # decode base64 secrets

# Current context
kubectl config current-context

# List contexts
kubectl config get-contexts

# Switch context
kubectl config use-context prod-cluster

# Rename context
kubectl config rename-context old-name new-name

# Delete context
kubectl config delete-context old-context

# Merge kubeconfigs (combine cluster credentials)
KUBECONFIG=~/.kube/config:~/Downloads/new-cluster.yaml   kubectl config view --flatten > ~/.kube/config

# Use a different kubeconfig file
kubectl --kubeconfig=/path/to/config get pods
export KUBECONFIG=/path/to/config    # or set env var

ConfigMaps & Secrets

# ConfigMap from literal values
kubectl create configmap app-config   --from-literal=DB_HOST=postgres   --from-literal=DB_PORT=5432

# ConfigMap from file
kubectl create configmap nginx-conf --from-file=nginx.conf
kubectl create configmap app-props --from-env-file=.env

# View ConfigMap data
kubectl get configmap app-config -o yaml
kubectl describe configmap app-config

# Secret (values are base64-encoded in YAML, not encrypted)
kubectl create secret generic db-creds   --from-literal=username=admin   --from-literal=password=s3cr3t

# TLS secret
kubectl create secret tls my-tls   --cert=tls.crt --key=tls.key

# Decode secret value
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d

# Update secret (edit base64-encodes values in $EDITOR)
kubectl edit secret db-creds

RBAC

# List roles and bindings
kubectl get roles,rolebindings -n default
kubectl get clusterroles,clusterrolebindings

# Check permissions (as yourself)
kubectl auth can-i create pods
kubectl auth can-i delete deployments -n production

# Check permissions as another user/serviceaccount
kubectl auth can-i get pods --as=jane
kubectl auth can-i list secrets --as=system:serviceaccount:default:my-sa

# Create role + binding
kubectl create role pod-reader   --verb=get,list,watch   --resource=pods

kubectl create rolebinding read-pods   --role=pod-reader   --user=jane   --serviceaccount=default:my-sa
kubectl

Debugging, Scaling & Advanced Operations

kubectl: Debugging, Scaling & Advanced Operations Logs & Exec # Pod logs kubectl logs my-pod kubectl logs my-pod -c container-name # specific container in multi

kubectl: Debugging, Scaling & Advanced Operations

Logs & Exec

# Pod logs
kubectl logs my-pod
kubectl logs my-pod -c container-name       # specific container in multi-container pod
kubectl logs my-pod --previous              # logs from previous (crashed) container
kubectl logs my-pod -f                      # follow (stream)
kubectl logs my-pod --tail=100              # last 100 lines
kubectl logs my-pod --since=1h              # last hour
kubectl logs -l app=nginx                   # logs from all pods with label

# Exec into container
kubectl exec -it my-pod -- bash
kubectl exec -it my-pod -c sidecar -- sh   # specific container
kubectl exec my-pod -- ls /app             # one-off command

# Copy files
kubectl cp my-pod:/app/config.yaml ./config.yaml   # pod → local
kubectl cp ./data.sql my-pod:/tmp/data.sql          # local → pod

Port Forwarding & Proxy

# Forward local port to pod
kubectl port-forward pod/my-pod 8080:80
kubectl port-forward deployment/my-deploy 8080:80
kubectl port-forward service/my-svc 8080:80

# Access background
kubectl port-forward svc/postgres 5432:5432 &

# Proxy to API server (all kubectl API accessible at localhost:8001)
kubectl proxy
# then: curl http://localhost:8001/api/v1/namespaces/default/pods

# Debug with ephemeral containers (K8s 1.23+)
kubectl debug -it my-pod --image=busybox --target=app
kubectl debug node/worker-1 -it --image=ubuntu

Resource Usage & Events

# Resource usage (requires metrics-server)
kubectl top pods
kubectl top pods -n production -l app=nginx
kubectl top nodes

# Events (sorted by time)
kubectl get events --sort-by=.lastTimestamp
kubectl get events -n staging
kubectl get events --field-selector reason=BackOff

# Resource requests/limits
kubectl describe pod my-pod | grep -A3 Requests
kubectl describe node worker-1 | grep -A10 "Allocated resources"

JSONPath & Custom Output

# JSONPath queries
kubectl get pod my-pod -o jsonpath='{.status.podIP}'
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
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,NODE:.spec.nodeName

# Sort output
kubectl get pods --sort-by=.metadata.creationTimestamp
kubectl get pods --sort-by=.status.containerStatuses[0].restartCount

# All resources across a namespace (for audit)
kubectl api-resources --verbs=list --namespaced -o name |   xargs -I{} kubectl get {} -n default 2>/dev/null

Helpful Plugins & Tips

  • kubectx / kubens (ahmetb): instantly switch contexts and namespaces — brew install kubectx.

  • krew: kubectl plugin manager — kubectl krew install <plugin>.

  • kubectl neat: strips clutter from -o yaml output (managedFields, status) — great for diffing.

  • kubecolor: colorized kubectl output — drop-in alias for kubectl.

  • k9s: terminal UI for Kubernetes — real-time cluster view with logs, exec, and port-forward.

  • stern: tail logs from multiple pods simultaneously, with regex filtering.

  • kubectl diff -f file.yaml: preview what apply would change without applying.

  • kubectl explain pod.spec.containers: built-in API field documentation without leaving the terminal.

# Useful aliases
alias k=kubectl
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgd='kubectl get deploy'
alias kl='kubectl logs -f'
alias ke='kubectl exec -it'

# Shell completion
source <(kubectl completion bash)    # bash
source <(kubectl completion zsh)     # zsh
# or add to ~/.bashrc / ~/.zshrc

# Dry-run (validate without applying)
kubectl apply -f app.yaml --dry-run=client
kubectl apply -f app.yaml --dry-run=server   # validates against cluster API

# Generate YAML from imperative command
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deployment.yaml
kubectl expose deployment nginx --port=80 --dry-run=client -o yaml >> deployment.yaml

Keep your kubectl knowledge sharp.

Save this stack to your personal DevRecall — add your own notes, track what you're learning, and share what you know with the community.

Get started — free forever