Skip to content

Kubernetes Pods

Pods are the smallest deployable units in Kubernetes that can be created and managed.

What is a Pod?

A Pod represents a single instance of a running process in your cluster and can contain one or more containers.

┌─────────────────────────────────────┐
│             POD                     │
│  ┌──────────────┐  ┌─────────────┐ │
│  │  Container 1 │  │ Container 2 │ │
│  │   (nginx)    │  │  (sidecar)  │ │
│  └──────────────┘  └─────────────┘ │
│                                     │
│  ┌──────────────────────────────┐  │
│  │     Shared Network (IP)      │  │
│  └──────────────────────────────┘  │
│                                     │
│  ┌──────────────────────────────┐  │
│  │     Shared Storage Volumes   │  │
│  └──────────────────────────────┘  │
└─────────────────────────────────────┘

Key Characteristics: - Shared network namespace (same IP) - Shared storage volumes - Shared IPC namespace - Ephemeral by nature - Scheduled together on same node

Basic Pod Definition

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    environment: production
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80

Pod Lifecycle

Pod Phases

Pending → Running → Succeeded/Failed

Phases: - Pending: Accepted but not running yet - Running: At least one container is running - Succeeded: All containers terminated successfully - Failed: All containers terminated, at least one failed - Unknown: Pod state cannot be determined

# Check pod phase
kubectl get pod nginx-pod -o jsonpath='{.status.phase}'

Container States

Waiting: Container is not running (pulling image, etc.)

state:
  waiting:
    reason: ContainerCreating

Running: Container is executing

state:
  running:
    startedAt: "2024-01-01T10:00:00Z"

Terminated: Container finished execution

state:
  terminated:
    exitCode: 0
    reason: Completed
    startedAt: "2024-01-01T10:00:00Z"
    finishedAt: "2024-01-01T10:05:00Z"

Pod Conditions

status:
  conditions:
  - type: PodScheduled
    status: "True"
  - type: Initialized
    status: "True"
  - type: ContainersReady
    status: "True"
  - type: Ready
    status: "True"

Multi-Container Pods

Sidecar Pattern

Helper container alongside main container:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  containers:
  - name: app
    image: myapp:1.0
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log

  - name: log-shipper
    image: fluentd:latest
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log

  volumes:
  - name: shared-logs
    emptyDir: {}

Ambassador Pattern

Proxy container for external services:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-ambassador
spec:
  containers:
  - name: app
    image: myapp:1.0
    env:
    - name: DATABASE_HOST
      value: localhost
    - name: DATABASE_PORT
      value: "5432"

  - name: db-proxy
    image: ambassador-proxy:latest
    ports:
    - containerPort: 5432

Adapter Pattern

Transform output to standard format:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-adapter
spec:
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: logs
      mountPath: /var/log

  - name: log-adapter
    image: log-formatter:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log

  volumes:
  - name: logs
    emptyDir: {}

Init Containers

Run before app containers start:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  initContainers:
  - name: init-db
    image: busybox:1.35
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done']

  - name: init-config
    image: busybox:1.35
    command: ['sh', '-c', 'echo "Initializing config" && sleep 5']

  containers:
  - name: myapp
    image: myapp:1.0

Init Container Characteristics: - Run sequentially - Must complete successfully - Run before app containers - Useful for setup tasks

Container Configuration

Resource Requests and Limits

apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Environment Variables

apiVersion: v1
kind: Pod
metadata:
  name: env-demo
spec:
  containers:
  - name: app
    image: nginx
    env:
    # Static value
    - name: ENVIRONMENT
      value: "production"

    # From ConfigMap
    - name: CONFIG_VALUE
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_url

    # From Secret
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: password

    # From field
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name

    # From resource field
    - name: CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          containerName: app
          resource: limits.cpu

Volume Mounts

apiVersion: v1
kind: Pod
metadata:
  name: volume-demo
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
    - name: data-volume
      mountPath: /data
    - name: cache-volume
      mountPath: /cache

  volumes:
  - name: config-volume
    configMap:
      name: app-config
  - name: data-volume
    persistentVolumeClaim:
      claimName: data-pvc
  - name: cache-volume
    emptyDir: {}

Health Checks

Liveness Probe

