TechLead
Lesson 6 of 25
5 min read
Cloud & Kubernetes

Pods and Deployments

Deep dive into Kubernetes Pods, Deployments, ReplicaSets, rolling updates, rollback strategies, and lifecycle management

Understanding Pods

A Pod is the smallest deployable unit in Kubernetes. It represents a single instance of a running process in your cluster. A Pod encapsulates one or more containers that share the same network namespace (IP address and ports), storage volumes, and lifecycle.

Pod Key Characteristics

  • Shared Network: All containers in a Pod share the same IP address and port space, communicating via localhost
  • Shared Storage: Containers in a Pod can access shared volumes for data exchange
  • Co-scheduling: All containers in a Pod are scheduled on the same node
  • Ephemeral: Pods are not designed to be durable — they can be terminated and replaced at any time
  • Atomic Unit: Kubernetes manages the entire Pod, not individual containers within it

Single-Container Pod

# single-container-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-web-app
  labels:
    app: web
    environment: development
  annotations:
    description: "A simple web application pod"
spec:
  containers:
  - name: web
    image: node:20-alpine
    command: ["node", "server.js"]
    ports:
    - containerPort: 3000
      name: http
      protocol: TCP
    env:
    - name: NODE_ENV
      value: "production"
    - name: PORT
      value: "3000"
    resources:
      requests:
        memory: "128Mi"
        cpu: "100m"
      limits:
        memory: "256Mi"
        cpu: "500m"
    livenessProbe:
      httpGet:
        path: /health
        port: 3000
      initialDelaySeconds: 10
      periodSeconds: 15
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 3000
      initialDelaySeconds: 5
      periodSeconds: 10
  restartPolicy: Always

Multi-Container Pod (Sidecar Pattern)

# sidecar-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web-with-logging
  labels:
    app: web
spec:
  containers:
  # Main application container
  - name: web-app
    image: my-web-app:1.0
    ports:
    - containerPort: 3000
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app

  # Sidecar: log collector
  - name: log-collector
    image: fluentd:v1.16
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
      readOnly: true
    - name: fluentd-config
      mountPath: /fluentd/etc

  # Init container: runs before main containers
  initContainers:
  - name: init-db-check
    image: busybox:1.36
    command: ['sh', '-c', 'until nc -z db-service 5432; do echo waiting for db; sleep 2; done']

  volumes:
  - name: shared-logs
    emptyDir: {}
  - name: fluentd-config
    configMap:
      name: fluentd-config

Deployments

A Deployment provides declarative updates for Pods and ReplicaSets. You describe a desired state in a Deployment, and the Deployment controller changes the actual state to the desired state at a controlled rate. Deployments manage ReplicaSets, which in turn manage Pods.

# production-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  labels:
    app: api-server
    version: v2
spec:
  replicas: 3
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: api-server
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # Max extra pods during update
      maxUnavailable: 0   # Zero downtime — all existing pods stay until new ones are ready
  template:
    metadata:
      labels:
        app: api-server
        version: v2
    spec:
      containers:
      - name: api
        image: myregistry/api-server:2.1.0
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
        - name: REDIS_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: redis-url
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /readyz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          failureThreshold: 3
        startupProbe:
          httpGet:
            path: /healthz
            port: 8080
          failureThreshold: 30
          periodSeconds: 10
      terminationGracePeriodSeconds: 60
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - api-server
              topologyKey: kubernetes.io/hostname

Rolling Updates and Rollbacks

# Update the image (triggers a rolling update)
kubectl set image deployment/api-server api=myregistry/api-server:2.2.0

# Watch the rollout progress
kubectl rollout status deployment/api-server

# View rollout history
kubectl rollout history deployment/api-server

# View details of a specific revision
kubectl rollout history deployment/api-server --revision=3

# Rollback to the previous version
kubectl rollout undo deployment/api-server

# Rollback to a specific revision
kubectl rollout undo deployment/api-server --to-revision=2

# Pause a rollout (for canary-style testing)
kubectl rollout pause deployment/api-server

# Resume a paused rollout
kubectl rollout resume deployment/api-server

# Scale a deployment
kubectl scale deployment/api-server --replicas=5

Pod Lifecycle

Phase Description
PendingPod accepted but containers not yet created (image pulling, scheduling)
RunningPod bound to a node, all containers created, at least one running
SucceededAll containers terminated successfully and will not restart
FailedAll containers terminated, at least one terminated in failure
UnknownPod state cannot be obtained (usually node communication failure)

Health Checks: Probes

Kubernetes uses three types of probes to determine container health and readiness:

  • Liveness Probe: Determines if a container is running. If it fails, kubelet kills the container and applies the restart policy.
  • Readiness Probe: Determines if a container is ready to serve traffic. Failing pods are removed from Service endpoints.
  • Startup Probe: Determines if a container application has started. Disables liveness/readiness checks until it succeeds — useful for slow-starting applications.

Key Takeaways

  • Pods are the smallest deployable unit — they contain one or more containers sharing network and storage
  • Deployments manage ReplicaSets to ensure the desired number of Pod replicas are running
  • Rolling updates provide zero-downtime deployments with easy rollback capability
  • Always configure resource requests/limits and health probes for production workloads
  • Use pod anti-affinity to spread replicas across nodes for high availability

Continue Learning