The commands you actually run
This is the working set — the commands you'll type dozens of times a day. There aren't many. Split them into two jobs: seeing what's happening (get, describe, logs, exec) and changing it (apply, port-forward). Get fluent in these and you can handle the large majority of real work without looking anything up.
See the shape: get
get is your overview. It lists objects and their high-level state. Run it first, always, to orient yourself.
NAME READY STATUS RESTARTS AGE
web-7c9f5d8b6-2xk4p 1/1 Running 0 3d
web-7c9f5d8b6-9mlpq 1/1 Running 0 3d
worker-5f6c8d9b-tq2vn 0/1 Pending 0 12s
What just happened: one line per pod. Read the columns: READY is running-containers / desired-containers (so 0/1 means it's not up yet), STATUS is the headline, RESTARTS is a smell — a climbing number means something keeps dying, and AGE tells you if this is fresh or has been limping for days.
Two flags turn get from a snapshot into a tool:
What just happened: -o wide answers "which node is this on, and what's its IP?" -w keeps the command open and prints a new line every time a pod's state changes — perfect for watching a rollout settle without spamming the up-arrow key. Ctrl-C to stop.
You can get any resource the same way: kubectl get deploy, kubectl get svc, kubectl get nodes. Same grammar, different noun.
Get the full story: describe
get gives you the headline; describe gives you the article. When a pod looks wrong, describe is where the why lives — especially the Events section at the bottom.
Name: worker-5f6c8d9b-tq2vn
Namespace: payments
Status: Pending
Containers:
worker:
Image: registry.example.com/worker:1.4.2
State: Waiting
Reason: ImagePullBackOff
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Failed 20s (x3 over 1m) kubelet Failed to pull image "...worker:1.4.2": not found
What just happened: the Events section narrated the failure in plain language — Kubernetes tried to pull an image that doesn't exist. get only showed you Pending; describe told you exactly why. When something is stuck, the Events at the bottom of describe are usually the answer. Train your eyes to scroll straight there.
Read the program's own voice: logs
describe tells you what Kubernetes thinks about your pod from the outside. logs shows you what your application wrote to stdout/stderr from the inside. Both matter, and they answer different questions.
What just happened: logs printed whatever your app logs. -f follows it live; --tail=50 spares you scrolling through a day of output to see the last few lines.
One flag earns its keep over and over. When a pod has restarted, the current container's logs are often empty or boring — the interesting crash is in the container that died:
What just happened: --previous (or -p) shows the logs of the prior container instance — the one that crashed and got replaced. For anything in a restart loop, this is where the real error message hides.
If a pod runs more than one container, logs needs to know which:
What just happened: -c selects a container inside a multi-container pod. Without it, logs defaults to the first container, which may not be the one you care about.
Step inside: exec
Sometimes you need to be in the container — check a file, hit localhost, see what an env var actually resolved to. exec runs a command inside a running container; with -it it gives you an interactive shell.
/app # ls
config.yaml server static
/app # echo $DATABASE_URL
postgres://db.internal:5432/app
/app # exit
What just happened: -it gave you a terminal inside the container; everything after -- is the command to run there (here, a shell). The -- matters — it tells kubectl "stop reading flags, the rest is the container's command." Use a slim image's /bin/sh if /bin/bash isn't present.
You don't need a full shell for a one-off check:
What just happened: a single command runs in the container and its output comes back to you, no interactive session needed. Great for quick "is the config what I think it is?" checks.
Reach the service: port-forward
A service inside the cluster usually isn't reachable from your laptop. port-forward tunnels a local port straight to a pod or service so you can poke it with a browser or curl, without exposing anything publicly.
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
What just happened: traffic to localhost:8080 on your machine now flows to port 80 of the web service in the cluster. Open http://localhost:8080 and you're hitting the in-cluster app. The tunnel lives only as long as the command runs — Ctrl-C closes it. The format is LOCAL:REMOTE, so 8080:80 means "my 8080 → its 80."
Change it: apply
So far everything has been read-only. apply is how you make changes the right way. You hand it a YAML file describing the desired state, and Kubernetes makes reality match it.
deployment.apps/web configured
What just happened: Kubernetes compared your file to what's running and made the difference real. The output verb tells you what it did — created (new), configured (changed), or unchanged (already matched). apply is declarative: the file is the source of truth, and you can run it repeatedly with the same result.
apply vs edit:
kubectl edit deploy webopens the live object in your editor for a quick in-place change. It's handy for a hotfix at 3am — but the change exists only in the cluster, not in your YAML or git, so it vanishes the next time someone runsapply. Treateditas a temporary probe; treatapply -f(from version-controlled files) as how real changes ship. If youeditsomething to recover, port the fix back into the YAML before you forget.
A few change commands you'll use alongside apply:
What just happened: rollout status blocks until the new version is fully up (or fails), so you know when a deploy is actually done. rollout restart cycles the pods without changing the spec. rollout undo is your panic button — it reverts to the last known-good revision.
The 90-percent set, in one place
If you remember nothing else, remember this list. It covers most days:
kubectl get pods [-A] [-o wide] [-w] # what exists, what state
kubectl describe pod <name> # why it's in that state (read Events!)
kubectl logs <name> [-f] [--previous] # what the app itself said
kubectl exec -it <name> -- /bin/sh # get inside
kubectl port-forward svc/<name> 8080:80 # reach it from localhost
kubectl apply -f <file>.yaml # change it, declaratively
What just happened: six commands, each with a flag or two. This is the actual working vocabulary of most Kubernetes users. The next phase shows how to chain the read commands into a debugging loop when a pod refuses to start.
[
{
"q": "A pod keeps restarting and `kubectl logs <pod>` shows nothing useful. What should you try?",
"choices": [
"kubectl logs <pod> --previous",
"kubectl delete <pod>",
"kubectl get pods -w",
"kubectl apply -f again"
],
"answer": 0,
"explain": "`--previous` shows logs from the container instance that just crashed — where the real error usually is — instead of the fresh, empty one."
},
{
"q": "What's the key risk of fixing something with `kubectl edit` instead of `kubectl apply -f`?",
"choices": [
"edit is slower than apply",
"edit can only change one field at a time",
"The change lives only in the cluster and is lost on the next apply",
"edit requires cluster-admin permissions"
],
"answer": 2,
"explain": "`edit` mutates the live object but not your YAML or git, so the next `apply` from version control overwrites it. Use edit for temporary probes, apply for real changes."
},
{
"q": "In `kubectl port-forward svc/web 8080:80`, what does 8080:80 mean?",
"choices": [
"Cluster port 8080 maps to your local port 80",
"Your local port 8080 maps to the service's port 80",
"It forwards both ports 8080 and 80 simultaneously",
"It's a timeout in seconds"
],
"answer": 1,
"explain": "The format is LOCAL:REMOTE. Traffic to localhost:8080 on your machine is tunneled to port 80 of the in-cluster service."
}
]
← Phase 1: The mental model | Overview | Phase 3: When a pod won't start →
Check your understanding 3 questions
1. A pod keeps restarting and `kubectl logs <pod>` shows nothing useful. What should you try?
2. What's the key risk of fixing something with `kubectl edit` instead of `kubectl apply -f`?
3. In `kubectl port-forward svc/web 8080:80`, what does 8080:80 mean?