Skip to content

Notes14-Kubernetes Commands

Kubernetes Commands

Imperative kubectl, output and JSONPath, nodes, kubeadm, etcd, certificates, and the host tools you reach for when the API is down.

Updated Oct 1, 2026

Kubernetes Commands Quick Notes




How to read this page

  • Replace placeholders: <ns>, <node>, <pod>, <deploy>, image tags, and file paths.
  • Context first: One shell can talk to several clusters. kubectl config use-context before any change.
  • Namespace on every command that targets a namespaced object, or set the context namespace once.
  • Imperative when the object is simple. --dry-run=client -o yaml when you must add a probe, a volume, or affinity.

Short names you can type: po Pod, svc Service, deploy Deployment, rs ReplicaSet, ds DaemonSet, sts StatefulSet, cm ConfigMap, ns Namespace, no Node, pv PersistentVolume, pvc PersistentVolumeClaim, sc StorageClass, ing Ingress, netpol NetworkPolicy, sa ServiceAccount, ep Endpoints, csr CertificateSigningRequest.


Context, namespace, and the shell


bash
kubectl config get-contexts
kubectl config current-context
kubectl config use-context <context>

kubectl config set-context --current --namespace=<ns>
kubectl config view --minify | grep namespace

alias k=kubectl
export do="--dry-run=client -o yaml"
echo $KUBECONFIG


  • KUBECONFIG: If this variable is set, kubectl ignores ~/.kube/config until you account for it.
  • k alias: Optional. type k shows whether this shell already defines it.
  • $do: Expand it yourself as --dry-run=client -o yaml if you would rather not rely on a variable. Example: kubectl create deployment web --image=nginx $do.


bash
kubectl version
kubectl cluster-info
kubectl auth whoami
kubectl api-resources
kubectl api-resources --namespaced=false
kubectl api-versions


Imperative create

Generators write a correct object without a blank YAML file. Add --dry-run=client -o yaml and redirect to a file when you need a field the generator cannot set.


bash
kubectl create namespace <ns>
kubectl create serviceaccount <sa> -n <ns>

kubectl run <pod> --image=<image> --port=80
kubectl run <pod> --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl run <pod> --image=nginx \
  --labels=app=web --env=COLOR=blue \
  --requests=cpu=100m,memory=64Mi \
  --limits=cpu=200m,memory=128Mi \
  --dry-run=client -o yaml > pod.yaml

kubectl create deployment <deploy> --image=<image> --replicas=3 --port=80
kubectl create job <job> --image=busybox:1.36 -- echo hello
kubectl create cronjob <cron> --image=busybox:1.36 --schedule="*/5 * * * *" -- echo tick
kubectl create job <job> --from=cronjob/<cron>

kubectl expose deployment <deploy> --name=<svc> --port=80 --target-port=80
kubectl expose deployment <deploy> --type=NodePort --port=80 --name=<svc>
kubectl create service clusterip <svc> --tcp=80:80
kubectl create service nodeport <svc> --tcp=80:80 --node-port=30080
kubectl create service loadbalancer <svc> --tcp=80:80

kubectl create ingress <ing> --class=nginx \
  --rule="shop.example.com/wear=wear:80"

kubectl create configmap <cm> \
  --from-literal=key=value \
  --from-file=app.conf=./app.conf \
  --from-env-file=./app.env
kubectl create secret generic <secret> --from-literal=password='s3cr3t' --from-file=username=./user.txt
kubectl create secret tls <tls-secret> --cert=tls.crt --key=tls.key
kubectl create secret docker-registry <regcred> \
  --docker-server=<registry> --docker-username=<user> --docker-password='<token>'

kubectl create token <sa> -n <ns> --duration=1h

kubectl create role <role> --verb=get,list,watch --resource=pods -n <ns>
kubectl create clusterrole <clusterrole> --verb=get,list --resource=nodes
kubectl create rolebinding <binding> --role=<role> --user=<user> -n <ns>
kubectl create rolebinding <binding> --clusterrole=view --user=<user> -n <ns>
kubectl create rolebinding <binding> --clusterrole=edit \
  --serviceaccount=<ns>:<sa> -n <ns>
