Learn / Kubernetes survival kit / Pods, Deployments, and Services
Pods, Deployments, and Services
The three objects almost everything else in Kubernetes builds on, and how they relate to each other.
Pod: the smallest deployable unit
A Pod wraps one or more containers that are scheduled together on the same node, sharing a
network namespace (they can reach each other on localhost) and optionally storage volumes.
Most Pods run exactly one container; a second “sidecar” container (a log shipper, a proxy) is
the common reason for more than one.
apiVersion: v1
kind: Pod
metadata:
name: hello-pod
labels:
app: hello
spec:
containers:
- name: hello
image: myregistry/hello:1.4
ports:
- containerPort: 8080
Pods are ephemeral by design - if a Pod’s container crashes past its restart policy, or its node fails, or you delete it, it’s gone. Nothing brings it back on its own. That’s on purpose: Kubernetes expects a higher-level controller to manage replacement, which is exactly what a Deployment does.
Deployment: managing a set of identical Pods
A Deployment declares “I want N replicas of this Pod spec running, always.” It creates and owns a ReplicaSet, which in turn creates and watches the actual Pods, replacing any that disappear.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
replicas: 3
selector:
matchLabels:
app: hello
template: # the Pod spec - identical to the bare Pod above, minus metadata.name
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: myregistry/hello:1.4
ports:
- containerPort: 8080
This is also what makes rolling updates possible (lesson 2) - the Deployment controller is what orchestrates replacing old Pods with new ones gradually instead of all at once.
Service: a stable address for a moving target
Pods get replaced constantly (crashes, rollouts, rescheduling), and each replacement gets a new internal IP. Nothing that depends on a specific Pod’s IP would survive that churn. A Service solves this by giving a stable DNS name and virtual IP to whichever Pods currently match its label selector:
apiVersion: v1
kind: Service
metadata:
name: hello
spec:
selector:
app: hello # matches the label on the Deployment's Pods
ports:
- port: 80
targetPort: 8080
Other Pods in the cluster can now reach this set of Pods at hello (or
hello.<namespace>.svc.cluster.local), and Kubernetes keeps that name routed to the current,
ready Pods automatically - no code anywhere has to track individual Pod IPs.
The chain, end to end
Deployment (desired state: 3 replicas of this Pod spec)
|
v creates/manages
ReplicaSet --> Pod, Pod, Pod (each gets its own IP, all carrying label app=hello)
^
| selects by label
Service (app=hello) <-- stable name/IP other things connect to
Everything from here (rollouts, autoscaling, config injection) is really about how these three objects get updated or extended - see the rest of this track, and the kubectl cheatsheet for the commands to inspect and manage them day to day.
Key takeaways
- A Pod is the smallest deployable unit - one or more containers that share network and storage, scheduled together on the same node.
- You almost never create a Pod directly in production - a Deployment manages a set of identical Pods, handling replicas, rollouts, and self-healing.
- A Service gives a stable network identity (a DNS name and virtual IP) to a set of Pods, because individual Pods are ephemeral and their IPs change as they're replaced.
- The chain is: Deployment creates/manages Pods -> Service routes traffic to whichever Pods are currently ready, by label selector, not by tracking individual Pod IPs.
Quick check
3 questions - see how much stuck.