Skip to content
Documentation Background

kubectl Reference

kubectl is the primary command-line interface to Kubernetes. Every command you type is translated into an authenticated HTTPS request to the API server, which then orchestrates the rest of the cluster. This page covers how to configure it, how to use it effectively, and when to choose each management style.


Before interacting with kubectl, you need a running cluster. You have two broad options: local (for development) and cloud-managed (for cloud-specific features and production scenarios).

ToolNodesNotes
Docker DesktopMulti-node (configurable)Bundles Docker, Kubernetes, and kubectl. Nodes run as Docker containers. Free for personal/educational use; paid license required for companies >250 employees or >$10M revenue.
MinikubeSingle-nodeSpins up a Linux VM. Works on any OS.
Kind (Kubernetes in Docker)Multi-nodeUses CRI-O, runs each node in a separate container. Easy to simulate real multi-node topologies.
k3dMulti-nodeLightweight K3s wrapped in Docker containers. Fast startup, low overhead.
K3sSingle or multi-nodeProduction-grade single-binary Kubernetes by Rancher/SUSE. ~512MB RAM footprint. Go-to for edge, ARM, and resource-constrained environments. k3d wraps this in Docker.
MicroK8sSingle or multi-nodeBy Canonical — installs via snap. Supports built-in addons (DNS, dashboard, storage, GPU). Popular on Ubuntu and Raspberry Pi.
Rancher DesktopSingle-nodeOpen-source alternative to Docker Desktop — bundles K3s, containerd/dockerd, and kubectl. No licensing restrictions.

Cloud clusters are required for features like cloud load balancers and cloud storage integrations. Any major managed Kubernetes service works — GKE, EKS (AWS), AKS (Azure), DigitalOcean, Linode — and all follow the same pattern: the provider manages the control plane, you configure node pools via their CLI or console, and download a kubeconfig to connect with kubectl.

Manual deployment (setting up a multi-node cluster entirely from scratch) is highly complex due to networking and administration requirements. See Cluster Setup with kubeadm if you need to do this.


kubectl reads a configuration file to know which cluster to talk to and how to authenticate.

  • Located at ~/.kube/config (macOS/Linux) or C:\Users\<username>\.kube\config (Windows)
  • The filename is exactly config - no .yaml extension
  • Structured into four components:
ComponentPurpose
ClustersList of known clusters and their API endpoints
UsersCredentials (certificates and private keys)
ContextsNamed pairings of a cluster + a user
Current contextThe active context kubectl sends all commands to

Your kubectl version must be within one minor version of your cluster. If the cluster runs v1.32.x, use kubectl v1.31.x or v1.33.x.

Terminal window
kubectl config get-contexts # list all contexts
kubectl config current-context # show active context
kubectl config use-context <context-name> # switch active context
# Set a default namespace for the current context
# Avoids typing -n <namespace> on every command
kubectl config set-context --current --namespace=my-namespace

When you need to add a second cluster (e.g., a cloud cluster) alongside an existing local one:

Terminal window
# 1. Rename your existing config as a backup
mv ~/.kube/config ~/.kube/config-bkp
# 2. Download the new cluster config into .kube/
# (e.g. tkb-kubeconfig.yaml from your cloud provider)
# 3. Set KUBECONFIG to point at both files
export KUBECONFIG=~/.kube/config-bkp:~/.kube/tkb-kubeconfig.yaml
# 4. Flatten into a single merged file
kubectl config view --flatten > ~/.kube/config
# 5. Switch the env var to the new unified file
export KUBECONFIG=~/.kube/config

Every kubectl command follows the same pattern:

kubectl [command] [TYPE] [NAME] [flags]
PartDescriptionExamples
commandThe action to performget, create, apply, delete, describe, edit, patch, exec, logs
TYPEResource type - full name or abbreviationpods/po, services/svc, deployments/deploy, nodes/no
NAMEObject name (metadata.name)my-pod, frontend
flagsOptional parameters-n namespace, -o yaml, --watch

Most commands operate on the current namespace by default. Use these flags to control scope:

FlagMeaning
-n <name> / --namespace=<name>Target a specific namespace
-A / --all-namespacesQuery across all namespaces

Set a persistent default with kubectl config set-context --current --namespace=<name> to avoid repeating -n on every command.

Control what kubectl prints with the -o flag:

FlagOutputBest used for
-o wideExtra columns (node, IP, etc.)Quick inspection at the terminal
-o yamlFull object as YAMLCopying a live object’s spec into a manifest
-o jsonFull object as JSONProgrammatic processing
-o jsonpath='{.spec.nodeName}'Extracted field valueScripting and automation
-o custom-columns=NAME:.metadata.name,NODE:.spec.nodeNameCustom tableTailored human-readable output
-o nameJust type/namePiping into kubectl delete or scripts
Terminal window
# --- Inspecting resources ---
kubectl get pods # list all pods in current namespace
kubectl get pods -n kube-system # specific namespace
kubectl get pods -A # all namespaces
kubectl get pods -o wide # extra columns (node, IP)
kubectl get pods -o yaml # full YAML output
kubectl get pods --watch # stream live updates
kubectl describe pod <name> # detailed view + events
kubectl get events --field-selector type=Warning # warnings only
# --- Logs ---
kubectl logs <pod-name> # container stdout/stderr
kubectl logs <pod-name> -c <container> # specific container in a multi-container pod
kubectl logs <pod-name> --previous # logs from last (crashed) container
kubectl logs <pod-name> -f # follow/stream logs
# --- Exec and copy ---
kubectl exec -it <pod-name> -- bash # interactive shell
kubectl exec <pod-name> -- <command> # one-shot command
kubectl cp <pod-name>:/path/to/file ./local # copy file from pod to local
kubectl cp ./local <pod-name>:/path/to/file # copy file from local to pod
# --- Port forwarding ---
kubectl port-forward pod/<name> 8080:80 # forward local port to pod
kubectl port-forward svc/<name> 8080:80 # forward local port to service
Terminal window
kubectl api-resources # all resource types with short names, groups, and scope
kubectl api-versions # all enabled API versions
kubectl explain pods # field-level documentation for Pods
kubectl explain pods.spec.containers # drill into nested fields
kubectl explain deployment.spec.strategy.rollingUpdate