kubectl create clusterrolebinding <binding> --clusterrole=cluster-admin --user=<user>
kubectl create clusterrolebinding <binding> --clusterrole=<clusterrole> --group=<group>

kubectl create quota <quota> --hard=cpu=2,memory=2Gi,pods=10 -n <ns>
kubectl create poddisruptionbudget <pdb> --selector=app=web --min-available=1 -n <ns>
kubectl autoscale deployment <deploy> --min=2 --max=10 --cpu-percent=70


  • kubectl run creates a Pod. kubectl create deployment creates a Deployment.
  • --restart=Never on kubectl run keeps a bare Pod. Without it, current kubectl still creates a Pod. Use create deployment when you want replicas.
  • --command -- on kubectl run replaces the image entrypoint. Everything after -- is the command.
  • RoleBinding can point at a ClusterRole (--clusterrole=view). The grant applies only in -n.
  • ServiceAccount subject on a binding is --serviceaccount=<namespace>:<name>.


Apply, edit, patch, delete, wait


bash
kubectl apply -f file.yaml
kubectl apply -f ./dir/
kubectl apply -k ./overlays/prod
kubectl diff -f file.yaml
kubectl replace -f file.yaml
kubectl delete -f file.yaml
kubectl delete -f file.yaml --wait=false

kubectl edit deployment <deploy> -n <ns>
kubectl edit pod <pod> -n <ns>

kubectl scale deployment <deploy> --replicas=5
kubectl scale sts <sts> --replicas=3
kubectl delete pod <pod> -n <ns> --force --grace-period=0
kubectl delete pods -l app=web -n <ns>

kubectl wait --for=condition=Ready pod -l app=web -n <ns> --timeout=90s
kubectl wait --for=condition=available deployment/<deploy> -n <ns> --timeout=120s
kubectl wait --for=condition=complete job/<job> -n <ns> --timeout=120s

kubectl patch deployment <deploy> -p '{"spec":{"replicas":3}}'
kubectl patch node <node> -p '{"spec":{"unschedulable":true}}'
kubectl patch pv <pv> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
kubectl patch pvc <pvc> -n <ns> -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
kubectl patch deployment <deploy> --type=json -p='[
  {"op":"replace","path":"/spec/replicas","value":4}
]'


  • kubectl edit on a Pod can change a few fields. Image, requests, and most of spec on a running Pod are immutable. Delete the Pod or edit the Deployment.
  • diff shows what apply would change. Run it before you overwrite a working object.
  • JSON patch (--type=json) is the reliable way to replace one path. A strategic merge patch is the default -p.


Set image, env, resources, service account


bash
kubectl set image deployment/<deploy> <container>=<image>:<tag>
kubectl set image deployment/<deploy> '*=nginx:1.27'
kubectl set env deployment/<deploy> COLOR=blue
kubectl set env deployment/<deploy> --from=configmap/<cm>
kubectl set env deployment/<deploy> PASSWORD-   # remove the variable
kubectl set resources deployment/<deploy> -c=<container> \
  --requests=cpu=100m,memory=128Mi \
  --limits=cpu=500m,memory=256Mi
kubectl set serviceaccount deployment/<deploy> <sa>


kubectl set image records a new Pod template, so a Deployment rolls out. Confirm with kubectl rollout status.

Rollouts


bash
kubectl rollout status deployment/<deploy>
kubectl rollout history deployment/<deploy>
kubectl rollout undo deployment/<deploy>
kubectl rollout undo deployment/<deploy> --to-revision=2
kubectl rollout pause deployment/<deploy>
kubectl rollout resume deployment/<deploy>
kubectl rollout restart deployment/<deploy>
kubectl rollout restart daemonset/<ds> -n kube-system
kubectl annotate deployment/<deploy> kubernetes.io/change-cause="bump image"


