Understanding Pod Controllers in Kubernetes

Common Pod Spec Fields

spec.containers <[]object>

  • spec.containers.name <string>: Container name, required and unique. Cannot be changed after creation.
  • spec.containers.image <string>: Image path/name:tag.
  • spec.containers.imagePullPolicy <string>: Image pull policy: Always, Never, IfNotPresent. Default is IfNotPresent, except for latest tags where it defaults to Always. This field is immutable after creation.
  • spec.containers.ports: List of ports exposed by the container. This is informational and does not affect network acessibility. Any port listening on 0.0.0.0 inside the container is accessible from the network.
    • containerPort <integer> (required): Port exposed by the Pod.
    • hostPort <integer>: Port exposed on the host.
    • protocol <string>: Port protocol.
    • hostIP <string>: Host IP to bind.
  • spec.containers.command <[]string>: Entrypoint command (similar to Docker's entrypoint). Does not run in a shell. If omitted, the image's ENTRYPOINT is used.
  • spec.containers.args <[]string>: Arguments to the entrypoint. If defined, the image's CMD is ignored. Use $(VAR_NAME) for varible references; escape as $$(VAR_NAME) to avoid substitution.

Official documentation for arguments and commands:

https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/

spec.containers.volumeMounts

  • name: Volume name.
  • mountPath: Path to mount the volume; cannot contain :.
  • subPath: Mount a subpath without overwriting existing files.
  • readOnly: Whether to mount as read-only (default false).

spec.containers.resources

  • limits: Resource limits.
    • cpu: CPU limit; can be exceeded temporarily without termination.
    • memory: Memory limit; cannot be exceeded; if exceeded, container may be terminated or rescheduled.
  • requests: Resource requests.
    • cpu: CPU request; used for scheduling; can be exceeded.
    • memory: Memory request; used for scheduling; can be exceeded, but may be evicted if Node memory is low.

spec.nodeSelector <map[string]string>

spec:
  nodeSelector:
    disktype: ssd

Targets Pods to nodes with matching labels.

spec.restartPolicy <string>

spec:
  restartPolicy: Always

Options: Always (restart on any exit), OnFailure (restart only on non-zero exit), Never (never restart). Kubelet applies exponential backoff delay (10s, 20s, 40s… up to 5 minutes) and resets after 10 minutes of successful execution.

Labels and Selectors

Labels are key-value pairs (key=value) that can be attached to any resource. A resource can have multiple labels, and the same label can be applied to different resources.

  • Key: Alphanumeric characters, _, -, .; must start and end with an alphanumeric character.
  • Value: Can be empty; must start and end with an alphanumeric character.

Label Selectors

Equality-based selectors: =, ==, !=

Set-based selectors:

  • KEY notin (VALUE1, VALUE2)
  • KEY notin (VALUE1, VALUE2)
  • KEY
  • !KEY

Many resources support embedded label selectors:

  • matchLabels: Direct key-value matching.
  • matchExpressions: Expression-based selection with {key: "KEY", operator: "OPERATOR", values: [VAL1, VAL2, ...]}.
    • Operators: In, NotIn (requires non-empty values), Exists, NotExists (requires empty values).

Label Operations

List all Pod labels:

kubectl get pods --show-labels

Add a label to a Pod:

kubectl label pods pod-demo release=canary

Overwrite an existing label:

kubectl label pods pod-demo release=canary1 --overwrite

Filter Pods by label:

kubectl get pods -l app --show-labels

View Node labels:

kubectl get nodes --show-labels

Add a label to a Node:

kubectl label node ubuntu disktype=ssd

Schedule a Pod to a specific node using nodeSelector:

spec:
  nodeSelector:
    disktype: ssd

Container Probes

Kubernetes supports three probe types:

  • ExecAction: Executes a command inside the container; success if exit code is 0.
  • TCPSocketAction: Attempts a TCP connection to the specified port; success if connection established.
  • HTTPGetAction: Performs an HTTP GET request on the container's IP; success if resposne status code is not an error.

Liveness Probe (ExecAction)

liveness-exec.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
spec:
  containers:
  - name: liveness-exec-pod
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/healthy;sleep 30;rm -rf /tmp/healthy;sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/healthy"]
      initialDelaySeconds: 2
      periodSeconds: 5

Liveness Probe (HTTPGetAction)

liveness-httpget.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
spec:
  containers:
  - name: liveness-httpget-pod
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    livenessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 2
      periodSeconds: 5

Readiness Probe (HTTPGetAction)

readiness-httpget.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-pod
spec:
  containers:
  - name: readiness-httpget-pod
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 2
      periodSeconds: 5

Lifecycle Hooks: postStart and preStop

poststart-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: poststart-pod
spec:
  containers:
  - name: busybox-httpd
    image: busybox
    imagePullPolicy: IfNotPresent
    lifecycle:
      postStart:
        exec:
          command: ["mkdir", "-p", "/data/web/html"]
    command: ["/bin/sh","-c","sleep 3600"]

Pod Controller Types

ReplicaSet

ReplicaSet manages stateless Pods, ensuring a specified number of replicas run at all times. It supports rolling updates and auto-scaling. It is considered the successor to ReplicationController.

Three core components:

  1. Desired replica count.
  2. Label selector to identify managed Pods.
  3. Pod template.

Kubernetes recommends using Deployment instead of ReplicaSet directly.

Deployment

Deployment operates above ReplicaSet, providing advanced features like version rollbacks, declarative updates, and pause/resume. It is the preferred controller for stateless applications.

DaemonSet

DaemonSet ensures that exactly one Pod replica runs on each Node (or a subset of Nodes). It is typically used for system daemons like log collectors or monitoring agents. Pods are automatically created on new Nodes and recreated if they fail.

Job

Job runs a task to completion. If the task fails, the Job recreates the Pod until successful completion. It is ideal for batch processing.

CronJob

CronJob runs Jobs on a schedule, similar to cron in Unix. It handles overlapping executions according to configuration.

StatefulSet

StatefulSet manages stateful applications where each Pod has a unique identity and persistent storage. It is used for databases, message queues, and similar workloads.

Custom Resources and Helm

  • Custom Resource Definitions (CRDs): Extend the Kubernetes API with custom resources.
  • Helm: A package manager for Kubernetes, similar to yum on Linux, simplifying deployment of complex applications.

ReplicaSet Resource Manifest

Top-level fields:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
spec:

Key spec fields:

replicas    <integer>
selector    <Object>
template    <Object>

The template embeds Pod metadata and spec.

Example rs-demo.yaml:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        release: canary
        environment: qa
    spec:
      containers:
      - name: myapp-container
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

Create the ReplicaSet:

kubectl create -f rs-demo.yaml

List ReplicaSets (alias rs):

kubectl get rs

Note: The Pod name defined in the template (name: myapp-pod) is ignored; Pods are named {controller-name}-{random-string}.

Deployment Resource Manifest

Deployment leverages ReplicaSet and keeps up to 10 historical versions by default. It supports declarative updates via kubectl apply -f.

Top-level fields:

apiVersion: apps/v1
kind: Deployment
metadata:
spec:

Key spec fields:

replicas          <integer>
selector          <Object>
template          <Object> -required-
strategy          <Object>
paused            <boolean>
revisionHistoryLimit <integer>

Strategy

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  • type: Recreate (delete all then recreate) or RollingUpdate (gradually replace). RollingUpdate enables rollingUpdate sub-field.

  • rollingUpdate.maxSurge: Maximum number of extra Pods during update (absolute or percentage).

  • rollingUpdate.maxUnavailable: Maximum number of unavailable Pods during update (absolute or percentage).

  • revisionHistoryLimit: Number of old ReplicaSets to retain for rollback (default 10; 0 disables).

  • paused: If true, deployment is paused; no new updates are applied until unpaused.

  • template: Pod template (same as ReplicaSet).

Example deploy-demo.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

Create declaratively:

kubectl apply -f deploy-demo.yaml
kubectl get deploy

This automatically creates a ReplicaSet named {deploy-name}-{pod-template-hash}.

Updating a Deployment

Edit the manifest (e.g., change image to v2) and reapply:

kubectl apply -f deploy-demo.yaml

Access the new version; the Pods should be updated to v2.

View rollout history:

kubectl rollout history deployment myapp-deploy

Update via patch (e.g., change replicas to 5):

kubectl patch deployment myapp-deploy -p '{"spec": {"replicas": 5}}'

Patch rolling update strategy:

kubectl patch deployment myapp-deploy -p '{"spec": {"strategy": {"type": "RollingUpdate", "rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0}}}}'

Verify the strategy:

kubectl describe deploy myapp-deploy

DaemonSet Resource Manifest

DaemonSet does not require replicas. Key spec fields:

revisionHistoryLimit  <integer>
selector              <Object>
template              <Object> -required-
updateStrategy        <Object>

Update Strategy

spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 2

Two types: RollingUpdate (gradually, only decreases available count) and OnDelete (manual Pod deletion triggers update). When using RollingUpdate, maxUnavailable is the only sub-field.

Example filebeat-ds.yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat-ds
  namespace: default
spec:
  selector:
    matchLabels:
      app: filebeat
      release: stable
  template:
    metadata:
      labels:
        app: filebeat
        release: stable
    spec:
      containers:
      - name: filebeat
        image: ikubernetes/filebeat:5.6.5-alpine
        env:
        - name: REDIS_HOST
          value: redis-svc
        - name: REDIS_LOG_LEVEL
          value: info

Note: replicas is not specified in a DaemonSet manifest.

Tags: kubernetes pod-controllers replicaset deployment daemonset

Posted on Tue, 26 May 2026 22:31:30 +0000 by yarons