Beginner Lesson 4 of 14

kubectl CLI

The command-line tool for Kubernetes. Master the commands you'll use every single day in production.

🧒 Simple Explanation (ELI5)

kubectl is your remote control for Kubernetes. Just like a TV remote lets you change channels, adjust volume, and check what's on, kubectl lets you deploy apps, check their status, read logs, and fix problems. Every Kubernetes interaction — whether from your terminal, a CI/CD pipeline, or a dashboard — ultimately goes through the same API that kubectl uses.

🤔 Why Do We Need kubectl?

🔧 Technical Explanation

kubectl communicates with the kube-apiserver using the Kubernetes API over HTTPS. It reads cluster connection details from ~/.kube/config (kubeconfig file), which contains cluster endpoints, authentication credentials, and context information.

Kubeconfig Structure

yaml
# ~/.kube/config (simplified)
apiVersion: v1
kind: Config
clusters:
  - name: my-cluster
    cluster:
      server: https://my-cluster-api.example.com:6443
      certificate-authority-data: <base64-ca-cert>
users:
  - name: admin
    user:
      client-certificate-data: <base64-cert>
      client-key-data: <base64-key>
contexts:
  - name: my-context
    context:
      cluster: my-cluster
      user: admin
      namespace: default
current-context: my-context

Command Structure

text
kubectl [command] [TYPE] [NAME] [flags]

Examples:
  kubectl get pods                     # List all pods in current namespace
  kubectl get pod my-pod -o yaml       # Get specific pod in YAML format
  kubectl describe svc my-service      # Detailed info about a service
  kubectl logs my-pod -c my-container  # Logs from a specific container
  kubectl apply -f deployment.yaml     # Apply a manifest file

⌨️ Hands-on: Essential kubectl Commands

Viewing Resources (GET / DESCRIBE / LOGS)

bash
# List pods in current namespace
kubectl get pods

# List pods in all namespaces
kubectl get pods -A

# Wide output (shows node, IP)
kubectl get pods -o wide

# JSON output (great for scripting)
kubectl get pod my-pod -o json

# YAML output
kubectl get pod my-pod -o yaml

# Custom columns
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName

# JSONPath (extract specific fields)
kubectl get pods -o jsonpath='{.items[*].metadata.name}'

# Watch for changes
kubectl get pods -w

# List all resource types
kubectl get all

# Describe (detailed info + events)
kubectl describe pod my-pod
kubectl describe node my-node
kubectl describe svc my-service

# Logs
kubectl logs my-pod
kubectl logs my-pod -c container-name     # specific container
kubectl logs my-pod --previous            # previous container (after crash)
kubectl logs my-pod -f                    # follow (stream)
kubectl logs my-pod --since=1h            # last hour
kubectl logs -l app=my-app                # by label selector

Creating & Managing Resources

bash
# Apply a manifest (declarative - preferred)
kubectl apply -f deployment.yaml

# Apply all manifests in a directory
kubectl apply -f ./manifests/

# Create imperatively (quick testing)
kubectl run nginx --image=nginx:1.25 --port=80
kubectl create deployment web --image=nginx --replicas=3

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

# Edit a live resource
kubectl edit deployment web

# Scale a deployment
kubectl scale deployment web --replicas=5

# Delete resources
kubectl delete pod my-pod
kubectl delete -f deployment.yaml
kubectl delete pods --all -n my-namespace

Debugging & Troubleshooting

bash
# Execute a command in a running pod
kubectl exec -it my-pod -- /bin/bash
kubectl exec my-pod -- env                # view environment variables
kubectl exec my-pod -- cat /etc/config    # read a file

# Port-forward (access pod from localhost)
kubectl port-forward pod/my-pod 8080:80
kubectl port-forward svc/my-service 8080:80

# Copy files to/from a pod
kubectl cp my-pod:/var/log/app.log ./app.log
kubectl cp ./config.txt my-pod:/etc/config.txt

# View events (sorted by time)
kubectl get events --sort-by=.metadata.creationTimestamp

# Top (resource usage - requires metrics-server)
kubectl top pods
kubectl top nodes

# Debug with ephemeral containers (K8s 1.25+)
kubectl debug -it my-pod --image=busybox --target=app

# Dry run (validate without applying)
kubectl apply -f deployment.yaml --dry-run=client
kubectl apply -f deployment.yaml --dry-run=server

Context & Namespace Management

bash
# View current context
kubectl config current-context

# List all contexts
kubectl config get-contexts

# Switch context
kubectl config use-context my-cluster-context

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

# Create a namespace
kubectl create namespace staging
💡
Pro Tip: Aliases

Add these to your ~/.bashrc or ~/.zshrc for speed:

alias k=kubectl
alias kgp="kubectl get pods"
alias kgs="kubectl get svc"
alias kd="kubectl describe"
alias kl="kubectl logs"

📊 Visual: kubectl Command Flow

How kubectl Commands Are Processed
kubectl (your terminal)
kubeconfig (auth + endpoint)
kube-apiserver (HTTPS)
kube-apiserver
Authentication → Authorization → Admission
etcd / scheduler / kubelet

🐛 Debugging Scenarios

Scenario 1: "kubectl: command not found"

Cause: kubectl not installed or not in PATH.

Scenario 2: "The connection to the server was refused"

Causes:

bash
# Debug steps
kubectl config view                       # check server URL
curl -k https://<api-server>:6443/healthz # test connectivity
kubectl cluster-info                      # see where K8s thinks it should connect

Scenario 3: "error: You must be logged in to the server (Unauthorized)"

