kubectl
← Home

kubectl - Resource Management

Quick navigation tip: use Ctrl/Cmd + F to jump to sections. Key terms: apply, create, edit, patch, set, delete, diff, ssa, replace, wait.

Creating and applying resources (apply/create)

Official documentation Declarative object management ↗

# Apply configuration from file
kubectl apply -f deployment.yaml

# Apply all yaml files from directory
kubectl apply -f ./configs/

# Apply configuration from URL
kubectl apply -f https://example.com/config.yaml

# Create namespace
kubectl create namespace <namespace-name>
kubectl create ns <namespace-name>

# Create deployment imperatively
kubectl create deployment <name> --image=<image>

# Create service
kubectl create service clusterip <name> --tcp=80:8080

# Create configmap from file
kubectl create configmap <name> --from-file=config.txt

# Create configmap from literal
kubectl create configmap <name> --from-literal=key=value

# Create secret from literal
kubectl create secret generic <name> --from-literal=password=secret123

# Create secret for docker registry
kubectl create secret docker-registry <name> --docker-server=<server> --docker-username=<user> --docker-password=<pass>

Editing resources (edit)

Official documentation kubectl edit ↗

# Edit deployment in default editor
kubectl edit deployment <deployment-name>

# Edit service
kubectl edit service <service-name>

# Edit configmap
kubectl edit configmap <configmap-name>

# Edit in specific namespace
kubectl edit deployment <deployment-name> -n <namespace>

# Use specific editor
KUBE_EDITOR="nano" kubectl edit deployment <deployment-name>

Patching resources (patch)

Official documentation Updating objects with patch ↗

# Change replica count via patch
kubectl patch deployment <deployment-name> -p '{"spec":{"replicas":3}}'

# Change container image
kubectl patch deployment <deployment-name> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container>","image":"nginx:1.21"}]}}}}'

# Merge patch format
kubectl patch deployment <deployment-name> --type=merge -p '{"spec":{"replicas":5}}'

# JSON patch format
kubectl patch deployment <deployment-name> --type=json -p='[{"op":"replace","path":"/spec/replicas","value":2}]'

# Add environment variable
kubectl patch deployment <deployment-name> --type=json -p='[{"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"NEW_VAR","value":"value"}}]'

# Change service type
kubectl patch svc <service-name> -p '{"spec":{"type":"NodePort"}}'

Quick resource modification (set)

Official documentation kubectl set ↗

# Change container image
kubectl set image deployment/<deployment-name> <container-name>=nginx:1.21

# Change image for all containers
kubectl set image deployment/<deployment-name> *=nginx:1.21

# Change image and explicitly record the change reason in an annotation
kubectl set image deployment/<deployment-name> nginx=nginx:1.21
kubectl annotate deployment/<deployment-name> kubernetes.io/change-cause="nginx=nginx:1.21" --overwrite

# Add environment variable
kubectl set env deployment/<deployment-name> ENV_VAR=value

# Add multiple variables
kubectl set env deployment/<deployment-name> VAR1=value1 VAR2=value2

# Remove environment variable
kubectl set env deployment/<deployment-name> ENV_VAR-

# Set variable from secret
kubectl set env deployment/<deployment-name> --from=secret/mysecret

# Set variable from configmap
kubectl set env deployment/<deployment-name> --from=configmap/myconfig

# Change resource limits
kubectl set resources deployment/<deployment-name> -c=nginx --limits=cpu=200m,memory=512Mi

# Change resource requests
kubectl set resources deployment/<deployment-name> -c=nginx --requests=cpu=100m,memory=256Mi

# Change service account
kubectl set serviceaccount deployment/<deployment-name> myserviceaccount

# Change selector for service
kubectl set selector service/<service-name> app=myapp,tier=frontend

Deleting resources (delete)

Official documentation kubectl delete ↗

# Delete pod
kubectl delete pod <pod-name>

# Delete deployment
kubectl delete deployment <deployment-name>

# Delete service
kubectl delete service <service-name>

# Delete resources from file
kubectl delete -f deployment.yaml

# Delete all resources by label
kubectl delete pods -l app=myapp

# Delete namespace (and all resources in it)
kubectl delete namespace <namespace-name>

# Force delete pod: use only when normal deletion is stuck
kubectl delete pod <pod-name> --force --grace-period=0

# Delete all pods in namespace
kubectl delete pods --all -n <namespace>

Comparing configurations (diff)

Official documentation kubectl diff ↗

# Compare local file with current state in cluster
kubectl diff -f deployment.yaml

# Compare all files from directory
kubectl diff -f ./configs/

# Compare configuration from URL
kubectl diff -f https://example.com/config.yaml

# Compare using kustomize
kubectl diff -k ./overlays/production/

# Show diff before apply (useful in CI/CD)
kubectl diff -f deployment.yaml && kubectl apply -f deployment.yaml

# Diff with server-side
kubectl diff -f deployment.yaml --server-side

# Check configuration without applying (dry-run + diff)
kubectl apply -f deployment.yaml --dry-run=server
kubectl apply -f deployment.yaml --dry-run=client

# Validate file without applying
kubectl apply --validate=true --dry-run=client -f deployment.yaml

# Check what will change on delete
kubectl delete -f deployment.yaml --dry-run=client

Server-side apply (SSA)

Official documentation Server-Side Apply ↗