Labels, annotations, taints


bash
kubectl label pod <pod> env=prod --overwrite
kubectl label node <node> disktype=ssd
kubectl label namespace <ns> pod-security.kubernetes.io/enforce=baseline
kubectl annotate pod <pod> owner=platform --overwrite

kubectl taint nodes <node> dedicated=batch:NoSchedule
kubectl taint nodes <node> dedicated=batch:NoSchedule-
kubectl taint nodes --all node-role.kubernetes.io/control-plane:NoSchedule-
kubectl taint nodes <node> node-role.kubernetes.io/control-plane:NoSchedule


Default StorageClass annotation (on the StorageClass, not the namespace):


bash
kubectl annotate storageclass <sc> storageclass.kubernetes.io/is-default-class=true --overwrite
kubectl annotate storageclass <old> storageclass.kubernetes.io/is-default-class=false --overwrite


Remove a label by putting a trailing - on the key: kubectl label node <node> disktype-.


Get, describe, and events


bash
kubectl get pods -n <ns> -o wide
kubectl get pods -A -o wide
kubectl get pods -n <ns> --show-labels
kubectl get pods -n <ns> -L app,env
kubectl get pods -n <ns> -w
kubectl get deploy,rs,po,svc -n <ns>
kubectl get nodes -o wide
kubectl get events -n <ns> --sort-by=.lastTimestamp
kubectl get events -A --field-selector type=Warning --sort-by=.lastTimestamp
kubectl describe pod <pod> -n <ns>
kubectl describe deploy <deploy> -n <ns>
kubectl describe node <node>
kubectl describe svc <svc> -n <ns>
kubectl explain pod.spec.containers
kubectl explain deployment.spec.strategy.rollingUpdate
kubectl explain ingress.spec --api-version=networking.k8s.io/v1
kubectl explain networkpolicy.spec.ingress.from --api-version=networking.k8s.io/v1
kubectl explain pods --recursive
k


Selectors:


bash
kubectl get pods -l app=web
kubectl get pods -l 'env in (prod,stage),tier!=cache'
kubectl get pods --field-selector status.phase=Running
kubectl get pods -A --field-selector spec.nodeName=<node>
kubectl get pods -n <ns> --field-selector status.phase=Running,spec.nodeName=<node>
kubectl get pv --field-selector status.phase=Released
kubectl get events --field-selector involvedObject.name=<pod>


Sort and columns:


bash
kubectl get pods --sort-by=.metadata.creationTimestamp
kubectl get pv --sort-by=.spec.capacity.storage
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,IP:.status.podIP,NODE:.spec.nodeName
kubectl get nodes -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion,OS:.status.nodeInfo.operatingSystem
kubectl get pods -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,NODE:.spec.nodeName,STATUS:.status.phase


JSONPath

Single quotes around the expression so the shell leaves {, $, and \ alone. {.field} is one object. {range .items[*]}...{end} walks a list. {"\n"} and {"\t"} are literals. A missing key prints nothing.


bash
kubectl get pod <pod> -o jsonpath='{.status.podIP}{"\n"}'
kubectl get pod <pod> -o jsonpath='{.spec.nodeName}{"\n"}'
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kubeletVersion}{"\n"}{end}'
kubectl get pod <pod> -o jsonpath='{range .spec.containers[*]}{.name}{" "}{.image}{"\n"}{end}'
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}{"\n"}'
kubectl get secret <secret> -n <ns> -o jsonpath='{.data.password}' | base64 -d; echo
kubectl get csr <csr> -o jsonpath='{.status.certificate}' | base64 -d > user.crt
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}'
kubectl -n kube-system get pod kube-apiserver-<node> -o jsonpath='{.spec.containers[0].command}{"\n"}'


Decode a whole Secret to YAML-friendly values:

kubectl get secret <secret> -n <ns> -o go-template='{{range $k,$v := .data}}{{$k}}={{$v | base64decode}}{{"\n"}}{{end}}'

Logs, exec, copy, debug, metrics


