॥ श्री ॥

Kubernetes — Troubleshooting

Self-Hosting & Servers 2026-08-28

Troubleshooting

General cluster issues

IssueSolution
kubectl: connection refusedsudo systemctl status k3s; verify kubeconfig server: IP
Node shows NotReadykubectl describe node <n>; check CNI pods in kube-system; verify br_netfilter loaded
Pod stuck in PendingNo nodes have enough resources, or PVC not bound — check StorageClass exists
Pod stuck in CrashLoopBackOffkubectl logs <pod> --previous; check env vars and volume mounts
Pod stuck in ImagePullBackOffImage name/tag wrong; registry unreachable; missing imagePullSecret
Pod OOMKilledContainer exceeded memory limit — kubectl describe pod <pod> shows Reason: OOMKilled; increase limits.memory or reduce app memory usage; use Goldilocks to right-size
Pod OOMKilled on node startupNode-level vm.max_map_count too low (Elasticsearch etc.) — set vm.max_map_count=524288 in sysctl
Namespace stuck TerminatingFinalizers blocking deletion — `kubectl get namespace -o json \jq '.spec.finalizers = []' \kubectl replace --raw "/api/v1/namespaces//finalize" -f -`
etcdserver: mvcc: database space exceededetcd DB too large — run compaction and defragmentation (see etcd Operations section)
Node DiskPressureClean up unused images: crictl rmi --prune; check Longhorn replica space

Distribution-specific

IssueSolution
MicroK8s permission deniedsudo usermod -aG microk8s $USER then log out/in
MicroK8s addon enable failsmicrok8s status; sudo snap logs microk8s
minikube start fails with Podman driversystemctl --user start podman.socket; minikube delete then re-create
minikube ImagePullBackOff after image loadConfirm image name matches exactly; check with minikube image ls
k3s agent not joiningVerify token matches /var/lib/rancher/k3s/server/node-token; check firewall allows 6443
kubeadm node stays NotReadyCNI not installed — apply CNI manifest immediately after kubeadm init
kubeadm certificate has expiredsudo kubeadm certs renew all && sudo systemctl restart kubelet
kubeadm init: container runtime not runningsudo systemctl status containerd; verify --cri-socket flag

Cilium / Networking

IssueSolution
Pods can't reach each other after Cilium installDelete stale config: sudo rm /etc/cni/net.d/10-flannel.conflist; restart pods
hubble observe returns no flowskubectl -n kube-system get pods -l k8s-app=hubble-relay
L7 policy not enforcedVerify envoy.enabled=true (implied by Cilium 1.17+); check cilium-envoy DaemonSet
WireGuard broken after node reboot`lsmodgrep wireguard; sudo modprobe wireguard`
kube-proxy still runningk3s not started with --disable-kube-proxy; reinstall with the flag
cilium status shows errorscilium connectivity test; check cilium DaemonSet pods in kube-system

Ingress / Gateway

IssueSolution
Ingress returns 404Verify ingressClassName: nginx matches controller; check service name and port
NGF GatewayClass not AcceptedCheck NGF logs; confirm Gateway API CRDs installed at correct version
NGF returns 404 for all requestsAdd header_up Host {host} inside Caddy's reverse_proxy block
NGF HTTPRoute not AcceptedCheck sectionName matches listener; verify parentRef namespace; check ReferenceGrant
Cross-namespace route returning 503ReferenceGrant must be in the target namespace; kubectl get referencegrant -A
NGF NodePort 30080 not reachablekubectl -n nginx-gateway get svc nginx-gateway-nginx — confirm 80:30080/TCP
NGF data plane OOMKilledIncrease nginx.container.resources.limits.memory to 1Gi minimum
ObservabilityPolicy CRD conflict on upgradeRe-apply deploy/crds.yaml from the new NGF version

Storage

IssueSolution
Longhorn volume stuck Attachingsudo systemctl status iscsid; check Longhorn manager logs
Longhorn volume degradedReplica on unavailable node — Longhorn rebuilds once node returns
PDB blocks node drainkubectl describe pdb; temporarily patch minAvailable: 0 if safe, then restore

GitOps & Delivery

IssueSolution
ArgoCD app OutOfSync after applyAdd ignoreDifferences to Application spec for server-side mutated fields
ArgoCD unable to connect to ForgejoUse HTTPS; add --insecure-skip-server-verification for self-signed cert
Helm upgrade fails mid-releasehelm rollback <release> -n <ns>; if stuck pending-upgrade, delete the stuck secret
Argo Rollouts stuck at canary weightVerify canaryService and stableService exist; kubectl argo rollouts get rollout myapp
Kargo Warehouse not discovering imagesCheck image registry credentials; verify semverConstraint matches published tags
Kargo promotion stuckkubectl -n myapp describe promotion <n>; verify ArgoCD app name matches stage config

Secrets