# Apply using server-side apply — preferred for GitOps and multi-actor environments
kubectl apply -f deployment.yaml --server-side

# SSA with a named field manager (label who owns each field)
kubectl apply -f deployment.yaml --server-side --field-manager=argocd

# Force-take ownership of conflicting fields from another field manager
kubectl apply -f deployment.yaml --server-side --force-conflicts

# Dry-run with server-side logic (validated by the API server)
kubectl apply -f deployment.yaml --server-side --dry-run=server

# Diff current cluster state vs local file using server-side logic
kubectl diff -f deployment.yaml --server-side

# Inspect field managers on a resource
kubectl get deployment my-deploy -o json | jq '.metadata.managedFields'

# Clean up managedFields from output for readability
kubectl get deployment my-deploy -o json | jq 'del(.metadata.managedFields)'
# or with the neat plugin:
kubectl neat get deployment my-deploy -o yaml

# Remove the legacy last-applied-configuration annotation after migrating to SSA
kubectl annotate deployment my-deploy kubectl.kubernetes.io/last-applied-configuration-

# Apply a whole directory with SSA
kubectl apply -f ./manifests/ --server-side --field-manager=platform-team

# SSA vs client-side apply:
# Client-side: tracks changes via kubectl.kubernetes.io/last-applied-configuration annotation
# Server-side: tracks ownership via .metadata.managedFields — safe for concurrent managers
# SSA is recommended when multiple tools (ArgoCD, Helm, kubectl) touch the same object

Replace and attach to resources (replace/attach)

Official documentation kubectl replace ↗ kubectl attach ↗

# Full resource replacement from file
kubectl replace -f deployment.yaml

# Force replacement (delete and recreate)
kubectl replace --force -f deployment.yaml

# Replace from stdin
cat deployment.yaml | kubectl replace -f -

# Attach to stdout/stderr of running container
kubectl attach <pod-name>

# Interactive attach to container (stdin + tty)
kubectl attach -it <pod-name>

# Attach to specific container
kubectl attach <pod-name> -c <container-name>

# Attach in specific namespace
kubectl attach <pod-name> -n <namespace>

# Convert config between API versions (requires the separate kubectl-convert plugin)
kubectl convert -f deployment.yaml --output-version apps/v1

# View completion for bash/zsh
kubectl completion bash
kubectl completion zsh

# Enable autocompletion (add to .bashrc/.zshrc)
# source <(kubectl completion bash)
# source <(kubectl completion zsh)

# Create alias for kubectl
# alias k=kubectl
# complete -o default -F __start_kubectl k

Waiting for conditions (wait)

Official documentation kubectl wait ↗

# Wait for pod to become Ready
kubectl wait pod/<pod-name> --for=condition=Ready

# Wait for pod with timeout (default is 30s)
kubectl wait pod/<pod-name> --for=condition=Ready --timeout=120s

# Wait for all pods with a label to be ready
kubectl wait pods -l app=myapp --for=condition=Ready --timeout=60s

# Wait for deployment to finish rollout (all replicas available)
kubectl wait deployment/<deploy-name> --for=condition=Available --timeout=300s

# Wait for job to complete
kubectl wait job/<job-name> --for=condition=Complete --timeout=120s

# Wait for job to fail
kubectl wait job/<job-name> --for=condition=Failed --timeout=60s

# Wait for resource deletion
kubectl wait pod/<pod-name> --for=delete --timeout=60s

# Wait for all pods with a label to be deleted
kubectl wait pods -l app=myapp --for=delete --timeout=120s

# Wait for node to become Ready
kubectl wait node/<node-name> --for=condition=Ready --timeout=300s

# Wait for all nodes to become Ready
kubectl wait nodes --all --for=condition=Ready --timeout=300s

# Wait for CRD to be established
kubectl wait crd/<crd-name> --for=condition=Established --timeout=60s

# Wait in a specific namespace
kubectl wait pod/<pod-name> -n <namespace> --for=condition=Ready --timeout=60s

# Wait for multiple resources of the same type (by label, all namespaces)
kubectl wait pods -l tier=backend --for=condition=Ready --all-namespaces --timeout=120s

# Wait for PVC to be Bound
kubectl wait pvc/<pvc-name> --for=jsonpath='{.status.phase}'=Bound --timeout=60s

# Wait on arbitrary field via jsonpath (k8s >= 1.23)
kubectl wait deployment/<deploy-name> \
  --for=jsonpath='{.status.readyReplicas}'=3 --timeout=120s

# CI/CD usage example
kubectl apply -f deployment.yaml
kubectl wait deployment/myapp --for=condition=Available --timeout=300s
echo "Deploy successful"

# Check multiple conditions sequentially
kubectl wait pod/<pod-name> --for=condition=Initialized --timeout=30s
kubectl wait pod/<pod-name> --for=condition=Ready --timeout=120s
kubectl wait pod/<pod-name> --for=condition=ContainersReady --timeout=120s

# Available pod conditions:
#   Initialized       — all init containers have completed
#   Ready             — pod is ready to serve traffic
#   ContainersReady   — all containers in the pod are ready
#   PodScheduled      — pod has been scheduled to a node

# Available node conditions:
#   Ready             — node is healthy and ready
#   MemoryPressure    — node is under memory pressure
#   DiskPressure      — node is under disk pressure
#   PIDPressure       — node is under PID pressure
#   NetworkUnavailable — node network is not configured

← Back to cheatsheet