Kubernetes Cluster AdministrationkubectlKubernetes CLIKubernetes Troubleshooting

Article & Tutorial

kubectl Commands Explained: Practical Kubernetes CLI Guide

A practical, safety-first kubectl guide for inspecting, applying, troubleshooting, and managing Kubernetes resources.

kubectl terminal communicating safely with the Kubernetes API
kubectl terminal communicating safely with the Kubernetes API
Contents

kubectl is the command-line client for talking to the Kubernetes API. This guide is a reviewed, version-aware field guide: commands use a disposable kubectl-demo namespace, explicit scope, safe placeholders, and verification after changes. Exact behavior depends on Kubernetes version, distribution, permissions, and installed APIs.

kubectl terminal communicating safely with the Kubernetes API and a demo cluster
A local terminal sends reviewed commands through kubectl to the Kubernetes API; cluster changes remain subject to authorization and review.

What kubectl is

kubectl builds authenticated API requests, sends them to the API server, and formats the response for a human or script. It does not bypass authorization or make a cluster safe by itself. A successful command means the API accepted the request, not that the workload is healthy.

Version compatibility

Check the client version before troubleshooting. Client and server versions have a supported compatibility policy, but there is no universal promise that every command or field behaves identically across releases and distributions. Confirm the target cluster's supported version and API resources.

version.sh
kubectl version --client
# If authorized and supported by the cluster:
kubectl version

Kubeconfig safety

Kubeconfig files can contain cluster endpoints and identity material. Keep them permission-restricted, out of source control and chat, and do not print credential-bearing fields. Use a deliberately selected context before any command that can mutate state.

context.sh
kubectl config get-contexts
kubectl config current-context
kubectl config use-context <context-name>
kubectl config view --minify
kubectl config set-context --current --namespace=kubectl-demo

Cluster, context and namespace inspection

Start with read-only discovery. These commands reveal the cluster connection and available API surface without changing an object. Output can still contain sensitive names, so share only the minimum needed for diagnosis.

discover.sh
kubectl cluster-info
kubectl api-resources
kubectl api-versions
kubectl get namespaces
kubectl get nodes -o wide

Resource discovery

Resource names and fields vary with installed APIs. Use api-resources to discover names and kubectl explain to inspect the schema exposed by the server. Recursive output is useful for exploration but should be checked against the target version.

schema.sh
kubectl explain deployment
kubectl explain deployment.spec
kubectl explain deployment.spec.template --recursive

Get and describe

Use get for a compact collection view and describe for an object-oriented diagnostic view. Keep the namespace explicit for namespaced resources and use a placeholder Pod name rather than copying a live identifier into a runbook.

inspect.sh
kubectl get pods -n kubectl-demo
kubectl get deployments -n kubectl-demo
kubectl get services -n kubectl-demo
kubectl describe pod <pod-name> -n kubectl-demo
kubectl get pod <pod-name> -n kubectl-demo -o yaml

Declarative apply workflow

Prefer reviewed, version-controlled manifests for durable environments. kubectl apply compares the desired declaration with the object managed through the API. Review the file and diff first, apply with an explicit namespace, then verify rollout and events.

apply.sh
kubectl diff -f deployment.yaml -n kubectl-demo
kubectl apply -f deployment.yaml -n kubectl-demo
kubectl apply -f . -n kubectl-demo
kubectl rollout status deployment/demo-web -n kubectl-demo

Create and dry-run

Client-side dry-run renders a proposed object without sending it to the server. It is useful for learning and generating a starting manifest, but server-side validation and admission can differ. The current form uses no deprecated generator flag.

generate.sh
kubectl create deployment demo-web \
  --image=nginx:1.27 \
  --namespace=kubectl-demo \
  --dry-run=client \
  -o yaml

Deployment YAML example