IssueSolution
Sealed secret not decryptingSealing key must match — never delete sealed-secrets-key; back it up
ExternalSecret stuck SecretSyncedErrorkubectl describe externalsecret <n> — wrong remoteRef.key, bad permissions, or unreachable backend
ESO not refreshing secretDecrease refreshInterval for testing; check ESO operator logs

Autoscaling

IssueSolution
HPA shows <unknown> for CPUresources.requests.cpu must be set — HPA calculates current / requested
VPA and HPA conflictNever run both on same metric (CPU/memory); HPA on external metrics + VPA for sizing
KEDA ScaledObject shows 0 replicas but queue has messagesCheck kubectl describe scaledobject for trigger errors; verify secret ref for queue credentials
KEDA scale-to-zero doesn't recoverCheck pollingInterval and cooldownPeriod; confirm trigger metric is reachable from KEDA namespace
Cluster Autoscaler not scaling upCheck cluster-autoscaler-status ConfigMap; ensure node group max not hit; check for unschedulable pods vs pending pods
StatefulSet pod stuck TerminatingCheck finalizers: `kubectl get pod -o json \jq .metadata.finalizers`
Init container stuck Init:0/1kubectl logs <pod> -c <init-container-name>

Certificates

IssueSolution
cert-manager Certificate stuck Pendingkubectl describe certificate <n> → look at CertificateRequest and Order events
cert-manager HTTP-01 challenge failingDomain must resolve publicly; check kubectl get challenges -A
cert-manager DNS-01 challenge failingCheck Cloudflare/provider credentials; kubectl describe challenge -A; verify TXT record propagated
cert-manager ACME account not foundDelete and recreate the ClusterIssuer privateKeySecretRef secret
Certificate in Ready: False loopkubectl describe certificaterequest -A; look for rate limit errors from Let's Encrypt (429)
cert-manager pods crashlooping after CRD installCRD version mismatch — reinstall with --set installCRDs=true or apply CRDs manually first
trust-manager bundle not appearing in namespaceNamespace missing trust: enabled label; kubectl label namespace myapp trust=enabled
Internal CA cert not trusted by podstrust-manager Bundle not applied; check kubectl get bundle -A and namespace label
kubeadm cert expiry breaking clustersudo kubeadm certs check-expiration; renew with sudo kubeadm certs renew all && sudo systemctl restart kubelet

Observability

IssueSolution
k9s shows no resourcesCheck active namespace :ns; switch context :ctx
Dashboard Unauthorizedkubectl -n kubernetes-dashboard create token admin-user
Headlamp shows no clustersEnsure kubeconfig mounted read-only; server: URL reachable from container
Loki shows no logsCheck Promtail/Alloy pods; verify lokiAddress matches Loki service name
Loki ingestion rate limit errorsIncrease ingestionRate and ingestionBurstSize in Loki values; or reduce log volume with Promtail pipeline stages
Tempo shows no tracesCheck OTel Collector receiving spans; verify endpoint in Instrumentation CRD
Prometheus scraping fails (connection refused)Target pod has no metrics port; ServiceMonitor label doesn't match serviceMonitorSelector; check kubectl get servicemonitor -A
Grafana datasource "no data" for PrometheusURL must be http://kube-prometheus-stack-prometheus.monitoring.svc:9090; test with Explore tab
AlertManager not sendingConfig YAML invalid — run amtool check-config alertmanager.yaml; check inhibit rules aren't silencing everything
PrometheusRule alerts not showing in AlertManagerLabels must include release: kube-prometheus-stack; check kubectl get prometheusrule -A
SonarQube / Elasticsearch OOMvm.max_map_count=524288 on host; restart pod

etcd

IssueSolution
etcdserver: mvcc: database space exceededRun compact + defrag (see etcd Operations section); increase --quota-backend-bytes
etcd leader election constantly changingClock skew between nodes — ensure NTP is synced: timedatectl status; check etcdctl endpoint status
etcd cluster has no quorum (2 of 3 nodes down)Force new cluster from snapshot: k3s server --cluster-reset; restore latest etcd snapshot
etcd high latency (>100ms p99)Disk I/O contention — move etcd data to a dedicated SSD; check etcdctl endpoint status --write-out=table
k3s etcd snapshot restore failsEnsure k3s is stopped (systemctl stop k3s); correct path in --cluster-reset-restore-path; restart k3s after reset
etcd request timeout in API server logsetcd overloaded; check etcd_disk_wal_fsync_duration_seconds_bucket in Prometheus

Policy & Hardening

IssueSolution
conftest passes locally but fails in CIEnsure --policy path and --all-namespaces flag match CI config
kubeconform fails on CRD resourcesAdd -schema-location for CRD catalog URL; use --ignore-missing-schemas during migration
kube-bench says API server flags missingFor k3s, set flags via kube-apiserver-arg: in /etc/rancher/k3s/config.yaml
PSA blocks system namespace podsAdd pod-security.kubernetes.io/enforce=privileged to kube-system before enforcing elsewhere
Kyverno webhook times outkubectl get pods -n kyverno; scale replicas; check --webhookTimeout

