LFCE 138 ๐ง Kubernetes โ Pods
A Pod is the smallest deployable unit in Kubernetes. It is not a container; it is a wrapper around one or more containers that share the same network namespace, the same IP address, and the same storage volumes . The containers inside a Pod are always co-located on the same node, always co-scheduled, and always share a context. When a Pod is created, Kubernetes manages the Pod as a whole, not the individual containers inside it.
This chapter covers the Pod abstraction: the single-container and multi-container models, the shared network and storage that define a Pod’s identity, the three multi-container design patterns (init containers, sidecars, and co-located peers), and the restart policy that determines what happens when a container exits.
Key point: A Pod is ephemeral. It is not designed to survive node failures or restarts. When a Pod is deleted or its node fails, the control plane creates a replacement Pod with a new name, a new IP address, and no memory of the previous instance. The Pod itself is the unit of scheduling, not the unit of persistence.
Why Pods exist
The co-location problem. Some processes are tightly coupled. A web server needs a log shipper to collect its output. An application needs a local cache to serve requests faster. A batch job needs a helper to fetch data before the main process starts. If these processes ran in separate containers on separate nodes, they would have to communicate over the network, which adds latency and complexity. A Pod places them on the same node, in the same network namespace, so they can communicate over localhost and share storage directly .
The atomic scheduling problem. Kubernetes schedules Pods, not containers. The scheduler evaluates the Pod’s total resource requests, the node’s available capacity, and the Pod’s constraints as a single decision. If the Pod has three containers, all three are scheduled together. There is no partial scheduling where one container runs on one node and another container runs on a different node. The Pod is the atomic unit of placement .
The lifecycle problem. A container has a lifecycle. It starts, runs, and exits. A Pod has a lifecycle that wraps the containers. The Pod can be Pending (waiting for scheduling), Running (at least one container is running), Succeeded (all containers exited with zero), or Failed (at least one container exited with non-zero and will not restart). The Pod’s status is the aggregate of its containers’ statuses .
a. The single-container Pod
The most common Pod has exactly one container. The Pod is a wrapper that gives the container a network identity, a set of resource limits, and a lifecycle managed by Kubernetes. The container does not know it is in a Pod; it just runs its process .
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
The Pod gets a cluster-internal IP address. The container inside the Pod binds to port 80. Other Pods can reach it at that IP and port. The Pod’s name (nginx) is its identity in the cluster, but the IP address is what other Pods use to connect.
The single-container model is the default for stateless applications. A Deployment creates a ReplicaSet, and the ReplicaSet creates Pods with one container each. The controller manages the Pods, not the containers.
b. The multi-container Pod
A Pod can contain multiple containers. These containers share the network namespace and the storage volumes. They are always scheduled on the same node. They can communicate over localhost because they share the same IP address and port space .
The Kubernetes documentation describes three patterns for multi-container Pods .
Init containers run before the main containers. They run sequentially, in the order they are listed in the initContainers field. Each init container must exit successfully before the next one starts. The main containers do not start until all init containers have completed. Init containers are used for setup tasks: waiting for a database to be ready, running a schema migration, or fetching configuration files .
spec:
initContainers:
- name: wait-for-db
image: busybox
command: ['sh', '-c', 'until nc -z db 5432; do sleep 1; done']
containers:
- name: app
image: myapp:1.0
Sidecar containers run alongside the main container for the Pod’s entire lifetime. They provide supporting functionality: log collection, metrics export, request proxying, or data synchronization. In Kubernetes v1.33 and later, a sidecar is defined as an init container with restartPolicy: Always, which makes it start before the main container and remain running until the Pod terminates .
Co-located containers are multiple containers in the containers array that run concurrently. Kubernetes does not guarantee a startup order between them. This pattern is appropriate when the containers are independent peers that need to share the network or storage but do not depend on each other’s startup sequence .
c. Shared resources and the Pod’s identity
Every container in a Pod shares the same network namespace. The Pod has one IP address, and every container binds to ports on that address. Two containers in the same Pod cannot bind to the same port; they must coordinate their port usage. Containers in different Pods have different IP addresses and cannot communicate via localhost .
Every container in a Pod can mount the same volumes. A volume is defined at the Pod level and mounted into each container that needs it. This is how a sidecar can read the main container’s log files, or how an init container can write a configuration file that the main container reads .
The Pod’s hostname is the Pod’s metadata.name. Containers inside the Pod see the hostname as the Pod name. This is useful for applications that report their identity, but it is not a stable identifier across Pod recreations.
Complete Example Session
# ============================================
# PART 1: A SINGLE-CONTAINER POD
# ============================================
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
# ============================================
# PART 2: CREATE AND INSPECT
# ============================================
kubectl apply -f pod.yaml
kubectl get pod web
kubectl describe pod web
# ============================================
# PART 3: AN INIT CONTAINER
# ============================================
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
initContainers:
- name: init-config
image: busybox
command: ['sh', '-c', 'echo "config" > /work/config.txt']
volumeMounts:
- name: work
mountPath: /work
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: work
mountPath: /work
volumes:
- name: work
emptyDir: {}
# ============================================
# PART 4: A SIDECAR CONTAINER
# ============================================
spec:
initContainers:
- name: log-shipper
image: fluentbit:latest
restartPolicy: Always
volumeMounts:
- name: logs
mountPath: /var/log/app
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}
# ============================================
# PART 5: CO-LOCATED CONTAINERS
# ============================================
spec:
containers:
- name: web
image: nginx:1.27
- name: metrics
image: prom-exporter:latest
ports:
- containerPort: 9090
# ============================================
# PART 6: CHECK POD STATUS
# ============================================
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# web 1/1 Running 0 30s
# app 2/2 Running 0 1m
# ============================================
# PART 7: CHECK CONTAINER LOGS
# ============================================
kubectl logs web
kubectl logs app -c init-config
# ============================================
# PART 8: EXEC INTO A CONTAINER
# ============================================
kubectl exec -it web -- /bin/sh
# ============================================
# PART 9: THE RESTART POLICY
# ============================================
# Always: restart regardless of exit code
# OnFailure: restart only on non-zero exit
# Never: never restart
# ============================================
# PART 10: THE COMPLETE POD
# ============================================
apiVersion: v1
kind: Pod
metadata:
name: complete
spec:
restartPolicy: OnFailure
initContainers:
- name: wait
image: busybox
command: ['sh', '-c', 'until nc -z db 5432; do sleep 1; done']
containers:
- name: app
image: myapp:1.0
ports:
- containerPort: 8080
The ten parts covered the single-container Pod, creation and inspection, init containers, sidecar containers, co-located containers, Pod status, container logs, exec, the restart policy, and the complete Pod.
Quick Reference
Pod models
| Model | Containers | Use case |
|---|---|---|
| Single-container | One | Stateless applications |
| Init containers | Sequential, run before main | Setup, migrations, waiting |
| Sidecar | Long-running helper | Logging, proxying, metrics |
| Co-located | Concurrent peers | Shared network/storage, independent |
Shared resources
| Resource | Shared |
|---|---|
| Network namespace | Yes (one IP, shared ports) |
| Volumes | Yes (mounted per container) |
| Hostname | Pod name |
| IPC | Yes (SystemV, POSIX) |
Restart policies
| Policy | Behavior |
|---|---|
Always | Restart regardless of exit code |
OnFailure | Restart only on non-zero exit |
Never | Never restart |
Pod lifecycle
| Phase | Meaning |
|---|---|
Pending | Accepted, not scheduled or containers not started |
Running | At least one container running |
Succeeded | All containers exited 0 |
Failed | At least one container exited non-zero |
Best Practices
โ Do This:
# Use init containers for setup that must complete first
initContainers:
- name: wait-for-db # โ
# Use a sidecar for log collection
initContainers:
- name: log-shipper
restartPolicy: Always # โ
# Set resource requests and limits
resources:
requests: { cpu: 100m, memory: 128Mi } # โ
โ Don’t Do This:
# Put unrelated services in the same Pod
containers:
- name: web
- name: database # separate concern # โ
# Assume startup order for co-located containers
containers:
- name: a
- name: b # b may start before a # โ
# Use a Pod directly for a long-running service
# Use a Deployment instead # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Pods are not recreated | Created directly, not via a controller | Use a Deployment or ReplicaSet |
| Container cannot bind port | Another container in the Pod uses it | Coordinate ports or use separate Pods |
| Init container hangs | Waiting for a service that never comes up | Check the init container’s command and logs |
| Sidecar does not start first | Co-located containers have no order | Use an init container with restartPolicy: Always |
| Data lost on Pod restart | Used emptyDir or no volume | Use a PersistentVolume |
Real-World Examples
1. Single-container Pod
spec:
containers:
- name: nginx
image: nginx:1.27
2. Init container
initContainers:
- name: migrate
image: myapp:1.0
command: ['sh', '-c', 'npm run migrate']
3. Sidecar
initContainers:
- name: proxy
image: envoy:latest
restartPolicy: Always
4. Co-located containers
containers:
- name: app
- name: metrics
5. Shared volume
volumes:
- name: shared
emptyDir: {}
6. Restart policy
restartPolicy: OnFailure
7. Check Pod status
kubectl get pods
8. Describe a Pod
kubectl describe pod web
9. Exec into a container
kubectl exec -it web -- /bin/sh
10. View logs
kubectl logs web
Visual
The Pod abstraction
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ POD โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Network namespace: 10.0.0.5 โโ
โ โ โโ
โ โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโ
โ โ โ Container A โ โ Container B โ โโ
โ โ โ port 8080 โ โ port 9090 โ โโ
โ โ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โโ
โ โ โ โ โโ
โ โ โโโโโโโโโโฌโโโโโโโโโ โโ
โ โ โผ โโ
โ โ โโโโโโโโโโโโโโโโโโโ โโ
โ โ โ Shared volume โ โโ
โ โ โโโโโโโโโโโโโโโโโโโ โโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Multi-container patterns
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ INIT CONTAINERS โ
โ init1 โโโบ init2 โโโบ main container โ
โ Sequential, must complete before main starts โ
โ โ
โ SIDECAR โ
โ sidecar โโโโโโโโโโโโโโโบ (runs for Pod lifetime) โ
โ main โโโโโโโโโโโโโโโโโโบ (runs for Pod lifetime) โ
โ Concurrent, sidecar may start first with restartPolicy โ
โ โ
โ CO-LOCATED โ
โ container A โโโโโโโโโโโบ โ
โ container B โโโโโโโโโโโบ โ
โ Concurrent, no startup order guaranteed โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Pod lifecycle
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PENDING โโโบ RUNNING โโโบ SUCCEEDED โ
โ โ โ โ
โ โ โโโโบ FAILED โ
โ โ โ
โ โผ โ
โ Scheduled to a node โ
โ Containers starting โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Shared network
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ POD: 10.0.0.5 โ
โ โ
โ Container A binds 8080 โ
โ Container B binds 9090 โ
โ โ
โ Container A โ localhost:9090 โ Container B โ
โ โ
โ External โ 10.0.0.5:8080 โ Container A โ
โ External โ 10.0.0.5:9090 โ Container B โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Definition | Smallest deployable unit, one or more containers |
| Shared resources | Network namespace, IP, volumes, IPC |
| Single-container | Most common, wrapper around one container |
| Init containers | Sequential, run before main containers |
| Sidecar | Long-running helper, restartPolicy: Always in initContainers |
| Co-located | Concurrent containers, no startup order |
| Restart policy | Always, OnFailure, Never |
| Lifecycle phases | Pending, Running, Succeeded, Failed |
| Pod IP | Unique per Pod, shared by all containers |
Key takeaways:
- A Pod is not a container. It is a wrapper around one or more containers that share a network namespace, an IP address, and storage volumes. Kubernetes manages Pods, not containers .
- The single-container model is the default. A Pod with one container is the standard unit for stateless applications. The Pod gives the container a network identity and a lifecycle managed by Kubernetes .
- Multi-container Pods exist for tightly coupled processes. Init containers run sequentially before the main containers. Sidecars run alongside the main container for the Pod’s lifetime. Co-located containers run concurrently with no guaranteed startup order .
- The shared network namespace is the defining feature. All containers in a Pod share the same IP address and port space. They can communicate over
localhost, but they cannot bind to the same port . - The restart policy determines what happens when a container exits.
Alwaysrestarts regardless of exit code,OnFailurerestarts only on non-zero, andNevernever restarts. The policy is set at the Pod level and applies to all containers . - Pods are ephemeral. A Pod is tied to the node where it was scheduled and remains there until termination or deletion. When a node fails, the control plane creates replacement Pods on other nodes. A Pod is not a persistent entity; it is a disposable unit of execution .
Remember: A Pod is the atomic unit of Kubernetes scheduling and the smallest deployable object. It wraps one or more containers that share a network namespace and storage volumes. The single-container Pod is the default. The multi-container Pod is for tightly coupled processes: init containers for setup, sidecars for supporting services, and co-located containers for independent peers. The Pod has an IP address, a hostname, and a lifecycle, but it does not have persistence. When a Pod dies, it is replaced. The controller that manages the replacement is the Deployment, the StatefulSet, or the DaemonSet, not the Pod itself.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!