bash
kubectl logs <pod> -n <ns>
kubectl logs <pod> -n <ns> -c <container>
kubectl logs <pod> -n <ns> -c <container> --previous
kubectl logs <pod> -n <ns> --all-containers --tail=50
kubectl logs deploy/<deploy> -n <ns> --prefix --tail=20
kubectl logs -l app=web -n <ns> --prefix --tail=20
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=30
kubectl logs -n kube-system etcd-<node>
kubectl logs -n kube-system kube-apiserver-<node>

kubectl exec -n <ns> <pod> -- hostname
kubectl exec -it -n <ns> <pod> -c <container> -- sh
kubectl exec -n <ns> <pod> -- nslookup kubernetes.default
kubectl exec -n <ns> <pod> -- wget -qO- --timeout=2 http://<svc>.<ns>.svc.cluster.local

kubectl cp <ns>/<pod>:/path/in/pod ./local-file -c <container>
kubectl cp ./local-file <ns>/<pod>:/path/in/pod -c <container>

kubectl port-forward pod/<pod> 8080:80 -n <ns>
kubectl port-forward svc/<svc> 8080:80 -n <ns>

kubectl debug -it <pod> -n <ns> --image=busybox:1.36 --target=<container>
kubectl debug node/<node> -it --image=busybox:1.36

kubectl top nodes
kubectl top pods -A --sort-by=memory
kubectl top pod <pod> -n <ns> --containers
kubectl get apiservice v1beta1.metrics.k8s.io
kubectl get deploy -n kube-system metrics-server


A disposable client Pod:


bash
kubectl run net --rm -it --restart=Never --image=busybox:1.36 -n <ns> -- sh


kubectl debug node starts a privileged Pod in the host namespaces and mounts the node root at /host. Use it when you cannot SSH and still need chroot /host to read kubelet files.


Workloads to list while you debug


bash
kubectl get deploy,rs,ds,sts,job,cronjob -n <ns>
kubectl get hpa -n <ns>
kubectl describe hpa <hpa> -n <ns>
kubectl get pdb -A
kubectl describe pdb <pdb> -n <ns>
kubectl get sa -n <ns>
kubectl get quota,limits -n <ns>
kubectl describe quota -n <ns>
kubectl get cronjob <cron> -n <ns>
kubectl get pods -n <ns> -l job-name=<job>


Services, DNS, Ingress, Gateway


bash
kubectl get svc -n <ns> -o wide
kubectl get endpoints -n <ns>
kubectl get endpointslices -n <ns> -l kubernetes.io/service-name=<svc>
kubectl get ingressclass
kubectl get ingress -A
kubectl describe ingress <ing> -n <ns>
kubectl get gatewayclass,gateway,httproute -A
kubectl describe httproute <route> -n <ns>

kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl get svc kube-dns -n kube-system
kubectl get configmap coredns -n kube-system -o yaml
kubectl rollout restart deployment coredns -n kube-system


NetworkPolicy


bash
kubectl get netpol -A
kubectl describe netpol <policy> -n <ns>
kubectl get pods -n <ns> --show-labels


There is no packet counter on the object. Test with wget or nc from a Pod in the source namespace.

Storage


bash
kubectl get pv,pvc,sc -A
kubectl describe pvc <pvc> -n <ns>
kubectl describe pv <pv>
kubectl get volumeattachment
kubectl get pods -n <ns> -o wide
kubectl delete pvc <pvc> -n <ns> --wait=false


volumeattachment shows which node holds a disk. A multi-attach error on an RWO volume usually means a terminating Pod on another node still has it.


RBAC checks


bash
kubectl get role,rolebinding -n <ns>
kubectl get clusterrole,clusterrolebinding
kubectl describe role <role> -n <ns>
kubectl describe rolebinding <binding> -n <ns>
kubectl describe clusterrole <clusterrole>
kubectl auth can-i create deployments -n <ns>
kubectl auth can-i delete nodes
kubectl auth can-i list secrets -n <ns> --as <user>
kubectl auth can-i get pods -n <ns> --as system:serviceaccount:<ns>:<sa>
kubectl auth can-i --list -n <ns>
kubectl auth can-i --list --as <user>


