Target Audience: Backend developers who want to understand Kubernetes Pod concept Prerequisites: Basic Docker container concepts After reading this: You will understand what Pods are and why we use Pods instead of containers

TL;DR
  • Pod is the smallest deployable unit in Kubernetes
  • A Pod contains one or more containers that share network and storage
  • Most Pods contain only a single container

What is a Pod?#

A Pod is the smallest deployable unit that can be created and managed in Kubernetes. While containers are the smallest unit in Docker, Pods are the smallest unit in Kubernetes.

flowchart TB
    subgraph Pod
        direction TB
        C1[Container 1]
        C2[Container 2]
        V[Shared Volume]
        C1 --- V
        C2 --- V
    end
    NET[Shared Network<br>localhost communication]
    Pod --- NET

Containers within a Pod share:

Shared ResourceDescription
NetworkSame IP address, can communicate via localhost
StorageShare data by mounting Volumes
IPCShare inter-process communication namespace

However, some resources are isolated per container:

Isolated ResourceDescription
FilesystemEach container has its own filesystem
ProcessesEach container has independent process space
CPU/MemoryCan set resource limits per container

Why Pod Instead of Container?#

How do Docker containers differ from Kubernetes Pods?

PerspectiveDocker ContainerKubernetes Pod
CompositionSingle process recommendedGroup of related containers
NetworkEach gets own IPOne IP per Pod
ScalingIndividual scalingPod-level scaling
DeploymentIndividual deploymentDeploy together, terminate together

Pods are used to manage tightly coupled containers as a single unit.

Example: Web Application with Log Collection#

flowchart LR
    subgraph Pod
        App[Web App<br>:8080]
        Log[Log Collector]
        V[(Log Volume)]
        App -->|write logs| V
        V -->|read logs| Log
    end
    Log -->|send| ES[(Elasticsearch)]

In this case, Web App and Log Collector should be in the same Pod because:

  • They must run on the same node (to share log files)
  • They should start and stop together
  • They should be replicated together during scale-out

Pod YAML Structure#

Let’s examine a basic Pod definition.

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  labels:
    app: my-app
    version: v1
spec:
  containers:
  - name: app
    image: nginx:1.25
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "128Mi"
        cpu: "100m"
      limits:
        memory: "256Mi"
        cpu: "200m"

Meaning of each field:

FieldDescription
apiVersionAPI version to use (v1 for Pod)
kindResource type
metadata.namePod name (unique within namespace)
metadata.labelsLabels to identify Pod
spec.containersList of containers
resources.requestsMinimum required resources (scheduling criteria)
resources.limitsMaximum usable resources

Pod Lifecycle#

A Pod goes through several stages from creation to termination.

stateDiagram-v2
    [*] --> Pending: Pod created
    Pending --> Running: Container starts
    Running --> Succeeded: Normal termination
    Running --> Failed: Abnormal termination
    Running --> Unknown: Node unreachable
    Succeeded --> [*]
    Failed --> [*]

Description of each stage:

StageDescriptionCommon Cause
PendingPod created but containers not yet startedImage downloading, node scheduling in progress
RunningAll containers created and at least one runningNormal state
SucceededAll containers terminated successfullyJob, CronJob completed
FailedAll containers terminated with at least one failureApplication error
UnknownCannot determine Pod statusNode network issues

Container States#

Each container within a Pod also has a state.

StateDescription
WaitingContainer waiting to start (image pull, etc.)
RunningContainer is running
TerminatedContainer terminated (successfully or failed)
# Check container state
kubectl describe pod my-app

Multi-Container Patterns#

Common patterns for including multiple containers in a Pod.

Sidecar Pattern#

Run a container that assists the main container.

apiVersion: v1
kind: Pod
metadata:
  name: web-with-logging
spec:
  containers:
  - name: web
    image: nginx:1.25
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
  - name: log-forwarder
    image: fluent/fluentd:v1.16
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
      readOnly: true
  volumes:
  - name: logs
    emptyDir: {}
ContainerRole
webMain application, generates logs
log-forwarderCollect logs and send externally

Sidecar pattern use cases:

  • Log collection (Fluentd, Filebeat)
  • Proxy (Envoy, Istio)
  • Configuration sync (Git-sync)

Init Container Pattern#

Perform initialization tasks before main container execution.

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 sleep 2; done']
  containers:
  - name: app
    image: my-app:1.0

Init Container characteristics:

CharacteristicDescription
Sequential executionMultiple Init Containers run in order
Completion requiredAll Init Containers must succeed before main containers start
RetryRetries until success if failed

Use cases:

  • Wait for dependent services (DB, cache, etc.)
  • Generate configuration files
  • Download data

Pod Networking#

Understanding core concepts of Pod networking.

Pod IP#

Each Pod is assigned a unique IP within the cluster.

flowchart LR
    subgraph Node1
        P1[Pod A<br>10.244.1.5]
        P2[Pod B<br>10.244.1.6]
    end
    subgraph Node2
        P3[Pod C<br>10.244.2.3]
    end
    P1 <-->|direct communication| P3
    P1 <-->|localhost unavailable| P2

Networking rules:

RuleDescription
Pod-to-Pod communicationAll Pods in same cluster communicate without NAT
Cross-node communicationPods on different nodes communicate directly via IP
Intra-Pod communicationContainers in same Pod communicate via localhost

Port Conflicts#

Containers in the same Pod cannot use the same port.

# Incorrect example - port conflict
spec:
  containers:
  - name: app1
    ports:
    - containerPort: 8080  # Conflict!
  - name: app2
    ports:
    - containerPort: 8080  # Conflict!
# Correct example
spec:
  containers:
  - name: app1
    ports:
    - containerPort: 8080
  - name: app2
    ports:
    - containerPort: 8081  # Use different port

Practice: Creating and Managing Pods#

Create Pod#

# Create from YAML file
kubectl apply -f pod.yaml

# Quickly create imperatively (for testing)
kubectl run nginx --image=nginx:1.25

Check Pod Status#

# List Pods
kubectl get pods

# Detailed information
kubectl describe pod nginx

# View logs
kubectl logs nginx

# Logs from specific container in multi-container Pod
kubectl logs nginx -c sidecar

Access Pod#

# Access container shell
kubectl exec -it nginx -- /bin/bash

# Access specific container
kubectl exec -it nginx -c sidecar -- /bin/sh

# Execute command
kubectl exec nginx -- cat /etc/nginx/nginx.conf

Delete Pod#

# Delete single Pod
kubectl delete pod nginx

# Delete using YAML file
kubectl delete -f pod.yaml

# Force delete (use with caution)
kubectl delete pod nginx --force --grace-period=0

Why Not Use Pods Directly?#

In actual operations, Pods are not created directly.

Direct Pod UseUsing Deployment
Not recovered when deletedAuto-recovery
Manual recreation for updatesRolling updates
Cannot scaleScale with replicas
Lost on node failureRescheduled on other nodes

Therefore, in practice, Pods are managed through workload resources like Deployment, StatefulSet, DaemonSet.

When to Use Pods Directly?
  • Temporary Pods for debugging
  • One-time tasks (quick tests with kubectl run)
  • Learning purposes

Always use Deployment etc. in production.


Next Steps#

Once you understand Pods, proceed to the next steps:

GoalRecommended Doc
Automatic Pod managementDeployment
How to access PodsService
Configure health checksHealth Checks