This safe example uses apps/v1, a dedicated namespace, matching labels, and bounded resource settings. Replace the placeholder image only after reviewing its provenance and the target cluster policy.

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-web
  namespace: kubectl-demo
  labels:
    app.kubernetes.io/name: demo-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: demo-web
  template:
    metadata:
      labels:
        app.kubernetes.io/name: demo-web
    spec:
      containers:
        - name: web
          image: melochip/demo-web:1.0
          ports:
            - name: http
              containerPort: 8080
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              cpu: 250m
              memory: 256Mi

Matching ClusterIP Service

The ClusterIP Service stays inside the cluster. Its selector matches the Deployment Pod-template label and its named target port avoids embedding a changing Pod identity.

service.yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-web
  namespace: kubectl-demo
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: demo-web
  ports:
    - name: http
      port: 80
      targetPort: http

Edit and patch

kubectl edit opens a live object for interactive changes. It is easy to lose review context or overwrite a field managed by another controller, so prefer a reviewed manifest for durable changes. A narrowly scoped patch can be appropriate for a deliberate label update.

patch.sh
kubectl label deployment/demo-web app.kubernetes.io/part-of=kubectl-lab -n kubectl-demo
kubectl annotate deployment/demo-web docs.example/owner=team-placeholder -n kubectl-demo
kubectl patch deployment/demo-web -n kubectl-demo --type=merge -p '{"spec":{"replicas":2}}'
kubectl get deployment/demo-web -n kubectl-demo --show-labels

Labels and annotations

Labels support selection and grouping; annotations hold non-identifying metadata that is not normally used for selection. --overwrite is explicit because it replaces an existing value. Verify the result and confirm that a selector was not accidentally changed.

metadata.sh
kubectl label deployment/demo-web environment=lab -n kubectl-demo
kubectl label deployment/demo-web environment=reviewed --overwrite -n kubectl-demo
kubectl annotate deployment/demo-web docs.example/review=complete -n kubectl-demo
kubectl get deployment/demo-web -n kubectl-demo -o jsonpath='{.metadata.labels}'

Logs

Bound log output while diagnosing a workload. Select a container explicitly in a multi-container Pod, use --previous for a restarted container, and avoid copying application secrets or unbounded output into tickets.

logs.sh
kubectl logs <pod-name> -n kubectl-demo --tail=100
kubectl logs <pod-name> -n kubectl-demo -c web --tail=100
kubectl logs <pod-name> -n kubectl-demo -c web --previous --tail=100
kubectl logs -l app.kubernetes.io/name=demo-web -n kubectl-demo --all-containers=true --tail=50

Exec

Exec starts a process inside a running container. It is authorization-sensitive, the requested shell must exist in the image, and it is a diagnostic aid—not a replacement for a reproducible image or deployment.

exec.sh
kubectl exec -n kubectl-demo -it <pod-name> -- /bin/sh

Port forwarding

Bind a local port to loopback when forwarding a Service. This keeps the listener off other network interfaces; access still depends on local host security and cluster authorization.

port-forward.sh
kubectl port-forward \
  --address 127.0.0.1 \
  -n kubectl-demo \
  service/demo-web 8080:80

Rollout status, history, restart and undo

A Deployment rollout can be observed, restarted, or rolled back. Undo depends on retained revision history and does not prove that the reverted workload is healthy; verify status, Pods, events, and application behavior afterward.

rollout.sh
kubectl rollout status deployment/demo-web -n kubectl-demo
kubectl rollout history deployment/demo-web -n kubectl-demo
kubectl rollout restart deployment/demo-web -n kubectl-demo
kubectl rollout undo deployment/demo-web -n kubectl-demo
kubectl get deployments,pods -n kubectl-demo

Scale

Manual scaling changes the Deployment's replica count. An autoscaling controller can later change that value, so document the owner of scaling decisions before using this command in a managed environment.

scale.sh
kubectl scale deployment/demo-web --replicas=3 -n kubectl-demo
kubectl get deployment/demo-web -n kubectl-demo