Restart container if unhealthy:

apiVersion: v1
kind: Pod
metadata:
  name: liveness-demo
spec:
  containers:
  - name: app
    image: myapp:1.0
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3

Readiness Probe

Remove from service if not ready:

apiVersion: v1
kind: Pod
metadata:
  name: readiness-demo
spec:
  containers:
  - name: app
    image: myapp:1.0
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

Startup Probe

For slow-starting containers:

apiVersion: v1
kind: Pod
metadata:
  name: startup-demo
spec:
  containers:
  - name: app
    image: myapp:1.0
    startupProbe:
      httpGet:
        path: /startup
        port: 8080
      failureThreshold: 30
      periodSeconds: 10

Probe Types

HTTP GET:

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
    httpHeaders:
    - name: Custom-Header
      value: Awesome

TCP Socket:

livenessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 20

Exec Command:

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

gRPC:

livenessProbe:
  grpc:
    port: 9090
  initialDelaySeconds: 10

Pod Security

Security Context

apiVersion: v1
kind: Pod
metadata:
  name: security-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault

  containers:
  - name: app
    image: nginx
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      runAsNonRoot: true
      capabilities:
        drop:
        - ALL
        add:
        - NET_BIND_SERVICE

Service Account

apiVersion: v1
kind: Pod
metadata:
  name: sa-demo
spec:
  serviceAccountName: my-service-account
  automountServiceAccountToken: true
  containers:
  - name: app
    image: nginx

Pod Scheduling

Node Selector

apiVersion: v1
kind: Pod
metadata:
  name: node-selector-demo
spec:
  nodeSelector:
    disktype: ssd
    environment: production
  containers:
  - name: nginx
    image: nginx

Node Affinity

apiVersion: v1
kind: Pod
metadata:
  name: affinity-demo
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/arch
            operator: In
            values:
            - amd64
            - arm64
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: nginx
    image: nginx

Pod Affinity/Anti-Affinity

apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity-demo
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - cache
        topologyKey: kubernetes.io/hostname

    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - web
          topologyKey: kubernetes.io/hostname
  containers:
  - name: nginx
    image: nginx

Taints and Tolerations

apiVersion: v1
kind: Pod
metadata:
  name: toleration-demo
spec:
  tolerations:
  - key: "key1"
    operator: "Equal"
    value: "value1"
    effect: "NoSchedule"
  - key: "key2"
    operator: "Exists"
    effect: "NoExecute"
    tolerationSeconds: 3600
  containers:
  - name: nginx
    image: nginx

Pod Disruption Budget

Ensure minimum availability during disruptions:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: app-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: myapp

Pod Commands

# Create pod
kubectl run nginx --image=nginx

# Create from YAML
kubectl apply -f pod.yaml

# List pods
kubectl get pods
kubectl get pods -o wide
kubectl get pods --all-namespaces

# Describe pod
kubectl describe pod nginx-pod

# View logs
kubectl logs nginx-pod
kubectl logs nginx-pod -c container-name
kubectl logs nginx-pod --previous
kubectl logs -f nginx-pod

# Execute command
kubectl exec nginx-pod -- ls /
kubectl exec -it nginx-pod -- /bin/bash

# Port forward
kubectl port-forward nginx-pod 8080:80

# Copy files
kubectl cp nginx-pod:/path/to/file ./local-file
kubectl cp ./local-file nginx-pod:/path/to/file

# Delete pod
kubectl delete pod nginx-pod
kubectl delete pod nginx-pod --grace-period=0 --force

Best Practices

  1. Single Responsibility
  2. One main process per container
  3. Use sidecars for supporting functions

  4. Resource Management

  5. Always set resource requests
  6. Set appropriate limits
  7. Monitor actual usage

  8. Health Checks

  9. Implement liveness probes
  10. Implement readiness probes
  11. Use startup probes for slow apps

  12. Security

  13. Run as non-root user
  14. Use read-only root filesystem
  15. Drop unnecessary capabilities
  16. Use security contexts

  17. Logging

  18. Log to stdout/stderr
  19. Use structured logging
  20. Include correlation IDs

  21. Configuration

  22. Use ConfigMaps for config
  23. Use Secrets for sensitive data
  24. Don't hardcode values

References