Intro
Kubernetes is powerful, but most day-2 operations boil down to a small, safe set of kubectl commands. This guide shows what to run, when to use it, and how to avoid surprises. You will:
- Set and verify context and namespace to reduce risk.
- Inspect workloads and nodes with read-only commands first.
- Apply small, reviewable changes and verify rollouts.
- Debug with logs, exec, port-forward, events, and metrics.
- Practice everything in a local pilot before you touch production.
All examples use a non-default namespace called demo for safety.
---
Workflow Overview
A dependable operator workflow keeps changes small, visible, and reversible.
- Set scope explicitly
- Pick context and namespace so every command is targeted.
- Commands:
kubectl config get-contexts,kubectl config use-context,kubectl config set-context --current --namespace=demo.
- Inspect current state
- Commands:
kubectl get,kubectl describe,kubectl get events --sort-by=.lastTimestamp.
- Plan a minimal change
- Prefer labels and resource selectors; avoid broad wildcards.
- Keep one change per apply to make rollback easy.
- Preview before apply
- Commands:
kubectl diff -f ...,kubectl apply --dry-run=server -f ....
- Apply and verify
- Commands:
kubectl apply -f ...,kubectl rollout status deploy/<name>,kubectl wait --for=condition=available.
- Roll back if needed
- Commands:
kubectl rollout undo deploy/<name>.
- Observe after change
- Commands:
kubectl logs,kubectl top,kubectl get events,kubectl describe.
---
Core kubectl essentials
Cluster, context, and namespace
# Show API server endpoints and component info
kubectl cluster-info
# List and switch contexts
kubectl config get-contexts
kubectl config use-context <your-context>
# Create and set a safe working namespace
kubectl create namespace demo
kubectl config set-context --current --namespace=demo
# Confirm namespace in your current context
kubectl config view --minify --output 'jsonpath={..namespace}{"\n"}'
Listing and filtering resources
# Common resources at a glance
kubectl get nodes
kubectl get ns
kubectl get deploy, ds, sts -A # cluster-wide list of workloads
# Namespaced views (safe default)
kubectl get all -n demo
kubectl get pods -n demo -o wide
# Filter by label selector
kubectl get pods -n demo -l app=web
# Sort and watch
kubectl get pods -n demo --sort-by=.metadata.name
kubectl get pods -n demo --watch
Describe for deep inspection
kubectl describe pod -n demo <pod-name>
kubectl describe deploy -n demo <deploy-name>
JSON and JSONPath output
# Get a single field with JSONPath
kubectl get svc -n demo web -o jsonpath='{.spec.clusterIP}{"\n"}'
# Pretty JSON
kubectl get deploy -n demo web -o json | jq . # if jq is available
Events and metrics
kubectl get events -n demo --sort-by=.lastTimestamp
# Metrics (requires metrics-server)
kubectl top nodes
kubectl top pods -n demo
---
Safe changes and rollbacks
Generate YAML, then apply
Prefer generating manifests and applying them, instead of imperative mutation. This keeps changes reviewable and repeatable.
# Option 1: scaffold YAML using kubectl and edit locally
kubectl create deploy web \
-n demo \
--image=nginx:1.25 \
--replicas=2 \
--dry-run=client -o yaml > web-deploy.yaml
# Option 2: write a minimal Deployment + Service (example below)
Example Deployment and Service (save as web.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
limits:
cpu: "200m"
memory: "128Mi"
requests:
cpu: "100m"
memory: "64Mi"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: web
namespace: demo
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
type: ClusterIP
Preview, apply, and verify:
kubectl diff -f web.yaml
kubectl apply --dry-run=server -f web.yaml
kubectl apply -f web.yaml
kubectl rollout status deploy/web -n demo
kubectl get pods -n demo -l app=web -o wide
kubectl get svc -n demo web
Safe updates
- Image update:
kubectl set image deploy/web -n demo web=nginx:1.25.3
kubectl rollout status deploy/web -n demo
- Scale temporarily:
kubectl scale deploy/web -n demo --replicas=3
kubectl get deploy/web -n demo -o jsonpath='{.spec.replicas}{"\n"}'
- Patch a small field:
kubectl patch deploy/web -n demo \
--type merge \
-p '{"spec":{"template":{"spec":{"terminationGracePeriodSeconds":20}}}}'
Roll back confidently
kubectl rollout history deploy/web -n demo
kubectl rollout undo deploy/web -n demo # to previous revision
# or to a specific revision
kubectl rollout undo deploy/web -n demo --to-revision=1
Safe deletions
Always scope deletions by resource kind, namespace, and labels.
# Delete just the Deployment. The Service remains.
kubectl delete deploy/web -n demo
# Delete by label selector (double-check with get first)
kubectl get deploy -n demo -l app=web
kubectl delete deploy -n demo -l app=web
---
Observability and debugging
Logs
# Current logs
kubectl logs -n demo deploy/web
# Stream logs from a single pod
POD=$(kubectl get pods -n demo -l app=web -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n demo $POD -f
# Include previous container logs after a crash
kubectl logs -n demo $POD --previous
Exec and port-forward
# Open a shell in a pod (use only when needed)
kubectl exec -n demo -it $POD -- sh
# Forward local port 8080 to Service port 80
kubectl port-forward -n demo svc/web 8080:80
# Now curl locally
curl -I http://127.0.0.1:8080/
Events, status, and readiness
kubectl get events -n demo --sort-by=.lastTimestamp | tail -n 20
kubectl describe deploy/web -n demo
kubectl wait -n demo --for=condition=available deploy/web --timeout=90s
Nodes: cordon, drain, uncordon (use with care)
# Prevent new pods from scheduling on a node
kubectl cordon <node-name>
# Evict pods safely (consider PodDisruptionBudgets)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# Allow scheduling again
kubectl uncordon <node-name>
Tips:
- Communicate impact before drain.
- Watch
kubectl get pods -A --watchduring maintenance. - Verify DaemonSets and PDBs ahead of time.
---
Local Pilot Plan
A good first pilot is narrow, measurable, and easy to inspect locally before deployment.
Option A: kind (requires Docker)
# 1) Create a local cluster
kind create cluster --name pilot
kubectl config use-context kind-pilot
# 2) Prepare namespace
kubectl create namespace demo
kubectl config set-context --current --namespace=demo
# 3) Deploy sample app
kubectl apply -f web.yaml
kubectl rollout status deploy/web -n demo
# 4) Validate
kubectl get pods -n demo -o wide
kubectl get svc -n demo web
kubectl port-forward -n demo svc/web 8080:80 &
curl -I http://127.0.0.1:8080/
# 5) Exercise change and rollback
kubectl set image deploy/web -n demo web=nginx:1.25.3
kubectl rollout status deploy/web -n demo
kubectl rollout undo deploy/web -n demo
# 6) Measure and clean up
kubectl get events -n demo --sort-by=.lastTimestamp | tail -n 20
kind delete cluster --name pilot
Option B: minikube (if you prefer)
minikube start
kubectl config set-context --current --namespace=demo || kubectl create namespace demo && kubectl config set-context --current --namespace=demo
kubectl apply -f web.yaml
minikube service -n demo web --url
Success criteria for the pilot:
- Pods become Ready, rollout completes, and curl returns HTTP 200.
- A small image update rolls out and can be undone cleanly.
- Events and logs clearly show the sequence of actions.
---
Conclusion
Mastering a compact set of kubectl commands makes daily Kubernetes operations predictable and safe. Always set your context and namespace, inspect first, preview diffs, apply small changes, verify rollouts, and observe system signals. Prove your flow with a tiny local pilot, then carry the same habits into shared environments.
Next steps:
- Save your common commands as scripts or aliases scoped by namespace.
- Add labels consistently so selectors stay precise.
- Practice rollouts and undo weekly on a non-critical service.