Events and troubleshooting

Use kubectl events where the installed client supports it. The get-events form is a compatible fallback. Events are useful diagnostic observations, not permanent audit records; correlate them with object status and controller logs.

events.sh
kubectl events -n kubectl-demo
kubectl get events -n kubectl-demo --sort-by=.metadata.creationTimestamp
kubectl describe pod <pod-name> -n kubectl-demo

JSONPath and custom-column output

Choose output formats for the task. JSONPath expressions are quoted for a POSIX shell; custom columns are easier to review when a small, stable set of fields is enough.

output.sh
kubectl get pods -n kubectl-demo -o wide
kubectl get deployment/demo-web -n kubectl-demo -o yaml
kubectl get deployment/demo-web -n kubectl-demo -o json
kubectl get pods -n kubectl-demo -o name
kubectl get pods -n kubectl-demo -o custom-columns='NAME:.metadata.name,READY:.status.containerStatuses[*].ready,PHASE:.status.phase'
kubectl get pod <pod-name> -n kubectl-demo -o jsonpath='{.metadata.name}'

Delete and cleanup safety

Deletion is asynchronous and can be delayed by finalizers. Inspect the exact object and diff before removing it, use an explicit namespace and name, and verify that the intended resource disappeared. Never use blanket deletion or target kube-system as a shortcut.

cleanup.sh
kubectl diff -f deployment.yaml -n kubectl-demo
kubectl get deployment/demo-web service/demo-web -n kubectl-demo
# Cleanup is destructive; run only after reviewing this disposable namespace.
# kubectl delete deployment/demo-web service/demo-web -n kubectl-demo
# kubectl delete namespace kubectl-demo

Common mistakes

  • Running a mutation against the current context without checking its name and namespace.
  • Treating client-side dry-run output as proof that server admission will accept an object.
  • Using imperative edits for durable state without updating the reviewed manifest.
  • Dumping Secrets or credential-bearing kubeconfig fields with YAML or JSON output.
  • Assuming logs are safe to paste without checking for application secrets.
  • Binding port-forward to every interface instead of loopback.
  • Assuming events are an audit trail or that manual scaling wins over an autoscaler.

Practical troubleshooting workflow

  1. 1
    Confirm scope

    Check client version, current context, namespace, and authorization before reading or changing anything.

  2. 2
    Inspect the object

    Use get, describe, events, and bounded logs to form a hypothesis.

  3. 3
    Compare desired state

    Review the manifest and kubectl diff, then compare selectors, labels, requests, and status.

  4. 4
    Make one reviewed change

    Apply a narrow, reversible change in kubectl-demo and record the expected observation.

  5. 5
    Verify and document

    Check rollout, Pods, Service endpoints, events, and logs; preserve only safe diagnostic evidence.

Quick reference

TaskSafe starting command
Versionkubectl version --client
Contextkubectl config current-context
Schemakubectl explain deployment.spec
Inspectkubectl get pods -n kubectl-demo
Applykubectl diff -f deployment.yaml -n kubectl-demo
Rolloutkubectl rollout status deployment/demo-web -n kubectl-demo
Eventskubectl events -n kubectl-demo
Logskubectl logs -n kubectl-demo --tail=100

Conclusion

kubectl is most effective when it is paired with reviewed declarative configuration, least-privilege access, bounded diagnostics, and explicit verification. The commands here provide a safe learning path without pretending that one command set covers every Kubernetes release or distribution.

Related Kubernetes learning sequence

Did this help?

Yes No

Join the discussion

0 Comments

Ask questions, add context, or share what worked.

Sign in to join the discussion

No comments yet. Start the discussion.

More from Melochip Editorial

Related articles

Stay in the loop. Get new Melochip articles

Receive Melochip article updates when new articles are available. Explicit opt-in only.

No pre-checked boxes. Unsubscribe support is part of the subscriber foundation.