Skip to content
DevOps devops orchestration 5 min read

kubectl Basics

kubectl (pronounced “kube-control” or “kube-cuttle”) is the command-line tool you use to talk to a Kubernetes cluster. Kubernetes is a system that runs and manages your containers (packaged-up apps) across many machines. You almost never click around in a web dashboard — instead you type kubectl commands or apply YAML files (text files that describe what you want running). This page teaches you the handful of commands you will use every single day: looking at what is running, reading logs, getting a shell inside a running app, deploying a manifest, and cleaning up.

How kubectl talks to your cluster

kubectl is just a client. It reads a configuration file (called a kubeconfig) that tells it the address of your cluster and how to log in. By default this file lives at ~/.kube/config on your Ubuntu machine.

When you install a local cluster (like Minikube or kind) or connect to a managed cluster (like Amazon EKS or Google GKE), that tool writes the connection details into this file for you.

Install kubectl on Ubuntu 22.04 / 24.04 LTS:

sudo apt-get update
sudo apt-get install -y ca-certificates curl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client

Output:

Client Version: v1.33.1
Kustomize Version: v5.6.0

Treat your ~/.kube/config file like a password. Anyone who can read it can control your entire cluster. Keep it at permission 0600 (chmod 600 ~/.kube/config) and never commit it to Git.

Contexts — which cluster am I talking to?

A context is a saved bundle of “which cluster + which user + which default namespace”. If you work with more than one cluster (say a local one and a production one), contexts let you switch between them so you do not accidentally run a command on the wrong cluster.

kubectl config get-contexts        # list all contexts
kubectl config current-context     # show the active one
kubectl config use-context minikube  # switch to a context

Output:

CURRENT   NAME       CLUSTER    AUTHINFO   NAMESPACE
*         minikube   minikube   minikube   default
          prod-eks   prod-eks   prod-eks   default

The * marks the active context. When to use this: always run current-context before any destructive command (like delete) so you are sure you are not pointed at production.

Namespaces — folders inside a cluster

A namespace is a way to split one cluster into separate areas, a bit like folders. Teams use them to keep dev, staging, and prod apart, or to give each team its own space. Most commands accept -n <namespace> to target a specific one, or -A / --all-namespaces to look across all of them.

kubectl get namespaces
kubectl get pods -n kube-system    # the cluster's own system pods
kubectl get pods -A                # pods everywhere

To avoid typing -n every time, set a default namespace on your context:

kubectl config set-context --current --namespace=dev

The four commands you will use constantly

CommandWhat it doesWhen to use it
kubectl getLists resources (pods, services, etc.)Quick “what is running?” check
kubectl describeShows full details and recent events for one resourceFiguring out why something is broken
kubectl logsPrints the output (stdout/stderr) of a containerDebugging crashes and app errors
kubectl execRuns a command inside a running containerPoke around a live container

Listing things with get

kubectl get pods
kubectl get pods -o wide          # adds node and IP columns
kubectl get deploy,svc            # several kinds at once
kubectl get pods -w               # "watch" — live updates as things change

Output:

NAME                     READY   STATUS    RESTARTS   AGE
web-7d9f8c6b4-2xq9z      1/1     Running   0          3m
web-7d9f8c6b4-lk4mn      1/1     Running   0          3m

READY 1/1 means the container is up. A status of CrashLoopBackOff or ImagePullBackOff means something is wrong — that is your cue to reach for describe and logs.

Investigating with describe and logs

kubectl describe pod web-7d9f8c6b4-2xq9z
kubectl logs web-7d9f8c6b4-2xq9z
kubectl logs -f web-7d9f8c6b4-2xq9z   # -f follows live, like tail -f
kubectl logs --previous web-7d9f8c6b4-2xq9z  # logs from the last crashed run

The Events section at the bottom of describe output is gold — it tells you things like “failed to pull image” or “out of memory”.

Getting a shell inside a pod with exec

kubectl exec -it web-7d9f8c6b4-2xq9z -- /bin/sh

The -it means interactive terminal, and everything after -- is the command to run inside the container. This drops you into a shell inside the live container so you can check files or test network connectivity.

Deploying a manifest with apply -f

A manifest is a YAML file describing what you want. kubectl apply -f reads that file and makes the cluster match it. The magic of apply is that it is declarative: you describe the desired end state, and you can run the same command again after editing the file — Kubernetes works out the difference and only changes what is needed.

Create a file called web.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80

Apply it and watch the pods come up:

kubectl apply -f web.yaml
kubectl get pods -w

Output:

deployment.apps/web created
service/web created

You can also point apply -f at a whole directory (kubectl apply -f ./manifests/) or even a URL. Use kubectl diff -f web.yaml to preview changes before applying them.

Cleaning up with delete

kubectl delete -f web.yaml      # removes exactly what the file created
kubectl delete pod web-7d9f8c6b4-2xq9z   # delete one pod (it gets recreated by the Deployment)

When NOT to use delete: do not delete individual pods to “fix” things in production. A Deployment immediately recreates them. Instead, fix the manifest and re-apply, or use kubectl rollout restart deployment/web to cycle pods cleanly.

Best practices

  • Always check kubectl config current-context before running delete, apply, or rollout so you never hit the wrong cluster.
  • Keep your manifests in Git and deploy with apply -f, not by typing imperative kubectl create commands — your repo becomes the source of truth.
  • Use kubectl diff -f before apply to preview exactly what will change.
  • Set a default namespace per context so you stop typing -n and stop making namespace mistakes.
  • Reach for describe (read the Events) and logs --previous first when a pod is crashing — they almost always reveal the cause.
  • Add alias k=kubectl to your ~/.bashrc to save thousands of keystrokes.
  • Never store ~/.kube/config in a repo and keep it at chmod 600.
Last updated June 15, 2026
Was this helpful?