Multi-Tenancy

IssueSolution
vCluster pods stuck PendingCheck host cluster has resources; verify storageClass exists in host namespace
vCluster kubeconfig connection refusedEnsure port-forward is running: vcluster connect <name> -n <ns>
Kubernetes Audit logs not appearing in LokiVerify Alloy kubernetes_audit config; check --audit-log-path in k3s config

Multi-Cluster & Registry

IssueSolution
Submariner tunnel not establishingCheck UDP 4500/4800 between nodes; verify broker token; subctl diagnose all
Zot push rejected 401Verify htpasswd credentials; check auth.htpasswd.path in config.json
Admiralty pods stuck PendingCheck MultiClusterSchedulingProfile on target cluster; verify Admiralty version compatibility
Harbor push fails: unknown blobHarbor storage PVC full — check kubectl -n harbor get pvc
Harbor DB migration error on upgradeCheck harbor-database pod logs; run migration job manually if needed

Alerting

IssueSolution
AlertManager not sending alertsCheck kubectl -n monitoring get pods; view config: kubectl -n monitoring get secret alertmanager-main -o yaml
PrometheusRule not picked upLabels must match prometheus.prometheusSpec.ruleSelector; add release: kube-prometheus-stack label
ServiceMonitor metrics missingLabels must match prometheus.serviceMonitorSelector; check kubectl get servicemonitor -A
Grafana OnCall not receiving alertsVerify Grafana alert notification policy points to OnCall integration
Beyla shows no metricsCheck DaemonSet is running; verify kernel ≥5.8; check eBPF capabilities (SYS_ADMIN or CAP_BPF)

Troubleshooting — Advanced Debug Flows

kubectl Quick Debug Flows

# ---- Pod won't start ----
kubectl describe pod <pod> -n myapp           # check Events section
kubectl logs <pod> -n myapp --previous        # logs from last crash
kubectl get events -n myapp --sort-by='.lastTimestamp' | tail -20

# ---- Service not reachable ----
# 1. Confirm endpoints exist
kubectl get endpoints myapp -n myapp          # should show pod IPs
# 2. Test from inside the cluster
kubectl run curl --rm -it --restart=Never --image=curlimages/curl -- \
  curl -v http://myapp.myapp.svc.cluster.local:8080/health
# 3. Check NetworkPolicy isn't blocking
hubble observe --to-pod myapp/<pod> --verdict DROPPED

# ---- Node is NotReady ----
kubectl describe node <node>                  # check Conditions section
ssh <node> 'sudo journalctl -u kubelet -n 50'
ssh <node> 'sudo systemctl status containerd'

# ---- PVC stuck Pending ----
kubectl describe pvc myapp-data -n myapp      # check Events
kubectl get sc                                # confirm StorageClass exists
kubectl get pods -n longhorn-system           # check CSI driver pods

# ---- OOMKilled ----
kubectl describe pod <pod> -n myapp | grep -A5 "OOMKilled"
kubectl top pod <pod> -n myapp --containers
# Fix: increase limits or fix memory leak

# ---- CrashLoopBackOff ----
kubectl logs <pod> -n myapp --previous
kubectl exec -it <pod> -n myapp -- /bin/sh    # if shell available
kubectl debug -it <pod> --image=busybox --target=myapp -n myapp  # if distroless

# ---- Certificate not provisioning ----
kubectl get certificate -n myapp
kubectl get certificaterequest -n myapp
kubectl get order -n myapp                    # ACME HTTP-01 / DNS-01 state
kubectl get challenge -n myapp               # challenge in progress?
kubectl describe challenge -n myapp          # detailed ACME error

# ---- ArgoCD OutOfSync (ignoring normal fields) ----
# ignoreDifferences for fields that Kubernetes/operators mutate:
spec:
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas           # if HPA manages replicas
    - group: ""
      kind: Service
      jsonPointers:
        - /spec/clusterIP          # assigned by Kubernetes
        - /spec/clusterIPs

Resource Debugging Checklist

# Full resource dump for a namespace — useful for incident handoff
kubectl get all,cm,secret,pvc,ingress,httproute,certificate,externalsecret \
  -n myapp -o yaml > /tmp/myapp-snapshot-$(date +%Y%m%d-%H%M).yaml

# Compare two snapshots
diff /tmp/myapp-snapshot-before.yaml /tmp/myapp-snapshot-after.yaml

# Cluster-wide resource count (spot runaway resource creation)
kubectl get pods -A --no-headers | wc -l
kubectl get pvc -A --no-headers | wc -l

# Top nodes and pods
kubectl top nodes
kubectl top pods -A --sort-by=memory | head -20
kubectl top pods -A --sort-by=cpu | head -20

# Find who owns a pod (trace back to Deployment/StatefulSet)
kubectl tree pod myapp-xyz -n myapp    # requires krew tree plugin