Cloud native command cheat sheet
The commands behind the four non-Kubernetes KCNA domains - the container runtime, observability, delivery and security - each with the output it actually produced on a four-node cluster.
- OSUbuntu 26.04 LTS
- Kubernetes1.36.4
- containerdv2.2.6
- crictlv1.36.0
- Chartkube-prometheus-stack 88.5.3
- Commands30
- Reviewed22 August 2026
Container runtime
-
sudo -n crictl versionWhich runtime the kubelet is talking to, and which CRI API version it speaks.
bash Example session sudo -n crictl versionVersion: 0.1.0RuntimeName: containerdRuntimeVersion: v2.2.6RuntimeApiVersion: v1 -
sudo -n grep -E 'container-runtime-endpoint|containerRuntimeEndpoint' /var/lib/kubelet/kubeadm-flags.env /var/lib/kubelet/config.yaml 2>&1 | head -4The socket the kubelet uses. There is no remote CRI - runtime and kubelet are always on the same host.
bash Example session sudo -n grep -E 'container-runtime-endpoint|containerRuntimeEndpoint' /var/lib/kubelet/kubeadm-flags.env /var/lib/kubelet/config.yaml 2>&1 | head -4/var/lib/kubelet/config.yaml:containerRuntimeEndpoint: unix:///run/containerd/containerd.sock -
sudo -n crictl pods --namespace kube-system --no-trunc | head -6Pod sandboxes as the runtime sees them. Still answers when the API server does not.
bash Example session sudo -n crictl pods --namespace kube-system --no-trunc | head -6POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIMEf78b2e72fa90e716ed0f1a7e61da14177936709dcf77552ea1aa8e6c6d272ed5 16 hours ago Ready kube-proxy-mzbdk kube-system 0 (default)2e721d7a13ba458b2eb0dbd6bcc5ddc70b6465a29ad37b39c65a048d3735034a 16 hours ago Ready kube-controller-manager-cka1001 kube-system 0 (default)49a1e14c7e36286cc7186efef6e30378f556834723e5d367cfc059fb0890f897 16 hours ago Ready kube-scheduler-cka1001 kube-system 0 (default) -
sudo -n ctr -n k8s.io containers ls | grep -c pauseOne pause container per sandbox. The count should equal your Pod count on this node.
bash Example session sudo -n ctr -n k8s.io containers ls | grep -c pause10 -
sudo -n grep -m1 cgroupDriver /var/lib/kubelet/config.yamlThe kubelet side of the cgroup driver. Must match the runtime, or memory accounting silently misbehaves.
bash Example session sudo -n grep -m1 cgroupDriver /var/lib/kubelet/config.yamlcgroupDriver: systemd
Prometheus and PromQL
-
kubectl --context cka1001 -n monitoring exec promq -- curl -sG http://kps-kube-prometheus-stack-prometheus:9090/api/v1/query --data-urlencode 'query=count(up)'How many scrape targets exist. The first query to run on any Prometheus.
bash Example session kubectl --context cka1001 -n monitoring exec promq -- curl -sG http://kps-kube-prometheus-stack-prometheus:9090/api/v1/query --data-urlencode 'query=count(up)'{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1787345650.435,"33"]}]}} -
kubectl --context cka1001 -n monitoring exec promq -- curl -sG http://kps-kube-prometheus-stack-prometheus:9090/api/v1/query --data-urlencode 'query=group by (job) (up == 0)'Which jobs have failing targets. A count is not a diagnosis; the job names are.
bash Example session kubectl --context cka1001 -n monitoring exec promq -- curl -sG http://kps-kube-prometheus-stack-prometheus:9090/api/v1/query --data-urlencode 'query=group by (job) (up == 0)'{"status":"success","data":{"resultType":"vector","result":[{"metric":{"job":"kube-proxy"},"value":[1787345655.967,"1"]},{"metric":{"job":"kube-scheduler"},"value":[1787345655.967,"1"]},{"metric":{"job":"kube-controller-manager"},"value":[1787345655.967,"1"]},{"metric":{"job":"kube-etcd"},"value":[1787345655.967,"1"]}]}} -
kubectl --context cka1001 -n monitoring exec promq -- curl -sG http://kps-kube-prometheus-stack-prometheus:9090/api/v1/query --data-urlencode 'query=sum by (node) (kube_pod_info) 'Pod count per node, from kube-state-metrics. Answers "is scheduling even?".
bash Example session kubectl --context cka1001 -n monitoring exec promq -- curl -sG http://kps-kube-prometheus-stack-prometheus:9090/api/v1/query --data-urlencode 'query=sum by (node) (kube_pod_info) '{"status":"success","data":{"resultType":"vector","result":[{"metric":{"node":"cka1001-node01"},"value":[1787345664.893,"16"]},{"metric":{"node":"cka1001-node02"},"value":[1787345664.893,"28"]},{"metric":{"node":"cka1001-node03"},"value":[1787345664.893,"20"]},{"metric":{"node":"cka1001"},"value":[1787345664.893,"10"]},{"metric":{},"value":[1787345664.893,"1"]}]}} -
kubectl --context cka1001 -n monitoring exec promq -- sh -c "curl -s http://alertmanager-operated:9093/api/v2/alerts | tr ',' '\n' | grep -c alertname"How many alerts Alertmanager is currently holding. Prometheus fires them; Alertmanager routes them.
bash Example session kubectl --context cka1001 -n monitoring exec promq -- sh -c "curl -s http://alertmanager-operated:9093/api/v2/alerts | tr ',' '\n' | grep -c alertname"20 -
kubectl --context cka1001 -n monitoring get configmap -l grafana_dashboard=1 --no-headers | wc -lDashboards delivered as ConfigMaps and loaded by a sidecar. Editing them in the UI does not persist.
bash Example session kubectl --context cka1001 -n monitoring get configmap -l grafana_dashboard=1 --no-headers | wc -l29
GitOps with Argo CD
-
kubectl --context cka1001 apply --server-side -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml 2>&1 | tail -4Install or update Argo CD. Server-side apply avoids the 256 KB annotation limit that breaks the plain apply.
bash Example session kubectl --context cka1001 apply --server-side -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml 2>&1 | tail -4* You may co-own fields by updating your manifest to match the existing value; in this case, you'll become the manager if the other manager(s) stop managing the field (remove it from their configuration). -
kubectl --context cka1001 -n argocd get application guestbook -o custom-columns=NAME:.metadata.name,REVISION:.status.sync.revision,SYNC:.status.sync.status,HEALTH:.status.health.statusThe exact commit an Application reconciled, plus sync and health. Sync and health are independent.
bash Example session kubectl --context cka1001 -n argocd get application guestbook -o custom-columns=NAME:.metadata.name,REVISION:.status.sync.revision,SYNC:.status.sync.status,HEALTH:.status.health.statusNAME REVISION SYNC HEALTHguestbook 8088f4c0d970abb09e250248cc97e35623447cb5 Synced Progressing -
kubectl --context cka1001 get crd -o name | grep argoproj.ioConfirm all three CRDs exist. A partial install leaves ApplicationSet missing and fails weeks later.
bash Example session kubectl --context cka1001 get crd -o name | grep argoproj.iocustomresourcedefinition.apiextensions.k8s.io/applications.argoproj.iocustomresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.iocustomresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io -
kubectl --context cka1001 -n guestbook scale deploy/guestbook-ui --replicas=3CautionWith selfHeal on, this is reverted within a second. Change Git, not the cluster.
bash Example session kubectl --context cka1001 -n guestbook scale deploy/guestbook-ui --replicas=3deployment.apps/guestbook-ui scaled
Admission and RBAC
-
kubectl --context cka1001 label namespace psa-strict pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latestTurn on Pod Security enforcement for a namespace. Applies to new Pods only - it never evicts.
bash Example session kubectl --context cka1001 label namespace psa-strict pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latestnamespace/psa-strict labeled -
kubectl --context cka1001 -n psa-strict run rooty --image=busybox:1.37 --restart=Never --overrides='{"spec":{"containers":[{"name":"rooty","image":"busybox:1.37","command":["sleep","3600"],"securityContext":{"privileged":true}}]}}'What a rejection looks like: Forbidden at admission, naming the profile and the violation. Nothing is created.
bash Example session kubectl --context cka1001 -n psa-strict run rooty --image=busybox:1.37 --restart=Never --overrides='{"spec":{"containers":[{"name":"rooty","image":"busybox:1.37","command":["sleep","3600"],"securityContext":{"privileged":true}}]}}'Error from server (Forbidden): pods "rooty" is forbidden: violates PodSecurity "restricted:latest": privileged (container "rooty" must not set securityContext.privileged=true), allowPrivilegeEscalation != false (container "rooty" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "rooty" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "rooty" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "rooty" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")[exit 1] -
kubectl --context cka1001 auth can-i --list --as=system:serviceaccount:psa-strict:reader -n psa-strict | head -6Everything an identity may do, without logging in as it. Note what operators granted to all authenticated users.
bash Example session kubectl --context cka1001 auth can-i --list --as=system:serviceaccount:psa-strict:reader -n psa-strict | head -6Resources Non-Resource URLs Resource Names Verbsselfsubjectreviews.authentication.k8s.io [] [] [create]selfsubjectaccessreviews.authorization.k8s.io [] [] [create]selfsubjectrulesreviews.authorization.k8s.io [] [] [create] -
kubectl --context cka1001 auth can-i list pods --as=system:serviceaccount:psa-strict:reader -n defaultThe same check in another namespace. A Role grants nothing outside its own namespace.
bash Example session kubectl --context cka1001 auth can-i list pods --as=system:serviceaccount:psa-strict:reader -n defaultno[exit 1] -
sudo -n grep -E 'enable-admission-plugins|--authorization-mode' /etc/kubernetes/manifests/kube-apiserver.yamlWhat the API server enforces before any of your policy. A default cluster is permissive about Pods.
bash Example session sudo -n grep -E 'enable-admission-plugins|--authorization-mode' /etc/kubernetes/manifests/kube-apiserver.yaml - --authorization-mode=Node,RBAC - --enable-admission-plugins=NodeRestriction
The API model
-
kubectl --context cka1001 get pods -n kube-system --request-timeout=10s -v=6 2>&1 | grep -E 'GET|round_trippers' | head -4The HTTP request behind a kubectl command. Everything in Kubernetes is a client of this API.
bash Example session kubectl --context cka1001 get pods -n kube-system --request-timeout=10s -v=6 2>&1 | grep -E 'GET|round_trippers' | head -4I0822 03:03:43.698134 1480840 round_trippers.go:632] "Response" verb="GET" url="https://192.168.0.175:6443/api/v1/namespaces/kube-system/pods?limit=500&timeout=10s" status="200 OK" milliseconds=11 -
kubectl --context cka1001 get --raw='/api/v1/namespaces/kube-system/pods?limit=1' | tr ',' '\n' | grep -E '"kind"|"resourceVersion"' | head -3The raw response. Lists are typed objects, and carry the resourceVersion a watch resumes from.
bash Example session kubectl --context cka1001 get --raw='/api/v1/namespaces/kube-system/pods?limit=1' | tr ',' '\n' | grep -E '"kind"|"resourceVersion"' | head -3{"kind":"PodList""metadata":{"resourceVersion":"174912""resourceVersion":"11837" -
kubectl --context cka1001 -n hpa-demo get deploy cpu-demo -o jsonpath='{.metadata.generation} {.status.observedGeneration}{"\n"}'Whether the controller has caught up with your spec. Equal means done.
bash Example session kubectl --context cka1001 -n hpa-demo get deploy cpu-demo -o jsonpath='{.metadata.generation} {.status.observedGeneration}{"\n"}'1 1 -
kubectl --context cka1001 -n hpa-demo get pod -l app=cpu-demo -o jsonpath='{.items[0].metadata.ownerReferences[0].kind}/{.items[0].metadata.ownerReferences[0].name}{"\n"}'Who owns a Pod. Deployment to ReplicaSet to Pod - deleting the Pod achieves nothing.
bash Example session kubectl --context cka1001 -n hpa-demo get pod -l app=cpu-demo -o jsonpath='{.items[0].metadata.ownerReferences[0].kind}/{.items[0].metadata.ownerReferences[0].name}{"\n"}'ReplicaSet/cpu-demo-7dd7d449d6 -
kubectl --context cka1001 get --raw='/readyz?verbose' | head -8Control plane health, check by check. Distinguishes an unhealthy API server from a denied request.
bash Example session kubectl --context cka1001 get --raw='/readyz?verbose' | head -8[+]ping ok[+]log ok[+]etcd ok[+]etcd-readiness ok[+]informer-sync ok[+]poststarthook/start-apiserver-admission-initializer ok
Autoscaling
-
kubectl --context cka1001 -n hpa-demo get hpa cpu-demoA working HPA shows a real percentage. `<unknown>` means the target declares no requests.
bash Example session kubectl --context cka1001 -n hpa-demo get hpa cpu-demoNAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGEcpu-demo Deployment/cpu-demo cpu: 2%/60% 1 4 1 64s -
kubectl --context cka1001 -n guestbook describe hpa guestbook-ui | sed -n '/Conditions/,/Events/p' | head -8The conditions are the diagnosis. ScalingActive False with FailedGetResourceMetric is the classic missing-requests case.
bash Example session kubectl --context cka1001 -n guestbook describe hpa guestbook-ui | sed -n '/Conditions/,/Events/p' | head -8Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True SucceededGetScale the HPA controller was able to get the target's current scale ScalingActive False FailedGetResourceMetric the HPA was unable to compute the replica count: failed to get cpu utilization: missing request for cpu in container guestbook-ui of Pod guestbook-ui-5d6468fd55-cj47cEvents: -
kubectl --context cka1001 get apiservices | grep -E 'metrics|custom.metrics|external.metrics'Which metric APIs exist. Only metrics.k8s.io means CPU and memory only - no custom-metric autoscaling.
bash Example session kubectl --context cka1001 get apiservices | grep -E 'metrics|custom.metrics|external.metrics'v1beta1.metrics.k8s.io kube-system/metrics-server True 14h
The standards
-
kubectl --context cka1001 get csidriversCSI drivers register themselves as objects. An empty list means non-CSI storage, which is normal.
bash Example session kubectl --context cka1001 get csidriversNAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGEcsi.tigera.io true true false <unset> false Ephemeral 16hhostpath.csi.k8s.io true true false <unset> false Persistent,Ephemeral 8h -
sudo -n crictl info | python3 -c "import json,sys; d=json.load(sys.stdin); print('CNI networks:', [n['Config']['Name'] for n in d['cniconfig']['Networks']])"The CNI networks the runtime knows about. Pod-IP problems live here, not in any Kubernetes object.
bash Example session sudo -n crictl info | python3 -c "import json,sys; d=json.load(sys.stdin); print('CNI networks:', [n['Config']['Name'] for n in d['cniconfig']['Networks']])"CNI networks: ['cni-loopback', 'k8s-pod-network'] -
sudo -n ctr -n k8s.io content get $(sudo -n ctr -n k8s.io images ls name==registry.k8s.io/pause:3.10.1 | awk 'NR==2 {print $3}') | python3 -c "import json,sys; d=json.load(sys.stdin); print('mediaType:', d['mediaType']); print('platforms:', [m['platform']['architecture'] for m in d['manifests']][:8])"One image tag, several platform manifests. This is why the same tag runs on arm64 and amd64.
bash Example session sudo -n ctr -n k8s.io content get $(sudo -n ctr -n k8s.io images ls name==registry.k8s.io/pause:3.10.1 | awk 'NR==2 {print $3}') | python3 -c "import json,sys; d=json.load(sys.stdin); print('mediaType:', d['mediaType']); print('platforms:', [m['platform']['architecture'] for m in d['manifests']][:8])"mediaType: application/vnd.docker.distribution.manifest.list.v2+jsonplatforms: ['amd64', 'arm', 'arm64', 'ppc64le', 's390x', 'amd64', 'amd64']
No command matches that search.