Kubernetes
Essential commands and patterns for managing containerised workloads with Kubernetes.
Kubernetes
Essential commands and patterns for managing containerised workloads with Kubernetes.
Overview
Kubernetes (K8s) is a container orchestration platform that automates deployment, scaling, and management of containerised applications. It organises containers into logical units called Pods, manages their lifecycle, and provides networking and storage abstractions.
graph TB
subgraph Control Plane
API[API Server]
ETCD[(etcd)]
SCHED[Scheduler]
CM[Controller Manager]
end
subgraph Worker Node 1
KL1[Kubelet]
KP1[Kube-proxy]
subgraph Pods1[Pods]
P1[Pod A]
P2[Pod B]
end
end
subgraph Worker Node 2
KL2[Kubelet]
KP2[Kube-proxy]
subgraph Pods2[Pods]
P3[Pod C]
P4[Pod D]
end
end
API --> ETCD
API --> SCHED
API --> CM
KL1 --> API
KL2 --> API
KP1 --> API
KP2 --> API
Pod Lifecycle and Management
Pods are the smallest deployable units in Kubernetes, containing one or more containers that share storage and network resources.
Pod Lifecycle States
stateDiagram-v2
[*] --> Pending : Pod created
Pending --> Running : Containers started
Running --> Succeeded : All containers exit 0
Running --> Failed : Container exits non-zero
Running --> Unknown : Node communication lost
Failed --> [*]
Succeeded --> [*]
Unknown --> Running : Communication restored
Unknown --> Failed : Timeout
Creating Pods
# Create pod from YAML manifest
kubectl apply -f pod.yaml
# Create pod imperatively (quick testing)
kubectl run nginx --image=nginx:1.25 --port=80
# Create pod with environment variables
kubectl run myapp --image=myapp:v1 --env="ENV=production" --env="DEBUG=false"
# Create pod with resource limits (--requests/--limits were removed from kubectl run; use --overrides or a manifest)
kubectl run nginx --image=nginx:1.25 \
--overrides='{"spec":{"containers":[{"name":"nginx","image":"nginx:1.25","resources":{"requests":{"cpu":"100m","memory":"128Mi"},"limits":{"cpu":"200m","memory":"256Mi"}}}]}}'
# Create pod with specific labels
kubectl run nginx --image=nginx:1.25 --labels="app=web,tier=frontend"
Inspecting Pods
# List all pods in current namespace
kubectl get pods
# List pods with additional details (IP, node)
kubectl get pods -o wide
# List pods across all namespaces
kubectl get pods -A
# Watch pods in real-time
kubectl get pods -w
# Get detailed pod information
kubectl describe pod nginx
# Get pod YAML manifest
kubectl get pod nginx -o yaml
# Get specific fields using jsonpath
kubectl get pod nginx -o jsonpath='{.status.podIP}'
# List pods sorted by restart count
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
Viewing Logs
# View pod logs
kubectl logs nginx
# Follow logs in real-time
kubectl logs -f nginx
# View logs for specific container in multi-container pod
kubectl logs nginx -c sidecar
# View previous container logs (after restart)
kubectl logs nginx --previous
# View logs with timestamps
kubectl logs nginx --timestamps
# View last N lines of logs
kubectl logs nginx --tail=100
# View logs from last hour
kubectl logs nginx --since=1h
# View logs from all containers in pod
kubectl logs nginx --all-containers
Executing Commands in Pods
# Execute command in pod
kubectl exec nginx -- ls /usr/share/nginx/html
# Get interactive shell
kubectl exec -it nginx -- /bin/bash
# Execute command in specific container
kubectl exec -it nginx -c sidecar -- /bin/sh
# Copy files to/from pod
kubectl cp local-file.txt nginx:/tmp/file.txt
kubectl cp nginx:/var/log/nginx/access.log ./access.log
Managing Pod Lifecycle
# Delete pod
kubectl delete pod nginx
# Delete pod immediately (force)
kubectl delete pod nginx --grace-period=0 --force
# Delete all pods in namespace
kubectl delete pods --all
# Delete pods by label selector
kubectl delete pods -l app=nginx
Example Pod Manifest
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
emptyDir: {}
Deployments and ReplicaSets
Deployments manage the rollout and scaling of ReplicaSets, which in turn manage Pod replicas.
flowchart TD
A[Deployment] --> B[ReplicaSet v2 - Current]
A -.-> C[ReplicaSet v1 - Previous]
B --> D[Pod]
B --> E[Pod]
B --> F[Pod]
C -.-> G[Pod - Terminating]
style B fill:#90EE90
style C fill:#FFE4B5
Creating Deployments
# Create deployment from YAML
kubectl apply -f deployment.yaml
# Create deployment imperatively
kubectl create deployment nginx --image=nginx:1.25 --replicas=3
# Create deployment with port exposed
kubectl create deployment nginx --image=nginx:1.25 --port=80
# Generate deployment YAML without creating
kubectl create deployment nginx --image=nginx:1.25 --dry-run=client -o yaml > deployment.yaml
Scaling Deployments
# Scale to specific replica count
kubectl scale deployment nginx --replicas=5
# Scale multiple deployments
kubectl scale deployment nginx redis --replicas=3
# Autoscale based on CPU utilisation
kubectl autoscale deployment nginx --min=3 --max=10 --cpu-percent=80
# View horizontal pod autoscaler
kubectl get hpa
# Delete autoscaler
kubectl delete hpa nginx
Rolling Updates
# Update container image
kubectl set image deployment/nginx nginx=nginx:1.26
# Record a change cause for rollout history (--record has been removed)
kubectl annotate deployment/nginx kubernetes.io/change-cause="update image to nginx:1.26"
# Update environment variable
kubectl set env deployment/nginx DEBUG=true
# Check rollout status
kubectl rollout status deployment/nginx
# View rollout history
kubectl rollout history deployment/nginx
# View specific revision details
kubectl rollout history deployment/nginx --revision=2
# Pause rollout (for batching changes)
kubectl rollout pause deployment/nginx
# Resume rollout
kubectl rollout resume deployment/nginx
Rollback
# Rollback to previous revision
kubectl rollout undo deployment/nginx
# Rollback to specific revision
kubectl rollout undo deployment/nginx --to-revision=2
# Restart all pods in deployment
kubectl rollout restart deployment/nginx
Example Deployment Manifest
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Max pods over desired count
maxUnavailable: 0 # Zero downtime
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
Services and Networking
Services provide stable network endpoints for accessing Pods, with different types for various use cases.
flowchart LR
subgraph External
U[User]
LB[LoadBalancer]
end
subgraph Cluster
ING[Ingress]
NP[NodePort]
SVC[ClusterIP Service]
P1[Pod 1]
P2[Pod 2]
P3[Pod 3]
end
U --> LB
LB --> NP
U --> ING
ING --> SVC
NP --> SVC
SVC --> P1
SVC --> P2
SVC --> P3
Service Types
| Type | Description | Use Case |
|---|---|---|
| ClusterIP | Internal cluster IP only | Inter-service communication |
| NodePort | Exposes on each node's IP | Development, direct node access |
| LoadBalancer | Cloud provider load balancer | Production external access |
| ExternalName | Maps to external DNS | External service integration |
Creating Services
# Expose deployment as ClusterIP service
kubectl expose deployment nginx --port=80 --target-port=80
# Expose as NodePort
kubectl expose deployment nginx --type=NodePort --port=80 --target-port=80
# Expose as LoadBalancer
kubectl expose deployment nginx --type=LoadBalancer --port=80 --target-port=80
# Create service with specific name
kubectl expose deployment nginx --name=nginx-svc --port=80
# Create service from YAML
kubectl apply -f service.yaml
Managing Services
# List services
kubectl get svc
# List services with endpoints
kubectl get endpoints
# Get service details
kubectl describe svc nginx
# Delete service
kubectl delete svc nginx
# Get service URL (minikube)
minikube service nginx --url
Example Service Manifests
# ClusterIP Service
apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip
spec:
type: ClusterIP
selector:
app: nginx
ports:
- port: 80
targetPort: 80
---
# NodePort Service
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080 # 30000-32767 range
---
# LoadBalancer Service
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Ingress
Ingress provides HTTP/HTTPS routing to services based on host and path.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
tls:
- hosts:
- app.example.com
secretName: tls-secret
# List ingresses
kubectl get ingress
# Describe ingress
kubectl describe ingress app-ingress
# Get ingress with address
kubectl get ingress -o wide
Network Policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-nginx
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
ConfigMaps and Secrets
ConfigMaps store non-sensitive configuration data; Secrets store sensitive data like passwords and tokens.
Creating ConfigMaps
# Create from literal values
kubectl create configmap app-config \
--from-literal=DATABASE_HOST=postgres \
--from-literal=DATABASE_PORT=5432
# Create from file
kubectl create configmap nginx-config --from-file=nginx.conf
# Create from directory (each file becomes a key)
kubectl create configmap app-config --from-file=config/
# Create from env file
kubectl create configmap app-config --from-env-file=app.env
# Create from YAML
kubectl apply -f configmap.yaml
Creating Secrets
# Create generic secret from literals
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=s3cr3t
# Create from file
kubectl create secret generic tls-cert \
--from-file=cert.pem \
--from-file=key.pem
# Create TLS secret
kubectl create secret tls tls-secret \
--cert=cert.pem \
--key=key.pem
# Create Docker registry secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass \
--docker-email=user@example.com
Viewing ConfigMaps and Secrets
# List ConfigMaps
kubectl get configmaps
# View ConfigMap data
kubectl describe configmap app-config
# Get ConfigMap as YAML
kubectl get configmap app-config -o yaml
# List Secrets
kubectl get secrets
# View Secret (base64 encoded)
kubectl get secret db-credentials -o yaml
# Decode secret value
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d
Using ConfigMaps and Secrets in Pods
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:v1
# Environment variables from ConfigMap
envFrom:
- configMapRef:
name: app-config
# Environment variables from Secret
- secretRef:
name: db-credentials
# Individual environment variables
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
# Mount as volume
volumeMounts:
- name: config-volume
mountPath: /etc/config
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
- name: secret-volume
secret:
secretName: db-credentials
Example ConfigMap and Secret Manifests
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: postgres
DATABASE_PORT: "5432"
# Multi-line configuration
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
---
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData: # Use stringData for plain text (auto-encoded)
username: admin
password: s3cr3t
# Or use data with base64-encoded values
# data:
# username: YWRtaW4=
# password: czNjcjN0
Namespaces and Resource Quotas
Namespaces provide logical isolation and resource boundaries within a cluster.
Managing Namespaces
# List namespaces
kubectl get namespaces
# Create namespace
kubectl create namespace development
# Set default namespace for context
kubectl config set-context --current --namespace=development
# View current namespace
kubectl config view --minify | grep namespace
# Delete namespace (and all resources within)
kubectl delete namespace development
Working with Namespaces
# List resources in specific namespace
kubectl get pods -n development
# List resources across all namespaces
kubectl get pods -A
# Create resource in specific namespace
kubectl apply -f deployment.yaml -n development
# Run pod in specific namespace
kubectl run nginx --image=nginx -n development
Resource Quotas
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: development
spec:
hard:
# Compute resources
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
# Object counts
pods: "20"
services: "10"
secrets: "10"
configmaps: "10"
persistentvolumeclaims: "5"
Limit Ranges
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: development
spec:
limits:
- type: Container
default: # Default limits
cpu: 200m
memory: 256Mi
defaultRequest: # Default requests
cpu: 100m
memory: 128Mi
max: # Maximum allowed
cpu: "2"
memory: 2Gi
min: # Minimum allowed
cpu: 50m
memory: 64Mi
# View resource quotas
kubectl get resourcequota -n development
# View limit ranges
kubectl get limitrange -n development
# Check quota usage
kubectl describe resourcequota compute-quota -n development
Labels and Selectors
Labels are key-value pairs for organising and selecting resources.
Managing Labels
# Add label to resource
kubectl label pod nginx app=web
# Add label to all pods
kubectl label pods --all env=production
# Update existing label (overwrite)
kubectl label pod nginx app=frontend --overwrite
# Remove label
kubectl label pod nginx app-
# Show labels
kubectl get pods --show-labels
# Get pods with specific label
kubectl get pods -l app=nginx
# Get pods with label selector (equality)
kubectl get pods -l 'env=production,tier=frontend'
# Get pods with set-based selector
kubectl get pods -l 'env in (production, staging)'
# Get pods without a label
kubectl get pods -l '!app'
Using Labels in Manifests
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
version: v1.25
spec:
replicas: 3
selector:
matchLabels:
app: nginx
# Set-based selector (alternative)
# matchExpressions:
# - key: app
# operator: In
# values: [nginx, web]
template:
metadata:
labels:
app: nginx
version: v1.25
spec:
containers:
- name: nginx
image: nginx:1.25
Annotations
# Add annotation
kubectl annotate pod nginx description="Main web server"
# Update annotation
kubectl annotate pod nginx description="Updated description" --overwrite
# Remove annotation
kubectl annotate pod nginx description-
# View annotations
kubectl get pod nginx -o jsonpath='{.metadata.annotations}'
Health Checks
Probes monitor container health and control traffic routing and restarts.
flowchart TD
A[Container Starts] --> B{Startup Probe}
B -->|Pass| C{Liveness Probe}
B -->|Fail| D[Container Restart]
C -->|Pass| E{Readiness Probe}
C -->|Fail| D
E -->|Pass| F[Receive Traffic]
E -->|Fail| G[Remove from Service]
G --> E
F --> C
Probe Types
| Probe | Purpose | Failure Action |
|---|---|---|
| Startup | Check if app has started | Restart container |
| Liveness | Check if app is running | Restart container |
| Readiness | Check if app can serve traffic | Remove from service endpoints |
Probe Configuration
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:v1
ports:
- containerPort: 8080
# HTTP GET probe
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 30 # Wait before first check
periodSeconds: 10 # Check interval
timeoutSeconds: 5 # Timeout per check
successThreshold: 1 # Successes to be healthy
failureThreshold: 3 # Failures before unhealthy
# TCP socket probe
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
# Exec command probe
startupProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30 # 30 * 5 = 150s max startup time
Common Probe Patterns
# Simple HTTP endpoint
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
# gRPC health check (Kubernetes 1.24+)
livenessProbe:
grpc:
port: 50051
service: myservice
initialDelaySeconds: 10
# Database connection check
readinessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -h localhost -p 5432
periodSeconds: 10
kubectl Essential Commands
Context and Configuration
# View current context
kubectl config current-context
# List all contexts
kubectl config get-contexts
# Switch context
kubectl config use-context my-cluster
# Set default namespace
kubectl config set-context --current --namespace=development
# View kubeconfig
kubectl config view
# Merge kubeconfig files
KUBECONFIG=~/.kube/config:~/new-config kubectl config view --flatten > merged
Resource Information
# List all resource types
kubectl api-resources
# Explain resource fields
kubectl explain pod.spec.containers
# Get resource with custom columns
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase
# Get all resources in namespace
kubectl get all
# Get resources by type
kubectl get deploy,svc,pods
Output Formats
# YAML output
kubectl get pod nginx -o yaml
# JSON output
kubectl get pod nginx -o json
# JSONPath queries
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
# Custom columns
kubectl get pods -o custom-columns='NAME:.metadata.name,IMAGE:.spec.containers[0].image'
# Wide output with additional info
kubectl get pods -o wide
Common Shortcuts
| Short | Full | Description |
|---|---|---|
| po | pods | Pod resources |
| svc | services | Service resources |
| deploy | deployments | Deployment resources |
| rs | replicasets | ReplicaSet resources |
| ds | daemonsets | DaemonSet resources |
| sts | statefulsets | StatefulSet resources |
| cm | configmaps | ConfigMap resources |
| ns | namespaces | Namespace resources |
| no | nodes | Node resources |
| pv | persistentvolumes | PersistentVolume |
| pvc | persistentvolumeclaims | PersistentVolumeClaim |
| ing | ingresses | Ingress resources |
| netpol | networkpolicies | NetworkPolicy resources |
Useful Aliases
# Add to ~/.bashrc or ~/.zshrc
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgd='kubectl get deploy'
alias kga='kubectl get all'
alias kd='kubectl describe'
alias kaf='kubectl apply -f'
alias kdf='kubectl delete -f'
alias kl='kubectl logs'
alias ke='kubectl exec -it'
alias kns='kubectl config set-context --current --namespace'
# Enable kubectl autocompletion
source <(kubectl completion bash) # bash
source <(kubectl completion zsh) # zsh
Troubleshooting
Viewing Events
# View events in namespace
kubectl get events
# View events sorted by time
kubectl get events --sort-by='.lastTimestamp'
# View events for specific resource
kubectl get events --field-selector involvedObject.name=nginx
# Watch events in real-time
kubectl get events -w
# View events across all namespaces
kubectl get events -A
Debugging Pods
# Check pod status and events
kubectl describe pod nginx
# Check container logs
kubectl logs nginx
# Check previous container logs (after crash)
kubectl logs nginx --previous
# Stream logs
kubectl logs -f nginx
# Execute debugging commands
kubectl exec nginx -- ps aux
kubectl exec nginx -- netstat -tlnp
kubectl exec nginx -- curl localhost
# Run debug container (Kubernetes 1.23+; beta on by default from 1.23, GA in 1.25)
kubectl debug nginx -it --image=busybox
# Copy files for inspection
kubectl cp nginx:/var/log/app.log ./app.log
Common Issues and Solutions
| Issue | Symptoms | Solution |
|---|---|---|
| ImagePullBackOff | Pod stuck pulling image | Check image name, registry credentials, network |
| CrashLoopBackOff | Pod repeatedly crashing | Check logs with kubectl logs --previous |
| Pending | Pod not scheduled | Check resource quotas, node capacity, taints |
| CreateContainerConfigError | Config mount failed | Verify ConfigMap/Secret exists and is correct |
| OOMKilled | Container killed for memory | Increase memory limits |
| Evicted | Pod removed from node | Check disk pressure, memory pressure |
Resource Debugging
# Check node status and capacity
kubectl describe node node-1
# Check resource usage (requires metrics-server)
kubectl top nodes
kubectl top pods
# Check PVC status
kubectl describe pvc my-claim
# Test service DNS resolution
kubectl run test --image=busybox --rm -it -- nslookup nginx-service
# Test service connectivity
kubectl run test --image=busybox --rm -it -- wget -qO- nginx-service
# Check endpoint health
kubectl get endpoints nginx-service
Debugging Network Issues
# Run network debug pod
kubectl run netshoot --image=nicolaka/netshoot --rm -it -- /bin/bash
# Inside debug pod:
# Check DNS
nslookup kubernetes.default
dig nginx-service.default.svc.cluster.local
# Check connectivity
curl -v http://nginx-service:80
nc -zv nginx-service 80
# Trace route
traceroute nginx-service
Quick Reference
Pod Operations
kubectl run nginx --image=nginx # Create pod
kubectl get pods -o wide # List pods
kubectl describe pod nginx # Pod details
kubectl logs -f nginx # Stream logs
kubectl exec -it nginx -- /bin/bash # Shell access
kubectl delete pod nginx # Delete pod
Deployment Operations
kubectl create deploy nginx --image=nginx --replicas=3 # Create
kubectl scale deploy nginx --replicas=5 # Scale
kubectl set image deploy/nginx nginx=nginx:1.26 # Update
kubectl rollout status deploy/nginx # Status
kubectl rollout undo deploy/nginx # Rollback
Service Operations
kubectl expose deploy nginx --port=80 --type=LoadBalancer # Expose
kubectl get svc # List
kubectl get endpoints # Endpoints
kubectl delete svc nginx # Delete
ConfigMap and Secret Operations
kubectl create cm config --from-literal=key=value # ConfigMap
kubectl create secret generic creds --from-literal=pass=secret # Secret
kubectl get cm,secrets # List both
Troubleshooting Commands
kubectl get events --sort-by='.lastTimestamp' # Events
kubectl describe pod nginx # Details
kubectl logs nginx --previous # Previous logs
kubectl top pods # Resource usage
kubectl debug nginx -it --image=busybox # Debug container
Common Issues and Solutions
Pod Stuck in Pending State
Causes and solutions:
-
Insufficient resources - Check node capacity and resource requests
kubectl describe nodes | grep -A5 "Allocated resources" -
No matching nodes - Check node selectors and taints
kubectl describe pod nginx | grep -A5 "Node-Selectors" kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints -
PVC not bound - Check PVC and StorageClass
kubectl get pvc kubectl describe pvc my-claim
ImagePullBackOff
Causes and solutions:
- Wrong image name - Verify image exists in registry
- Authentication required - Create and use imagePullSecret
kubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=user \ --docker-password=pass - Network issues - Check node network connectivity to registry
CrashLoopBackOff
Debugging steps:
# Check logs
kubectl logs nginx --previous
# Check exit code
kubectl describe pod nginx | grep -A10 "State:"
# Interactive troubleshooting
kubectl run debug --image=nginx --command -- sleep infinity
kubectl exec -it debug -- /bin/bash
Service Not Accessible
Debugging checklist:
-
Check service selector matches pod labels
kubectl get svc nginx -o yaml | grep -A5 selector kubectl get pods --show-labels -
Check endpoints exist
kubectl get endpoints nginx -
Check pod readiness
kubectl get pods -o wide -
Test from within cluster
kubectl run test --image=busybox --rm -it -- wget -qO- nginx-service
Deployment Not Updating
Causes and solutions:
- Same image tag - Use unique tags or imagePullPolicy: Always
- Paused rollout - Resume with
kubectl rollout resume - Failed rollout - Check events and pod logs
kubectl rollout status deploy nginx kubectl describe deploy nginx
ConfigMap/Secret Not Updating
Note: Changes to ConfigMaps and Secrets are not automatically reflected in running pods.
Solutions:
-
Restart pods - Trigger rolling restart
kubectl rollout restart deployment nginx -
Use immutable ConfigMaps - Create new ConfigMap with different name
-
Use Reloader - Install tools like stakater/Reloader for automatic restarts
Related Topics
The following topics complement Kubernetes knowledge and are commonly used together:
- Helm - Package manager for Kubernetes applications; simplifies complex deployments with charts and templating
- Docker - Container runtime; understanding container basics is essential for Kubernetes
- ArgoCD - GitOps continuous delivery tool for Kubernetes; automates deployments from Git repositories
- Kustomize - Native Kubernetes configuration management; patch and customise manifests without templates
- Prometheus - Monitoring system commonly used with Kubernetes; collects metrics from cluster and applications
- Istio - Service mesh for Kubernetes; adds traffic management, security, and observability