Imperative Commands & Kubectl Ninja
Mastering kubectl is the primary differentiator between a novice and a Senior Kubernetes Engineer. This guide moves beyond basic get and describe to advanced filtering, debugging, and introspection.
1. DECLARATIVE VS. IMPERATIVE
Understanding the workflow difference is critical for production stability.
1.1 Imperative ("Do this now")
- Commands:
kubectl run,kubectl create,kubectl scale,kubectl expose. - Behavior: The API server executes the action immediately.
- Use Case:
- Disaster Recovery: Restarting workloads instantly.
- Debugging: Launching temporary pods.
- Bootstrapping: Generating initial YAML manifests.
- Risk: Changes are not recorded in Git. The cluster state drifts from the repo.
1.2 Declarative ("Make it look like this")
- Commands:
kubectl apply -f folder/. - Behavior: Client sends a patch. The Cluster calculates the difference between "Current State" and "Desired State" and reconciles.
- Use Case: GitOps (ArgoCD, Flux). The
yamlfile is the source of truth.
2. GENERATORS (Dry Run)
Never write YAML from scratch. Use imperative commands with --dry-run=client to generate the scaffold, then edit it.
Standard Boilerplates:
# 1. POD (with command arguments)
kubectl run tmp-shell --image=busybox --restart=Never --dry-run=client -o yaml \
-- /bin/sh -c 'echo hello; sleep 3600' > pod.yaml
# 2. DEPLOYMENT (Scalable app)
kubectl create deploy nginx-app --image=nginx:1.23 --replicas=3 --dry-run=client -o yaml > deploy.yaml
# 3. SERVICE (Exposing the deployment)
kubectl expose deploy nginx-app --name=nginx-svc --port=80 --target-port=8080 --type=ClusterIP --dry-run=client -o yaml > svc.yaml
# 4. CRONJOB (Periodic tasks)
kubectl create cronjob backup-job --image=postgres:15 --schedule="0 2 * * *" --dry-run=client -o yaml > cron.yaml
3. KUBECTL DEBUGGING (The "Ninja" Tier)
3.1 Ephemeral Containers (kubectl debug)
Modern container images (Distroless) lack shells, ps, curl, and tar. You cannot kubectl exec into them meaningfully.
The Solution: Inject a "Sidecar on demand" that shares the Process Namespace (PID) of the target.
# Attach a "netshoot" container (loaded with net tools) to a running Pod
kubectl debug -it <target-pod-name> \
--image=nicolaka/netshoot \
--target=<main-container-name> \
-- sh
# --target: Crucial. It makes the ephemeral container share the Process ID namespace.
# Once inside, run 'ps aux' to see the main container's processes.
3.2 Introspection (kubectl explain)
Stop googling "Kubernetes Pod Spec API". The documentation is built into the CLI.
# View the hierarchy of the Pod Spec
kubectl explain pod.spec
# Drill down into specific fields (e.g., how to configure liveness probes)
kubectl explain pod.spec.containers.livenessProbe --recursive
3.3 Raw API Access
Sometimes kubectl get hides details. You can hit the API server endpoints directly.
# Check cluster metrics (if Metrics Server is installed)
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes | jq .
4. JSONPATH MASTERY
Stop piping to grep and awk. Use standard JSONPath to extract data reliably for scripting.
Syntax: -o jsonpath='{expression}'
A. Security & Auditing
1. List all container images running in the namespace:
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort | uniq
2. Decode a Secret immediately:
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d
B. Networking
1. Get Pod Name and IP Address:
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
2. Get the NodePort assigned to a Service:
kubectl get svc my-service -o jsonpath='{.spec.ports[0].nodePort}'
C. Troubleshooting
1. Find Pods that are NOT Running:
kubectl get pods --field-selector=status.phase!=Running
2. Sort by Restart Count (Find the crash loops):
kubectl get pods -A --sort-by='.status.containerStatuses[0].restartCount'
3. Sort Events by Time (See what just happened):
kubectl get events --sort-by='.metadata.creationTimestamp'
5. HOW 'APPLY' WORKS (The Three-Way Merge)
Understanding this is required to debug "Drift" in GitOps.
When you run kubectl apply -f file.yaml, Kubernetes performs a Three-Way Merge Patch:
- The Live Object: The current JSON in Etcd.
- The Local Config: The YAML file you are applying.
- The Last-Applied-Configuration: A specific annotation stored on the Live Object:
kubectl.kubernetes.io/last-applied-configuration
The Logic Logic
| Condition | Action Taken |
|---|---|
| Field in Local, not in Live | Add (Update Live). |
| Field in Live, not in Local | Check Last-Applied. |
| -> If present in Last-Applied | Delete (You removed it from YAML, so K8s removes it). |
| -> If MISSING in Last-Applied | Ignore/Keep (Another controller, like HPA or Istio, added this field. Do not touch). |
The "Diff" Command
Before applying to production, always check the delta.
kubectl diff -f deployment.yaml
Returns exit code 1 if there are differences, 0 if identical. Useful for CI/CD pipelines.
6. ESSENTIAL KREW PLUGINS
krew is the plugin manager for kubectl. A Senior Engineer's toolkit typically includes:
kubectl ctx/kubectl ns: Fast switching between contexts and namespaces.kubectl tree: Visualizes ownership (Deployment -> RS -> Pod).kubectl tree deploy/my-app
kubectl neat: Cleans up the "garbage" (managedFields, creationTimestamp) when exporting YAML.kubectl get pod my-pod -o yaml | kubectl neat
kubectl stern: Tail logs from multiple pods simultaneously using regex.kubectl stern "backend-.*" -n default(Tails all backend pods at once).