Kubernetes orchestrates containers using a set of core objects: Pods, Deployments, and ReplicaSets. Understanding how these relate to each other is fundamental to working with GKE.
Resource Hierarchy
flowchart TD D["Deployment"] --> RS["ReplicaSet"] RS --> P1["Pod 1"] RS --> P2["Pod 2"] RS --> P3["Pod 3"] P1 --> C1["Container"] P2 --> C2["Container"] P3 --> C3["Container"]
| Level | What It Does | Managed By |
|---|---|---|
| Deployment | Declares desired state, manages rollout strategy | You (via kubectl or YAML) |
| ReplicaSet | Ensures the correct number of pod replicas are running | Deployment controller |
| Pod | Runs one or more containers with shared network/storage | ReplicaSet controller |
| Container | Your actual application image | Pod lifecycle |
Key Insight: You almost always interact with Deployments, not ReplicaSets directly. The Deployment creates and manages the ReplicaSet for you.
Pods
A Pod is the smallest deployable unit in Kubernetes. It encapsulates one or more containers that share the same network namespace (IP address) and storage volumes.
Pod Structure
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m" # 0.1 vCPU
memory: "128Mi"
limits:
cpu: "500m" # 0.5 vCPU
memory: "256Mi"
restartPolicy: AlwaysKey Pod Concepts
| Concept | Description |
|---|---|
| Ephemeral | Pods are not self-healing. If a pod dies, a new one is created (by a controller) |
| Single IP | All containers in a pod share one IP address |
| Co-located | All containers in a pod run on the same node |
| Shared storage | Containers in a pod can share volumes |
| Resource requests/limits | Define CPU/memory needs for scheduling and QoS |
Tip: Use one container per pod unless you have a tightly-coupled sidecar (like a logging agent). Multi-container pods share the same lifecycle — they start, stop, and scale together.
Pod Lifecycle
Pending → Running → Succeeded/Failed
↘ CrashLoopBackOff (repeated failures)| Phase | Meaning |
|---|---|
| Pending | Pod accepted but not yet running (scheduling or image pull) |
| Running | At least one container is still running |
| Succeeded | All containers completed successfully (batch jobs) |
| Failed | At least one container terminated with an error |
| Unknown | Pod state cannot be determined (usually node communication issue) |
Common Pod Commands
# List pods
kubectl get pods
kubectl get pods -o wide # with node and IP info
kubectl get pods --show-labels # show labels
# Pod details
kubectl describe pod POD_NAME
# Pod logs
kubectl logs POD_NAME
kubectl logs POD_NAME -c CONTAINER_NAME # specific container
kubectl logs POD_NAME --previous # previous crashed container
# Execute commands inside a pod
kubectl exec -it POD_NAME -- /bin/bash
# Delete a pod (controller will recreate it)
kubectl delete pod POD_NAMEDeployments
A Deployment manages a ReplicaSet and provides declarative updates for Pods. It handles rollout strategy, rollback, and scaling.
Deployment YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # allow 1 extra pod during rollout
maxUnavailable: 0 # keep all existing pods running
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"Deployment Strategies
| Strategy | How It Works | When to Use |
|---|---|---|
| RollingUpdate (default) | Gradually replaces old pods with new ones | Most production deployments |
| Recreate | Kills all old pods before starting new ones | When you cannot run old and new versions simultaneously |
flowchart LR subgraph RollingUpdate direction TB R1["v1: 3 pods"] --> R2["v1: 2 pods, v2: 1 pod"] --> R3["v1: 1 pod, v2: 2 pods"] --> R4["v2: 3 pods"] end subgraph Recreate direction TB C1["v1: 3 pods"] --> C2["0 pods"] --> C3["v2: 3 pods"] end
Deployment Commands
# Create a deployment
kubectl create deployment my-app --image=nginx:1.25 --replicas=3
# Apply from YAML
kubectl apply -f deployment.yaml
# Check rollout status
kubectl rollout status deployment/my-app
# View rollout history
kubectl rollout history deployment/my-app
# Rollback to previous version
kubectl rollout undo deployment/my-app
# Rollback to specific revision
kubectl rollout undo deployment/my-app --to-revision=2
# Scale a deployment
kubectl scale deployment my-app --replicas=5
# Update the container image (triggers rollout)
kubectl set image deployment/my-app app=nginx:1.26
# Edit the deployment directly
kubectl edit deployment my-appHow Deployments Manage Rollouts
sequenceDiagram participant User participant Deployment participant ReplicaSet as New ReplicaSet participant OldRS as Old ReplicaSet User->>Deployment: Update image to v2 Deployment->>ReplicaSet: Create with v2 image ReplicaSet->>ReplicaSet: Scale up to 1 pod Deployment->>OldRS: Scale down to 2 pods ReplicaSet->>ReplicaSet: Scale up to 2 pods Deployment->>OldRS: Scale down to 1 pod ReplicaSet->>ReplicaSet: Scale up to 3 pods Deployment->>OldRS: Scale down to 0 pods Note over Deployment: Rollout complete
Key Insight: Each time you update a Deployment, a new ReplicaSet is created. Old ReplicaSets are kept (scaled to zero) for rollback. This is why
kubectl rollout undoworks.
ReplicaSets
A ReplicaSet ensures a specified number of pod replicas are running at all times. In practice, you rarely create ReplicaSets directly — Deployments manage them for you.
ReplicaSet YAML (rarely used directly)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-app-rs
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.25Deployment vs ReplicaSet vs Pod
| Aspect | Deployment | ReplicaSet | Pod |
|---|---|---|---|
| Purpose | Declarative updates and rollouts | Maintain replica count | Run containers |
| Self-healing | Yes (via ReplicaSet) | Yes (recreates failed pods) | No |
| Rolling updates | Yes | No (creates new RS manually) | No |
| Rollback | Yes | No | No |
| Scaling | Yes (kubectl scale) | Yes | No |
| Use directly? | Yes — primary workload object | Rarely — let Deployments manage them | Rarely — let controllers manage them |
Labels and Selectors
Labels and selectors are the glue that connects Kubernetes objects:
# Deployment has a selector
spec:
selector:
matchLabels:
app: my-app # This must match the pod template labels
# Pod template has labels
template:
metadata:
labels:
app: my-app # This must match the deployment selectorWarning: The
selectorin a Deployment is immutable after creation. You cannot change which pods a Deployment manages. If you need different labels, create a new Deployment.
Common Label Conventions
| Label | Purpose | Example |
|---|---|---|
app | Application name | app: my-app |
version | Application version | version: v2 |
tier | Architecture tier | tier: frontend |
environment | Deployment environment | environment: production |
Probes
Probes let Kubernetes check the health of containers in a pod:
| Probe Type | Purpose | Failure Result |
|---|---|---|
| livenessProbe | Is the container still running correctly? | Kubernetes restarts the container |
| readinessProbe | Can the container serve traffic? | Pod is removed from Service endpoints |
| startupProbe | Has the container finished starting? | Liveness/readiness probes delayed until success |
containers:
- name: app
image: nginx:1.25
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 15
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5Tip: Always define a readiness probe. Without it, Kubernetes sends traffic to pods that may not be ready to serve requests.
Common Commands Summary
| Command | Purpose |
|---|---|
kubectl get pods | List all pods |
kubectl describe pod NAME | Detailed pod information and events |
kubectl logs NAME | View pod logs |
kubectl exec -it NAME -- bash | Shell into a container |
kubectl get deployments | List deployments |
kubectl rollout status deploy/NAME | Watch rollout progress |
kubectl rollout undo deploy/NAME | Rollback to previous version |
kubectl scale deploy/NAME --replicas=N | Scale deployment |
kubectl set image deploy/NAME container=image:tag | Update container image |
kubectl get rs | List ReplicaSets |
kubectl get events --sort-by='.lastTimestamp' | View recent cluster events |
TL;DR
- Pods run containers — they are ephemeral and not self-healing on their own
- ReplicaSets maintain a desired number of pod replicas — rarely used directly
- Deployments manage ReplicaSets and provide rolling updates and rollbacks — the primary workload object
- Always define resource requests and limits and readiness probes
- Use
kubectl apply -ffor declarative management; avoid imperative commands in production - Labels and selectors connect Deployments to Pods — get them right