## 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. After reading, you will be able to:

- Set and verify context and namespace to reduce risk of targeting the wrong cluster.

- Inspect workloads and nodes with read-only commands before making changes.

- Apply small, reviewable changes and verify rollouts complete successfully.

- Debug issues using logs, exec, port-forward, events, and metrics.

- Practice everything in a local pilot cluster before touching production.

All examples use a non-default namespace called demo for safety.

---

## Workflow Overview

A dependable operator workflow keeps changes small, visible, and reversible.

### 1. Set scope explicitly

Pick context and namespace so every command is targeted:

kubectl config get-contexts
kubectl config use-context <your-context>
kubectl config set-context --current --namespace=demo 

### 2. Inspect current state

 kubectl get nodes
kubectl get deploy,sts,ds -n demo
kubectl get events -n demo --sort-by=.lastTimestamp 

### 3. Plan a minimal change

 Prefer labels and resource selectors; avoid broad wildcards. Keep one change per apply to make rollback easy.

### 4. Preview before apply

kubectl diff -f web.yaml
kubectl apply --dry-run=server -f web.yaml 

### 5. Apply and verify

 kubectl apply -f web.yaml
kubectl rollout status deploy/web -n demo
kubectl wait --for=condition=available deploy/web -n demo --timeout=90s 

### 6. Roll back if needed

 kubectl rollout undo deploy/web -n demo 

### 7. Observe after change

 kubectl logs -n demo deploy/web
kubectl top pods -n demo
kubectl get events -n demo --sort-by=.lastTimestamp | tail -20
kubectl describe deploy/web -n demo 
 ---

## 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 (requires jq)
kubectl get deploy -n demo web -o json | jq . 

### 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 
 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
kubectl rollout undo deploy/web -n demo --to-revision=1 # to specific revision 

### 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 from deployment (all pods)
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 -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 --watch during 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 -20
kind delete cluster --name pilot 

### Option B: minikube (if you prefer)

 minikube start
kubectl config set-context --current --namespace=demo 2>/dev/null || \
 (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.