yes / no from auth can-i is the check that the binding matches the user you think it matches.


Certificates and kubeconfig


bash
openssl genrsa -out user.key 2048
openssl req -new -key user.key -out user.csr -subj "/CN=<user>/O=<group>"
cat user.csr | base64 | tr -d '\n'

kubectl get csr
kubectl certificate approve <csr>
kubectl certificate deny <csr>
kubectl delete csr <csr>

openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates -subject
openssl x509 -in user.crt -noout -subject -issuer -dates

kubeadm certs check-expiration
kubeadm certs renew all

kubectl config set-cluster <cluster> \
  --server=https://<api>:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true
kubectl config set-credentials <user> \
  --client-certificate=user.crt \
  --client-key=user.key \
  --embed-certs=true
kubectl config set-credentials <user> --token="<token>"
kubectl config set-context <user>@<cluster> \
  --cluster=<cluster> --user=<user> --namespace=<ns>
kubectl config use-context <user>@<cluster>
kubectl config view --minify --flatten
kubectl config view --raw


CA hash for kubeadm join (hex only; prefix the join flag with sha256:):


bash
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt \
  | openssl rsa -pubin -outform der 2>/dev/null \
  | openssl dgst -sha256 -hex | sed 's/^.* //'


Base64 helpers:


bash
echo -n 's3cr3t' | base64
echo '<base64>' | base64 -d


echo -n avoids embedding a trailing newline in the Secret.


Nodes: cordon, drain, capacity


bash
kubectl get nodes
kubectl describe node <node>
kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data --force
kubectl uncordon <node>


--ignore-daemonsets lets drain continue. It does not delete DaemonSet Pods. --force is for Pods that have no controller. Drain stops while a PodDisruptionBudget would be violated.


bash
kubectl describe node <node> | sed -n '/Taints/,+8p'
kubectl describe node <node> | sed -n '/Allocated resources/,+12p'
kubectl describe node <node> | sed -n '/Conditions/,+12p'
kubectl get ds -A -o wide


kubeadm


bash
kubeadm version
kubeadm init \
  --apiserver-advertise-address=<node-ip> \
  --pod-network-cidr=<cidr> \
  --control-plane-endpoint=<lb-host>:6443 \
  --kubernetes-version=v1.35.0 \
  --upload-certs

mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown "$(id -u):$(id -g)" $HOME/.kube/config

kubeadm token list
kubeadm token create --print-join-command
kubeadm token create --ttl 2h
kubeadm init phase upload-certs --upload-certs

kubeadm join <endpoint>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
kubeadm join <endpoint>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash> \
  --control-plane --certificate-key <key>

kubeadm upgrade plan
kubeadm upgrade apply v1.35.0
kubeadm upgrade node
kubeadm reset
kubeadm config images list


kubeadm reset removes this node’s cluster install. Use it only on the node you intend to rejoin.

Control-plane upgrade, then each other node:


bash
sudo apt-get update
sudo apt-cache madison kubeadm
sudo apt-get install -y kubeadm=<pkg-version>
sudo kubeadm upgrade plan
sudo kubeadm upgrade apply v1.35.0          # first control plane only
sudo apt-get install -y kubelet=<pkg-version> kubectl=<pkg-version>
sudo systemctl daemon-reload
sudo systemctl restart kubelet


Other control planes and workers use kubeadm upgrade node after drain, then the same kubelet package install, then kubectl uncordon.


bash
sudo apt-mark hold kubelet kubeadm kubectl
sudo apt-mark unhold kubelet kubeadm kubectl
ls /etc/kubernetes/manifests
ls /etc/kubernetes/pki


etcdctl

Set the API version once per shell. Certificates below are the kubeadm defaults. Read /etc/kubernetes/manifests/etcd.yaml if this cluster uses different paths.