Kubernetes supports three approaches for creating and managing objects. Kubernetes objects (Pods, Deployments, Services, and more) are covered in Kubernetes API & Object Model.

Direct kubectl commands manage objects without a manifest file. Fastest for one-off tasks and quick iteration.

Creating:

Terminal window
kubectl run frontend --image=nginx # create a Pod
kubectl create deployment app --image=nginx # create a Deployment
kubectl create service clusterip my-svc --tcp=80:80
kubectl create configmap app-config --from-literal=ENV=prod
kubectl create secret generic db-secret --from-literal=password=s3cr3t

Updating:

Terminal window
kubectl edit deployment app # opens live config in editor; saves on exit
kubectl patch pod my-pod -p '{"spec":{"containers":[{"name":"nginx","image":"nginx:1.25"}]}}'
kubectl set image deployment/app nginx=nginx:1.25
kubectl scale deployment app --replicas=5

Deleting:

Terminal window
kubectl delete pod my-pod
kubectl delete pod my-pod --now # skip 30-second grace period (SIGKILL immediately)
kubectl delete deployment app # deletes the Deployment and its Pods

YAML or JSON manifest files declare the desired state. The recommended approach for production, version control, and GitOps.

Terminal window
kubectl apply -f pod.yaml # create or update from a file
kubectl apply -f ./manifests/ # apply all files in a directory
kubectl apply -f https://example.com/app.yaml # apply from a URL
kubectl delete -f pod.yaml # delete objects described in a file

Why apply instead of create:

  • apply is idempotent - it compares the file with the live state and applies only the diff
  • apply stores a JSON snapshot in the annotation kubectl.kubernetes.io/last-applied-configuration to track historical changes
  • create fails if the resource already exists; apply succeeds whether creating or updating

Not every configuration is available as a flag. The hybrid approach uses imperative commands to generate boilerplate YAML without deploying anything - then you edit the file and apply it declaratively.

Terminal window
# Generate a Pod manifest without creating the Pod
kubectl run frontend --image=nginx -o yaml --dry-run=client > pod.yaml
# Generate a Deployment manifest
kubectl create deployment app --image=nginx -o yaml --dry-run=client > deploy.yaml
# Generate a Service manifest
kubectl create service clusterip my-svc --tcp=80:80 -o yaml --dry-run=client > svc.yaml

Then edit the generated YAML and deploy:

Terminal window
kubectl apply -f pod.yaml

Kubernetes tracks Deployment changes as revisions, enabling you to monitor progress and roll back if something goes wrong.

Terminal window
# Monitor a rollout as it progresses
kubectl rollout status deployment/app
# View revision history
kubectl rollout history deployment/app
# Show the exact changes in a specific revision
kubectl rollout history deployment/app --revision=2
# Roll back to the previous revision
kubectl rollout undo deployment/app
# Roll back to a specific revision
kubectl rollout undo deployment/app --to-revision=1
# Pause and resume a rollout (useful for canary testing)
kubectl rollout pause deployment/app
kubectl rollout resume deployment/app
# Restart all pods in a deployment (triggers a rolling replacement)
kubectl rollout restart deployment/app

Terminal window
# Create a Service to expose a Deployment
kubectl expose deployment app --port=80 --target-port=8080
# LoadBalancer Service (cloud environments - provisions a public IP)
kubectl expose deployment app --type=LoadBalancer --port=80
# NodePort (local/no-cloud environments - opens a port on every node)
kubectl expose deployment app --type=NodePort --port=80

In cloud environments, LoadBalancer Services automatically provision a public-facing load balancer. In local clusters without a cloud controller, Kubernetes falls back to NodePort - a port opened on every worker node that forwards traffic to the Service.

Terminal window
kubectl scale deployment app --replicas=10
kubectl autoscale deployment app --min=2 --max=10 --cpu-percent=80

When scaled, the Service automatically acts as an internal load balancer - distributing incoming requests across all available Pod replicas.


In production environments, teams strongly favour the declarative approach combined with GitOps principles:

  • Declarative YAML manifests are stored in a Git repository, which becomes the single source of truth for the cluster’s desired state
  • Tools like Argo CD and Flux watch the Git repository and automatically sync changes to the cluster
  • Every change to cluster state is a Git commit - giving you a full, auditable history and trivial rollbacks (git revert)
  • Drift detection ensures the live cluster never silently diverges from what is in Git

GitOps treats the cluster as a read-only artefact of the repository, not as a system that is manually configured.