Cause: Invalid or expired credentials in kubeconfig.

Scenario 4: Pod not running — debugging workflow

bash
# 1. Get overview
kubectl get pods

# 2. Check events 
kubectl describe pod problem-pod

# 3. Read logs
kubectl logs problem-pod
kubectl logs problem-pod --previous   # if crashed

# 4. Check resource issues
kubectl top pod problem-pod

# 5. Shell into the pod
kubectl exec -it problem-pod -- /bin/sh

# 6. Check environment
kubectl exec problem-pod -- env

# 7. Check network
kubectl exec problem-pod -- nslookup my-service

🎯 Interview Questions

Beginner

Q: What is kubectl?

kubectl is the command-line tool used to interact with Kubernetes clusters. It communicates with the kube-apiserver to create, inspect, update, and delete Kubernetes resources. It reads connection info from the kubeconfig file (default: ~/.kube/config).

Q: What is a kubeconfig file?

A kubeconfig file contains cluster connection info: API server URL, authentication credentials, and contexts. It defines clusters, users, and contexts (cluster + user + namespace combination). Default location: ~/.kube/config. You can manage multiple clusters by having multiple contexts.

Q: What's the difference between kubectl apply and kubectl create?

kubectl create is imperative — creates a resource; fails if it already exists. kubectl apply is declarative — creates or updates a resource to match the YAML manifest. Apply is preferred for production because it's idempotent, version-controllable, and supports incremental updates.

Q: How do you view logs of a crashed container?

kubectl logs pod-name --previous. The --previous flag shows logs from the previous container instance. This is essential for debugging CrashLoopBackOff — the current container might restart too fast to catch logs.

Q: How do you run a command inside a running pod?

kubectl exec -it pod-name -- /bin/bash (or /bin/sh). The -it flags make it interactive with a TTY. For a specific container in a multi-container pod: kubectl exec -it pod-name -c container-name -- /bin/bash.

Intermediate

Q: How do you switch between multiple clusters using kubectl?

Use contexts. kubectl config get-contexts to list all. kubectl config use-context context-name to switch. Each context maps to a cluster + user + namespace. You can also use the KUBECONFIG environment variable to point to different config files, or merge configs.

Q: What is kubectl port-forward and when do you use it?

kubectl port-forward pod/my-pod 8080:80 creates a tunnel from localhost:8080 to pod port 80. Used for debugging — access a pod directly without creating a Service or Ingress. Also works with services: kubectl port-forward svc/my-svc 8080:80. Not for production traffic — only for development and debugging.

Q: Explain kubectl dry-run modes.

--dry-run=client: validates locally without sending to the server. Fast but doesn't catch server-side validation errors. --dry-run=server: sends to the API server for full validation (auth, admission controllers, schema) but doesn't persist. Use client for quick generation; use server for accurate validation.

Q: How do you generate YAML manifests quickly?

Use imperative commands with dry-run: kubectl create deployment web --image=nginx --dry-run=client -o yaml > deploy.yaml. Or kubectl run test --image=nginx --dry-run=client -o yaml > pod.yaml. This generates boilerplate YAML you can edit. Essential for CKA/CKAD exam speed.

Q: What is JSONPath in kubectl and how do you use it?

JSONPath lets you extract specific fields from kubectl output. Example: kubectl get pods -o jsonpath='{.items[*].metadata.name}' lists all pod names. kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.capacity.cpu}{"\n"}{end}' shows node names and CPU capacity. Extremely useful for scripting and automation.

Scenario-Based

Q: You need to quickly find why a pod named 'api-server' is failing in the 'production' namespace. Walk through your commands.

kubectl get pod api-server -n production (check status). kubectl describe pod api-server -n production (check events, conditions). kubectl logs api-server -n production (current logs). kubectl logs api-server -n production --previous (if crashed). kubectl get events -n production --sort-by=.lastTimestamp (recent events). If needed: kubectl exec -it api-server -n production -- /bin/sh to inspect inside.

Q: You need to access a service running on port 5432 inside the cluster from your laptop. How?

kubectl port-forward svc/my-database 5432:5432 -n database. Now connect to localhost:5432 from your laptop. This creates a secure tunnel through the API server. For long-running needs, consider using a tool like kubefwd which forwards multiple services at once. Never expose database ports publicly.

Q: During a CKA exam, you need to create a nginx deployment with 3 replicas as fast as possible. What's the fastest way?

kubectl create deployment nginx --image=nginx:1.25 --replicas=3. If you need to customize further, generate YAML first: kubectl create deployment nginx --image=nginx:1.25 --replicas=3 --dry-run=client -o yaml > deploy.yaml, edit it, then kubectl apply -f deploy.yaml. Know your imperative shortcuts — they save crucial minutes in the exam.

Q: kubectl is timing out when connecting to a cluster. How do you diagnose?

1) kubectl config view — verify server URL. 2) ping or curl -k the API server endpoint — check network connectivity. 3) Check if VPN is required and connected. 4) Check firewall rules (port 6443). 5) Check if the cluster is actually running (cloud console, SSH to master). 6) Try kubectl --v=9 get pods for verbose output showing the full HTTP request/response cycle.

Q: You need to find all pods using more than 500Mi memory across all namespaces. How?

kubectl top pods -A --sort-by=memory (requires metrics-server). For resource requests: kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].resources.requests.memory}{"\n"}{end}'. Pipe through sort and awk to filter values above 500Mi.

🌍 Real-World Use Case

A DevOps team manages 12 Kubernetes clusters across 3 cloud providers. Their kubectl workflow:

📝 Summary

← Back to Kubernetes Course