Qingular

Workload Controllers

·CKAk8sPractice

Creating and operating Deployment, StatefulSet, DaemonSet, Job, CronJob

← Back to CKA Practice Index

Overview

Workload controllers manage Pod lifecycle, replica count, update strategies, and more. The CKA exam focuses on Deployment, DaemonSet, Job, and CronJob.


1. Deployment

1.1 Create Deployment

kubectl create deployment web --image=nginx --replicas=3

# Generate YAML (--dry-run=client -o yaml is commonly used)
kubectl create deployment web --image=nginx --replicas=3 --dry-run=client -o yaml > deploy.yaml

# Expose Service
kubectl expose deployment web --port=80 --target-port=80 --type=NodePort

1.2 YAML Example

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

1.3 Rolling Update (RollingUpdate)

# Update image
kubectl set image deployment/nginx-deployment nginx=nginx:1.26

# Or edit YAML
kubectl edit deployment/nginx-deployment

# Specify update strategy (Recreate / RollingUpdate)
kubectl patch deployment nginx-deployment -p '{"spec":{"strategy":{"type":"RollingUpdate","rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"}}}}'

# View update status
kubectl rollout status deployment/nginx-deployment
kubectl rollout history deployment/nginx-deployment

Update Strategy Comparison

StrategyDescriptionUse Case
RollingUpdateGradually replace Pods, supports maxSurge/maxUnavailableDefault strategy, zero downtime
RecreateDelete all old Pods first, then create new PodsDevelopment environment, database migration
# RollingUpdate configuration
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # Maximum number of Pods allowed beyond the desired replica count (number or percentage)
      maxUnavailable: 0    # Maximum number of Pods allowed to be unavailable during the update

1.4 Rollback

# Roll back to the previous revision
kubectl rollout undo deployment/nginx-deployment

# Roll back to a specific revision
kubectl rollout undo deployment/nginx-deployment --to-revision=2

# View revision history
kubectl rollout history deployment/nginx-deployment

# View details of a specific revision
kubectl rollout history deployment/nginx-deployment --revision=2

1.5 Scaling

# Manual scaling
kubectl scale deployment/nginx-deployment --replicas=5
kubectl scale deployment/nginx-deployment --replicas=2

2. ReplicaSet

ReplicaSet ensures a specified number of Pods are always running. Usually managed automatically by Deployments; direct management is not recommended.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: nginx
# View ReplicaSet (RS)
kubectl get replicasets
kubectl get rs

# View the association between RS and Deployment
kubectl describe deployment nginx-deployment | grep ReplicaSet
kubectl get rs -l app=nginx

# Delete RS (also deletes the Pods it manages, but you cannot directly delete an RS managed by a Deployment)
kubectl delete rs <rs-name>

Note: The CKA exam does not require manually creating RS, but you need to understand that RS is the foundation for how Deployments manage Pods.


3. StatefulSet

Used for stateful applications (databases, message queues, etc.), providing stable network identities and persistent storage.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

Key Features

FeatureDescription
Ordered DeploymentPods are created sequentially from 0 to N-1 (web-0, web-1, web-2)
Ordered Scale-downDeleted sequentially from N-1 to 0
Stable Network IdentityPod names are stable: <statefulset>-<ordinal>
Stable StoragePVCs are retained when decoupled from Pods
# View StatefulSet Pod names
kubectl get pods -l app=nginx    # Output: web-0, web-1, web-2

# Access via stable DNS
# <pod>.<service>.<namespace>.svc.cluster.local
# web-0.nginx.default.svc.cluster.local

Update Strategies

# OnDelete: Update after manually deleting Pods
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"OnDelete"}}}'

# RollingUpdate (default): Update sequentially
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'

# Partitioned update
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'

4. DaemonSet

Runs one Pod on each node (or on matching nodes).

Typical Use Cases

  • Node monitoring (Node Exporter)
  • Log collection (Fluentd, Filebeat)
  • Network plugins (Calico, Flannel)
  • Storage plugins (Ceph, GlusterFS)
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      tolerations:
      - operator: Exists
      containers:
      - name: fluentd
        image: fluent/fluentd:v1.16
# Create DaemonSet
kubectl apply -f daemonset.yaml

# View DaemonSet
kubectl get daemonsets
kubectl get ds

# View Pods on each node
kubectl get pods -o wide

# Update image
kubectl set image ds/fluentd fluentd=fluent/fluentd:v1.17

# View rolling update status
kubectl rollout status ds/fluentd

# Exam tip: Imperative creation of DaemonSet
kubectl create deployment fluentd --image=fluent/fluentd --dry-run=client -o yaml > ds.yaml
# Then edit ds.yaml to change kind to DaemonSet and remove replicas

5. Job

Executes one-off tasks, Pods automatically terminate upon completion.

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  completions: 5           # Number of Pods that need to complete successfully
  parallelism: 2           # Number of parallel executions
  backoffLimit: 4          # Failure retry count
  activeDeadlineSeconds: 30  # Task timeout
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
# Create Job
kubectl create job pi --image=perl:5.34 -- perl -Mbignum=bpi -wle 'print bpi(2000)'

# Create Job (generate YAML from CronJob)
kubectl create job test-job --from=cronjob/backup-cronjob -n default

# View Job status
kubectl get jobs
kubectl describe job pi

# View Job Pod logs
kubectl logs job/pi
kubectl logs -l job-name=pi

# Delete Job
kubectl delete job pi

# Important: restartPolicy can only be Never or OnFailure

Advanced Parameters

ParameterDescriptionDefault
.spec.completionsNumber of Pods to complete1
.spec.parallelismNumber of parallel Pods1
.spec.backoffLimitFailure retry count6
.spec.activeDeadlineSecondsTask timeout durationUnlimited
.spec.ttlSecondsAfterFinishedAuto-cleanup timeUnlimited

