Available for day contractsFrom 21st September I have availability for day and half day contracts. Please contact for more information.

Contact →
mikepreston.org

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.

Worker Node 2Worker Node 1Control PlanePodsPod CPod DPodsPod APod BAPI ServeretcdSchedulerController ManagerKubeletKube-proxyKubeletKube-proxyWorker Node 2Worker Node 1Control PlanePodsPod CPod DPodsPod APod BAPI ServeretcdSchedulerController ManagerKubeletKube-proxyKubeletKube-proxy

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

Pod createdContainers startedAll containers exit 0Container exits non-zeroNode communication lostCommunication restoredTimeoutPendingRunningSucceededFailedUnknownPod createdContainers startedAll containers exit 0Container exits non-zeroNode communication lostCommunication restoredTimeoutPendingRunningSucceededFailedUnknown

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.

DeploymentReplicaSet v2 -CurrentReplicaSet v1 -PreviousPodPodPodPod - TerminatingDeploymentReplicaSet v2 -CurrentReplicaSet v1 -PreviousPodPodPodPod - Terminating

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.

ClusterExternalUserLoadBalancerIngressNodePortClusterIP ServicePod 1Pod 2Pod 3ClusterExternalUserLoadBalancerIngressNodePortClusterIP ServicePod 1Pod 2Pod 3

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.

PassFailPassFailPassFailContainer StartsStartup ProbeLiveness ProbeContainer RestartReadiness ProbeReceive TrafficRemove from ServicePassFailPassFailPassFailContainer StartsStartup ProbeLiveness ProbeContainer RestartReadiness ProbeReceive TrafficRemove from Service

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:

  1. Insufficient resources - Check node capacity and resource requests

    kubectl describe nodes | grep -A5 "Allocated resources"
    
  2. 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
    
  3. PVC not bound - Check PVC and StorageClass

    kubectl get pvc
    kubectl describe pvc my-claim
    

ImagePullBackOff

Causes and solutions:

  1. Wrong image name - Verify image exists in registry
  2. Authentication required - Create and use imagePullSecret
    kubectl create secret docker-registry regcred \
      --docker-server=registry.example.com \
      --docker-username=user \
      --docker-password=pass
    
  3. 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:

  1. Check service selector matches pod labels

    kubectl get svc nginx -o yaml | grep -A5 selector
    kubectl get pods --show-labels
    
  2. Check endpoints exist

    kubectl get endpoints nginx
    
  3. Check pod readiness

    kubectl get pods -o wide
    
  4. Test from within cluster

    kubectl run test --image=busybox --rm -it -- wget -qO- nginx-service
    

Deployment Not Updating

Causes and solutions:

  1. Same image tag - Use unique tags or imagePullPolicy: Always
  2. Paused rollout - Resume with kubectl rollout resume
  3. 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:

  1. Restart pods - Trigger rolling restart

    kubectl rollout restart deployment nginx
    
  2. Use immutable ConfigMaps - Create new ConfigMap with different name

  3. 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