Join our Discord Server
Collabnix Team The Collabnix Team is a diverse collective of Docker, Kubernetes, and IoT experts united by a passion for cloud-native technologies. With backgrounds spanning across DevOps, platform engineering, cloud architecture, and container orchestration, our contributors bring together decades of combined experience from various industries and technical domains.

What Are Pods in Kubernetes? A Complete Guide with Examples

5 min read

Kubernetes has become the de facto standard for container orchestration, and at its core lies a fundamental building block: the Pod. Whether you’re just getting started with Kubernetes or looking to deepen your understanding, mastering Pods is essential for deploying and managing containerized applications effectively.

In this comprehensive guide, we’ll explore what Pods are, how they work, and walk through practical examples with code snippets you can use in your own clusters.

What is a Pod in Kubernetes?

A Pod is the smallest deployable unit in Kubernetes. Think of it as a wrapper around one or more containers that share the same network namespace, storage volumes, and lifecycle. While Docker runs individual containers, Kubernetes manages Pods—and each Pod can contain one or more tightly coupled containers.

The key characteristics of a Pod include:

  • Shared Network: All containers in a Pod share the same IP address and port space
  • Shared Storage: Pods can mount the same volumes, allowing containers to share data
  • Co-located Execution: Containers in a Pod are always scheduled together on the same node
  • Ephemeral Nature: Pods are designed to be disposable and replaceable

Why Does Kubernetes Use Pods Instead of Containers?

You might wonder why Kubernetes doesn’t just manage containers directly. The Pod abstraction provides several advantages:

  1. Multi-container patterns: Some applications need helper containers (sidecars, init containers) that work alongside the main application
  2. Resource sharing: Containers in a Pod can easily share files and communicate via localhost
  3. Atomic scheduling: Related containers are guaranteed to run on the same node
  4. Abstraction layer: Pods provide a container-runtime-agnostic way to manage workloads

Pod Architecture and Components

A Pod specification consists of several key components:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: myapp
spec:
  containers:
    - name: main-container
      image: nginx:latest
      ports:
        - containerPort: 80
  volumes:
    - name: shared-data
      emptyDir: {}

Let’s break down the structure:

  • apiVersion: The Kubernetes API version (v1 for Pods)
  • kind: The resource type (Pod)
  • metadata: Information about the Pod including name, labels, and annotations
  • spec: The desired state of the Pod including containers, volumes, and other configurations

Creating Your First Pod

Let’s create a simple Pod running an Nginx web server.

Using a YAML Manifest

Create a file named nginx-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    environment: demo
spec:
  containers:
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80
      resources:
        requests:
          memory: "64Mi"
          cpu: "250m"
        limits:
          memory: "128Mi"
          cpu: "500m"

Apply the manifest to your cluster:

kubectl apply -f nginx-pod.yaml

Verify the Pod is running:

kubectl get pods

Expected output:

NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          30s

Using kubectl run (Imperative Method)

For quick testing, you can create a Pod directly from the command line:

kubectl run nginx-quick --image=nginx:1.25 --port=80

Multi-Container Pod Patterns

One of the most powerful features of Pods is the ability to run multiple containers together. Here are the common patterns:

Sidecar Pattern

A sidecar container extends and enhances the main container’s functionality:

apiVersion: v1
kind: Pod
metadata:
  name: web-with-logging
spec:
  containers:
    - name: web-server
      image: nginx:1.25
      ports:
        - containerPort: 80
      volumeMounts:
        - name: logs
          mountPath: /var/log/nginx
    
    - name: log-shipper
      image: fluent/fluent-bit:latest
      volumeMounts:
        - name: logs
          mountPath: /var/log/nginx
          readOnly: true
  
  volumes:
    - name: logs
      emptyDir: {}

In this example, the log-shipper sidecar reads logs from the shared volume and forwards them to a centralized logging system.

Init Container Pattern

Init containers run before the main containers start, useful for setup tasks:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
    - name: init-db-check
      image: busybox:1.36
      command: ['sh', '-c', 'until nc -z db-service 5432; do echo waiting for database; sleep 2; done']
    
    - name: init-config
      image: busybox:1.36
      command: ['sh', '-c', 'wget -O /config/app.conf http://config-server/app.conf']
      volumeMounts:
        - name: config-volume
          mountPath: /config
  
  containers:
    - name: main-app
      image: myapp:latest
      volumeMounts:
        - name: config-volume
          mountPath: /app/config
  
  volumes:
    - name: config-volume
      emptyDir: {}

Ambassador Pattern

An ambassador container proxies network connections to and from the main container:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-ambassador
spec:
  containers:
    - name: main-app
      image: myapp:latest
      env:
        - name: DB_HOST
          value: "localhost"
        - name: DB_PORT
          value: "5432"
    
    - name: db-ambassador
      image: haproxy:latest
      ports:
        - containerPort: 5432
      volumeMounts:
        - name: haproxy-config
          mountPath: /usr/local/etc/haproxy
  
  volumes:
    - name: haproxy-config
      configMap:
        name: haproxy-config

Pod Lifecycle and States

Understanding Pod states helps with troubleshooting and monitoring:

PhaseDescriptionPendingPod accepted but containers not yet createdRunningPod bound to a node, all containers created, at least one runningSucceededAll containers terminated successfullyFailedAll containers terminated, at least one failedUnknownPod state cannot be determined

Check detailed Pod status:

kubectl describe pod nginx-pod

View Pod events for troubleshooting:

kubectl get events --field-selector involvedObject.name=nginx-pod

Configuring Pod Resources

Proper resource configuration ensures your Pods get the resources they need:

apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
    - name: app
      image: python:3.11-slim
      command: ["python", "-m", "http.server", "8000"]
      resources:
        requests:
          memory: "128Mi"
          cpu: "100m"
        limits:
          memory: "256Mi"
          cpu: "200m"
  • Requests: Minimum guaranteed resources
  • Limits: Maximum resources the container can use

Pod Networking

All containers in a Pod share the same network namespace:

apiVersion: v1
kind: Pod
metadata:
  name: network-demo
spec:
  containers:
    - name: web
      image: nginx:1.25
      ports:
        - containerPort: 80
    
    - name: curl
      image: curlimages/curl:latest
      command: ["sleep", "3600"]

Test inter-container communication:

kubectl exec network-demo -c curl -- curl localhost:80

Pod Storage with Volumes

Pods can mount various volume types for persistent or shared storage:

apiVersion: v1
kind: Pod
metadata:
  name: storage-demo
spec:
  containers:
    - name: writer
      image: busybox:1.36
      command: ['sh', '-c', 'while true; do date >> /data/output.txt; sleep 5; done']
      volumeMounts:
        - name: shared-storage
          mountPath: /data
    
    - name: reader
      image: busybox:1.36
      command: ['sh', '-c', 'tail -f /data/output.txt']
      volumeMounts:
        - name: shared-storage
          mountPath: /data
  
  volumes:
    - name: shared-storage
      emptyDir: {}

Environment Variables and ConfigMaps

Inject configuration into your Pods:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  LOG_LEVEL: "info"
---
apiVersion: v1
kind: Pod
metadata:
  name: config-demo
spec:
  containers:
    - name: app
      image: myapp:latest
      envFrom:
        - configMapRef:
            name: app-config
      env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP

Health Checks: Liveness and Readiness Probes

Configure probes to ensure your application is healthy:

apiVersion: v1
kind: Pod
metadata:
  name: health-demo
spec:
  containers:
    - name: web
      image: nginx:1.25
      ports:
        - containerPort: 80
      
      livenessProbe:
        httpGet:
          path: /
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 5
        failureThreshold: 3
      
      readinessProbe:
        httpGet:
          path: /
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 3
      
      startupProbe:
        httpGet:
          path: /
          port: 80
        failureThreshold: 30
        periodSeconds: 10
  • Liveness Probe: Restarts container if it fails
  • Readiness Probe: Removes Pod from Service endpoints if it fails
  • Startup Probe: Disables other probes until the container starts successfully

Security Context for Pods

Configure security settings at the Pod and container level:

apiVersion: v1
kind: Pod
metadata:
  name: security-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  
  containers:
    - name: secure-app
      image: nginx:1.25
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
      volumeMounts:
        - name: cache
          mountPath: /var/cache/nginx
        - name: run
          mountPath: /var/run
  
  volumes:
    - name: cache
      emptyDir: {}
    - name: run
      emptyDir: {}

Common kubectl Commands for Pods

Here are essential commands for managing Pods:

# List all Pods
kubectl get pods

# List Pods with more details
kubectl get pods -o wide

# Describe a specific Pod
kubectl describe pod nginx-pod

# View Pod logs
kubectl logs nginx-pod

# View logs from a specific container in multi-container Pod
kubectl logs nginx-pod -c nginx

# Stream logs in real-time
kubectl logs -f nginx-pod

# Execute a command in a Pod
kubectl exec nginx-pod -- ls /usr/share/nginx/html

# Get an interactive shell
kubectl exec -it nginx-pod -- /bin/bash

# Delete a Pod
kubectl delete pod nginx-pod

# Delete a Pod immediately
kubectl delete pod nginx-pod --grace-period=0 --force

# Get Pod YAML
kubectl get pod nginx-pod -o yaml

# Watch Pod status changes
kubectl get pods -w

Pods vs Deployments: When to Use Which

While Pods are the fundamental unit, you typically don’t create Pods directly in production:

FeaturePodDeploymentSelf-healingNoYesRolling updatesNoYesScalingManualAutomaticVersioningNoYesUse caseTesting, debuggingProduction workloads

For production, use a Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

Troubleshooting Pod Issues

Common issues and how to debug them:

Pod stuck in Pending state

kubectl describe pod <pod-name>
# Check Events section for scheduling issues

Pod in CrashLoopBackOff

# Check container logs
kubectl logs <pod-name> --previous

# Check resource limits
kubectl describe pod <pod-name> | grep -A 5 "Limits"

Pod in ImagePullBackOff

# Verify image name and tag
kubectl describe pod <pod-name> | grep -A 3 "Image"

# Check for image pull secrets
kubectl get secrets

Best Practices for Pods

  1. Always set resource requests and limits to ensure proper scheduling and prevent resource contention
  2. Use health probes to enable self-healing and proper load balancing
  3. Don’t run Pods directly in production—use Deployments, StatefulSets, or DaemonSets
  4. Keep containers focused on a single responsibility
  5. Use labels and annotations for organization and automation
  6. Configure security contexts to follow the principle of least privilege
  7. Use ConfigMaps and Secrets for configuration instead of hardcoding values

Conclusion

Pods are the foundation of everything you run in Kubernetes. Understanding how they work—from networking and storage to multi-container patterns and lifecycle management—is crucial for building reliable, scalable applications.

While you’ll typically use higher-level abstractions like Deployments in production, knowing Pods inside out helps you debug issues, optimize performance, and design better architectures.

Start experimenting with the examples in this guide, and you’ll quickly become comfortable with this essential Kubernetes concept.

Have Queries? Join https://launchpass.com/collabnix

Collabnix Team The Collabnix Team is a diverse collective of Docker, Kubernetes, and IoT experts united by a passion for cloud-native technologies. With backgrounds spanning across DevOps, platform engineering, cloud architecture, and container orchestration, our contributors bring together decades of combined experience from various industries and technical domains.
Join our Discord Server
Index