bash
export ETCDCTL_API=3
export ETCDCTL_ENDPOINTS=https://127.0.0.1:2379
export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt
export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/server.crt
export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/server.key

sudo -E etcdctl endpoint health
sudo -E etcdctl endpoint status --write-out=table
sudo -E etcdctl member list --write-out=table
sudo -E etcdctl snapshot save /opt/etcd-backup.db
sudo etcdctl snapshot status /opt/etcd-backup.db --write-out=table
sudo etcdctl snapshot restore /opt/etcd-backup.db --data-dir=/var/lib/etcd-restore


sudo -E keeps the ETCDCTL_* variables. After restore, point the etcd static Pod manifest hostPath and --data-dir at the new directory. The kubelet restarts etcd when that file changes.

Find the live paths when the lab is non-standard:


bash
sudo grep -E 'data-dir|listen-client-urls|advertise-client-urls|cert-file|key-file|trusted-ca' \
  /etc/kubernetes/manifests/etcd.yaml


When kubectl cannot reach the API


On the node:


bash
sudo systemctl status kubelet containerd --no-pager
sudo systemctl restart kubelet
sudo systemctl enable --now kubelet containerd
sudo journalctl -u kubelet --since "20 min ago" --no-pager
sudo journalctl -u kubelet -u containerd -p err --since "1 hour ago" --no-pager

sudo crictl ps -a
sudo crictl pods
sudo crictl logs <container-id>
sudo crictl inspect <container-id>
sudo crictl images
ls /var/log/pods
ls /etc/cni/net.d
ls /opt/cni/bin


crictl reads /etc/crictl.yaml for the runtime socket. If it hangs, that file is missing or containerd is down.

Static Pod restart without deleting the definition: move the manifest out and back.


bash
sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
sleep 20
sudo mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/


Health once the API answers again:

kubectl get --raw='/readyz?verbose'
kubectl get --raw='/livez?verbose'

Host network and OS checks


bash
hostname
hostnamectl
cat /sys/class/dmi/id/product_uuid
swapon --show
sudo swapoff -a
free -h
df -h
df -hi
ip addr
ip route
ss -lntup | grep -E '6443|2379|10250'

sysctl net.ipv4.ip_forward
sysctl net.bridge.bridge-nf-call-iptables
sudo modprobe overlay
sudo modprobe br_netfilter

ps aux | grep kubelet
ps aux | grep etcd
sudo containerd config dump | grep SystemdCgroup


Pod CIDR and bridge interfaces show up in ip addr and ip route after the CNI is healthy. ss showing nothing on 6443 means the apiserver process is not listening.


Helm and Kustomize


bash
helm repo add <name> <url>
helm repo update
helm search repo <chart>
helm show values <repo>/<chart>
helm install <release> <repo>/<chart> -n <ns> --create-namespace -f values.yaml
helm install <release> <repo>/<chart> -n <ns> --set key=value
helm list -A
helm status <release> -n <ns>
helm get values <release> -n <ns>
helm get manifest <release> -n <ns>
helm history <release> -n <ns>
helm upgrade <release> <repo>/<chart> -n <ns> -f values.yaml
helm upgrade --install <release> <repo>/<chart> -n <ns> -f values.yaml
helm rollback <release> <revision> -n <ns>
helm uninstall <release> -n <ns>

kubectl kustomize ./overlays/prod
kubectl apply -k ./overlays/prod
kubectl diff -k ./overlays/prod
kubectl delete -k ./overlays/prod


kubectl apply -f on a directory does not run Kustomize. The flag is -k.

One-page change loop


bash
kubectl config use-context <context>
kubectl config set-context --current --namespace=<ns>
kubectl get pods -o wide
kubectl describe pod <pod>
kubectl logs <pod> --previous
# fix with create / set / edit / apply
kubectl get pods -o wide
kubectl auth can-i <verb> <resource> --as <user> -n <ns>


For a node fix, finish on kubectl get nodes showing Ready, and uncordon if you drained.

Official docs