6. CronJob

Scheduled execution of Jobs, based on standard Cron syntax.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"    # Execute every minute
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            command: ["echo", "Hello CKA"]
          restartPolicy: OnFailure
  startingDeadlineSeconds: 100  # Startup deadline
  concurrencyPolicy: Forbid     # Allow / Forbid / Replace
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
# Create CronJob
kubectl create cronjob hello --image=busybox:1.28 --schedule="*/1 * * * *" -- echo "Hello CKA"

# View CronJob
kubectl get cronjobs
kubectl get cj

# View triggered Jobs
kubectl get jobs

# Suspend CronJob
kubectl patch cronjob hello -p '{"spec":{"suspend":true}}'

# Resume
kubectl patch cronjob hello -p '{"spec":{"suspend":false}}'

# Manually trigger
kubectl create job --from=cronjob/hello manual-job

Cron Syntax Quick Reference

Minute Hour Day Month Weekday
*/1    *    *   *     *       Every minute
0      *    *   *     *       Every hour
0      8    *   *     1       Every Monday 8:00
0      0    1   *     *       1st of every month 0:00
*/5    *    *   *     *       Every 5 minutes

CronJob Parameters

ParameterDescription
concurrencyPolicy: AllowAllow concurrent execution (default)
concurrencyPolicy: ForbidForbid concurrency, skip if previous is incomplete
concurrencyPolicy: ReplaceReplace the previous running Job
startingDeadlineSecondsMaximum wait time after missing a schedule
successfulJobsHistoryLimitNumber of retained successful Job history
failedJobsHistoryLimitNumber of retained failed Job history

7. Useful Exam Commands

# Create Deployment and generate YAML
kubectl create deployment web --image=nginx --replicas=3 --dry-run=client -o yaml

# Update Deployment image
kubectl set image deployment/web nginx=nginx:1.26

# View rollout status
kubectl rollout status deployment/web
kubectl rollout history deployment/web

# Rollback
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=1

# Scaling
kubectl scale deployment/web --replicas=5

# Create Job and CronJob (--dry-run supported)
kubectl create job pi --image=perl:5.34 -- perl -Mbignum=bpi -wle 'print bpi(2000)' --dry-run=client -o yaml
kubectl create cronjob hello --image=busybox:1.28 --schedule="*/1 * * * *" --dry-run=client -o yaml

# JSON method for creating DaemonSet
kubectl run ds-test --image=nginx --restart=Always --dry-run=client -o yaml | sed 's/kind: Deployment/kind: DaemonSet/' | sed '/replicas/d'

🧪 Complete Hands-on Example: Create a Deployment, Perform Rolling Update and Rollback

Scenario

Create an nginx Deployment, update the image version, then perform a rollback.

Prerequisites

  • A working Kubernetes cluster
  • kubectl is configured to connect to the cluster

Steps

Step 1: Create Deployment

kubectl create deployment web --image=nginx:1.25 --replicas=3
# Expected output: deployment.apps/web created

kubectl get deployment web
# Expected output: NAME   READY   UP-TO-DATE   AVAILABLE   AGE
#          web    3/3     3            3           <seconds>

kubectl get pods -l app=web
# Expected output: NAME                   READY   STATUS    RESTARTS   AGE
#          web-<hash1>-<pod-id>   1/1     Running   0          <seconds>
#          web-<hash2>-<pod-id>   1/1     Running   0          <seconds>
#          web-<hash3>-<pod-id>   1/1     Running   0          <seconds>

Step 2: Upgrade Image Version (Rolling Update)

kubectl set image deployment/web nginx=nginx:1.26
# Expected output: deployment.apps/web image updated

# Observe the rolling update process
kubectl rollout status deployment/web
# Expected output: Waiting for rollout to finish: 2 out of 3 new replicas are available...
#          deployment "web" successfully rolled out

Step 3: View Rolling Update History

kubectl rollout history deployment/web
# Expected output: deployment.apps/web
#          REVISION  CHANGE-CAUSE
#          1         <none>
#          2         <none>

kubectl rollout history deployment/web --revision=2
# Expected output: deployment.apps/web with revision #2
#          Pod Template:
#            Labels:	app=web
#            Containers:
#             nginx:
#              Image:	nginx:1.26

Step 4: Perform Rollback

# Roll back to the previous revision
kubectl rollout undo deployment/web
# Expected output: deployment.apps/web rolled back

# Confirm rollback is complete
kubectl rollout status deployment/web
# Expected output: deployment "web" successfully rolled out

# Verify image version has been restored
kubectl describe deployment web | grep Image
# Expected output: nginx:1.25

# Roll back to a specific revision (optional)
kubectl rollout undo deployment/web --to-revision=2

Verification

# Check current replica count and image version
kubectl get deployment web -o wide
# Expected output shows 3/3 READY, IMAGE is nginx:1.25

# Check all Pods are running normally
kubectl get pods -l app=web
# Expected output: 3 Pods all in Running status

# Cleanup
kubectl delete deployment web
# Expected output: deployment.apps "web" deleted

Exam Tips

  • Using percentages for maxSurge and maxUnavailable in rolling updates is more flexible and is a CKA exam topic
  • kubectl set image is the fastest way to update, but the exam often also requires using kubectl edit or kubectl patch
  • ReplicaSet history is not deleted after rollback; you can roll back to any historical revision again
  • Using the --record flag when creating a Deployment records command history in CHANGE-CAUSE (older K8s versions)
  • Deployment rollback is essentially replacing the Pod template with the ReplicaSet corresponding to the historical revision