Full lesson
Explore the full explanation, examples, and visuals at your own pace.
Terminal: the change that went missing
The apply said configured, yet staging hasn't changed. Look at the second command. The current context is prod-admin, a leftover from an earlier debugging session. So that apply didn't fail. It quietly patched the web deployment on prod, a cluster you never meant to touch.
$ kubectl apply -f web.yaml
deployment.apps/web configured
$ kubectl config current-context
prod-adminkubeconfig: clusters, users, contexts
Think of kubeconfig as a small map. A context bundles a cluster with a user. Here, staging pairs the staging cluster with the dev user, and prod-admin pairs the prod cluster with the admin user. Then current-context is a single pointer to one of them, and every kubectl command follows it.
~/.kube/config (credentials omitted)
Here's the actual file. Two clusters, two contexts, and current-context points at prod-admin. Notice neither context sets a namespace. Also, use-context doesn't just change your session; it rewrites that current-context line on disk. So a switch made while debugging carries into every later shell.
apiVersion: v1
kind: Config
current-context: prod-admin
clusters:
- name: staging
cluster: {server: https://staging.example:6443}
- name: prod
cluster: {server: https://prod.example:6443}
contexts:
- name: staging
context: {cluster: staging, user: dev}
- name: prod-admin
context: {cluster: prod, user: admin}kubectl never names its target
Watch what happens when you run apply. kubectl quietly reads current-context from kubeconfig, and gets back the prod cluster with admin credentials. Then it sends the patch to the Prod API, which answers 200 OK. The only thing you see is web configured. The output never names the cluster, so nothing looked wrong, even though prod just changed.
Namespace: the first one set wins
For a namespaced object, kubectl checks four places in order. First, metadata.namespace in the manifest. If that's unset, the -n flag. Then the namespace on the current context. If none of those say anything, it falls back to default. One catch: if the manifest namespace conflicts with -n, apply fails instead of picking one.
Milder case: right cluster, wrong namespace
Now we're on staging, the right cluster. But the manifest has no namespace, apply passed no -n, and the staging context sets none. So the Deployment lands in default. The clue is created, not configured. Looking in web finds nothing, while default shows it. Add namespace web to the manifest, and it lands where the team expects.
$ kubectl config current-context
staging
$ kubectl apply -f web.yaml
deployment.apps/web created
$ kubectl get deploy web -n web
Error from server (NotFound): deployments.apps "web" not found
$ kubectl get deploy web -n default
NAME READY UP-TO-DATE AVAILABLE AGE
web 1/1 1 1 20sMake the target visible
The fix is making the target visible. Run kubectl config current-context before anything risky, and put the context in your shell prompt. For prod, keep it out of your default kubeconfig, or require an explicit --context prod-admin on every command.
- Check kubectl config current-context first
- Show the current context in your prompt
- Prod: separate KUBECONFIG or explicit --context
RBAC: the server-side backstop
Even if kubectl points at prod, the server gets the final say. Here, a patch arrives as dev, the Prod API asks RBAC whether dev can patch, and with no matching rule it returns 403 Forbidden. The write is blocked server-side. But this only protects you if broad admin credentials aren't handed out to everyone.
Safeguards lower the odds; none make mistakes impossible.
Prompts get ignored, and an authorized admin can still hit the wrong target. So layer your safeguards, because no single one is enough on its own.
Check the pointer before you apply
Every kubectl command follows the current-context pointer unless a flag overrides it. And the namespace comes from the manifest, then the -n flag, then the context, then default. So before you apply, check where that pointer is aimed. A quick look saves you from a surprise in prod.
