Prerequisites: Linux CLI, TCP/IP, basic knowledge of containers and Kubernetes
Table of Contents
- 1. Course Overview
- 2. Using Controllers to Deploy Applications — Deployment Basics
- 3. Maintaining Applications with Deployments
- 4. DaemonSets, Jobs, CronJobs, and StatefulSets
- 5. Reference Diagrams
- 6. Reference YAML Snippets
- 7. Controller Reference Tables
- 8. Essential kubectl Commands
- 9. Best Practices
1. Course Overview
This course covers all Kubernetes controllers used to deploy and manage workloads in production:
- Introduction to controllers: understand what they are and how they maintain desired state
- The Deployment controller: the main mechanism for deploying, updating, rolling back, and scaling applications
- Additional controllers:
DaemonSet,Job,CronJob, andStatefulSetfor specialized workloads
Lab Environment
| Node | Role | OS | vCPU | RAM |
|---|---|---|---|---|
| c1-cp1 | Control Plane | Ubuntu 22.04 | 2 | 2 GB |
| c1-node1 | Worker | Ubuntu 22.04 | 2 | 2 GB |
| c1-node2 | Worker | Ubuntu 22.04 | 2 | 2 GB |
| c1-node3 | Worker | Ubuntu 22.04 | 2 | 2 GB |
2. Using Controllers to Deploy Applications — Deployment Basics
2.1 Kubernetes Core Principles
- Desired State & Declarative Configuration: describe the desired application state in code (YAML), and Kubernetes converges toward that state
- Controllers: monitor the current cluster state and make the necessary changes to reach desired state
- API Server: the cluster information center — all interactions go through it
2.2 The Controller Manager
| Controller Manager | Role |
|---|---|
kube-controller-manager | Native cluster controllers (Deployment, ReplicaSet, DaemonSet, Job, etc.) — runs on the control plane |
cloud-controller-manager | Cloud infrastructure integration (load balancers, storage, nodes) |
The controller manager implements watch loops:
Watch Loop:
1. Observe → read current state from API server
2. Diff → compare with desired state
3. Act → make changes if needed
2.3 Main Controllers Overview
graph TD
A[Controller Manager] --> B[Deployment]
A --> C[StatefulSet]
A --> D[DaemonSet]
A --> E[Job]
A --> F[CronJob]
B --> G[ReplicaSet]
G --> H[Pod]
C --> I[Pod with stable identity]
D --> J[Pod per node]
E --> K[Single completion Pod]
F --> L[Scheduled Job]
| Controller | Short Description |
|---|---|
Deployment | Declarative deployment with rolling updates and rollback |
StatefulSet | Stateful applications with persistent naming and stable storage |
DaemonSet | One Pod per node (or subset of nodes) |
Job | Task run to completion |
CronJob | Job scheduled on a cron schedule |
ReplicaSet | Maintains a number of Pod replicas (managed by Deployment) |
2.4 The Deployment Controller — Basics
The Deployment is the primary mechanism for deploying stateless applications. It provides:
- Declarative updates of ReplicaSets and their Pods
- Orchestrated creation and deletion of Pods
- Rollout management (new versions) with configurable update strategy
- Rollback to a previous version
- Scaling manual or automatic (HPA)
| Section | Description |
|---|---|
selector | Labels to identify Pods belonging to the Deployment |
replicas | Desired Pod count |
template | Pod specification (image, ports, probes, etc.) |
strategy | Update strategy (RollingUpdate or Recreate) |
2.5 The ReplicaSet Controller
Deploys a defined number of Pods and ensures that number stays constant, even during failures.
Behavior during failure:
- A Pod disappears (crash, dead node, manual deletion)
- ReplicaSet controller detects fewer Pods matching the selector than desired
- Creates a new Pod to reach the desired state
Best practice: Never create ReplicaSets directly. Always use Deployments which manage ReplicaSets automatically.
2.6 Demos — Deployment and ReplicaSet
# Create a deployment imperatively
kubectl create deployment hello-world --image=my-registry/hello-app:1.0
# Scale to 5 replicas
kubectl scale deployment hello-world --replicas=5
# Create with image AND replicas in one command
kubectl create deployment hello-world --image=my-registry/hello-app:1.0 --replicas=5
# Apply declaratively
kubectl apply -f deployment.yaml
# Inspect resources
kubectl get replicasets
kubectl describe replicaset hello-world-<hash>
# View Pods with their labels
kubectl get pods --show-labels
# Isolate a Pod by changing its label
kubectl label pod <pod-name> app=DEBUG --overwrite
3. Maintaining Applications with Deployments
3.1 Updating a Deployment
An update is triggered by any change in the Pod template (spec.template):
- Container image change (most common)
- Environment variables, secrets, resources, restart policy
Important: Modifying
replicascount does not trigger a rollout.
Rolling update process:
- Creates a new ReplicaSet with the new configuration
- Scales up the new ReplicaSet progressively
- Scales down the old ReplicaSet progressively
- Old ReplicaSet remains at 0 replicas (for rollback)
kubectl rollout status deployment hello-world
kubectl rollout history deployment hello-world
kubectl rollout history deployment hello-world --revision=2
3.2 Controlling Rollouts — UpdateStrategy
| Strategy | Behavior |
|---|---|
RollingUpdate | Progressive transition between old and new ReplicaSet. Default strategy. |
Recreate | Stops all old Pods before starting new ones. Causes downtime, but useful when two versions can’t coexist. |
RollingUpdate Parameters:
| Parameter | Description | Default |
|---|---|---|
maxUnavailable | Max Pods that can be unavailable during update (int or %) | 25% |
maxSurge | Max extra Pods that can exist during update (int or %) | 25% |
Other control fields:
| Field | Description |
|---|---|
progressDeadlineSeconds | If rollout doesn’t progress within this time, it’s marked as failed |
revisionHistoryLimit | Number of ReplicaSets kept to enable rollbacks (default: 10) |
minReadySeconds | Minimum time a Pod must be Ready before considered available |
3.3 Readiness Probes and Controlled Rollouts
A Readiness Probe tells Kubernetes whether a Pod is ready to receive traffic.
With a Readiness Probe, the Deployment halts the rollout if the number of Pods failing the probe drops below maxUnavailable. This protects the application by keeping old Pods active during updates.
| Parameter | Description |
|---|---|
initialDelaySeconds | Delay before first check (for slow-starting apps) |
periodSeconds | Interval between checks |
failureThreshold | Consecutive failures before marking Pod as non-ready |
3.4 Pause, Resume, and Rollback
# Pause an ongoing rollout
kubectl rollout pause deployment hello-world
# Resume rollout after modifications
kubectl rollout resume deployment hello-world
# Roll back to previous version
kubectl rollout undo deployment hello-world
# Roll back to a specific revision
kubectl rollout undo deployment hello-world --to-revision=1
# Restart a Deployment
kubectl rollout restart deployment hello-world
3.5 Scaling Deployments
# Manual scaling
kubectl scale deployment hello-world --replicas=10
# Autoscaling (HPA)
kubectl autoscale deployment hello-world --min=2 --max=10 --cpu-percent=80
4. DaemonSets, Jobs, CronJobs, and StatefulSets
4.1 DaemonSets
Guarantees one Pod copy runs on each node (or subset of nodes).
Typical use cases:
| Workload | Description |
|---|---|
kube-proxy | Networking — present in all Kubernetes clusters |
| Log agents (Fluentd, Filebeat) | Log collection on each node |
| Monitoring agents (Prometheus Node Exporter) | System metrics per node |
| Security agents | Scanning, intrusion detection |
| CNI network plugins | Calico-node, Cilium, etc. |
Update strategies:
| Strategy | Behavior |
|---|---|
RollingUpdate | Old Pods are terminated and replaced automatically. Default. |
OnDelete | New Pods are only created when you manually delete old ones. Full control. |
# Label a node to enable selective DaemonSet deployment
kubectl label node c1-node1 node=hello-world-ns
kubectl get daemonsets -o wide
kubectl describe daemonset hello-world-ds
4.2 Jobs
Creates one or more Pods and ensures a specified number of them complete successfully.
Key parameters:
| Parameter | Description |
|---|---|
completions | Total successful completions required (default: 1) |
parallelism | Max Pods running in parallel simultaneously |
backoffLimit | Attempts before marking Job as failed (default: 6) |
restartPolicy | Must be Never or OnFailure (never Always for a Job) |
activeDeadlineSeconds | Maximum Job execution time before cancellation |
restartPolicy | Failure behavior |
|---|---|
Never | Creates new Pod on each failure (up to backoffLimit) |
OnFailure | Restarts container in same Pod (up to backoffLimit) |
kubectl get jobs
kubectl describe job hello-world-job
kubectl get pods --selector=job-name=hello-world-job
kubectl logs <pod-name>
4.3 CronJobs
Creates Job resources at regular intervals using UNIX cron format.
Schedule format: "* * * * *" → minute, hour, day of month, month, day of week
| Schedule | Meaning |
|---|---|
"*/1 * * * *" | Every minute |
"0 * * * *" | Every hour on the hour |
"0 2 * * *" | Daily at 2:00 AM |
"0 0 * * 0" | Sundays at midnight |
concurrencyPolicy:
| Value | Behavior |
|---|---|
Allow | Multiple runs can run in parallel |
Forbid | If a run is in progress, the next is skipped |
Replace | If a run is in progress, it’s cancelled and replaced by the new one |
kubectl get cronjobs
kubectl describe cronjob hello-world-cron
kubectl get jobs --watch
4.4 StatefulSets — Conceptual Introduction
Manages stateful applications where Pods need persistent identities:
- Ordered and persistent naming: Pods are named
<name>-0,<name>-1, etc. — reused on redeploy - Persistent storage: via
PersistentVolumeClaimsstably attached to each Pod viavolumeClaimTemplates - Headless Service: no ClusterIP or load balancer, enabling stateful apps to locate each other via DNS
Use cases: Databases (MongoDB, MySQL, PostgreSQL), cache servers (Redis cluster), messaging systems (Kafka, ZooKeeper)
Ordered operations:
- Scale up: Pods created in order (0, 1, 2…)
- Scale down: Pods deleted in reverse order (N, N-1…)
- Updates: applied in reverse order (newest to oldest)
5. Reference Diagrams
5.1 Controller Hierarchy
graph TD
CM["Controller Manager"]
CM --> DEP["Deployment\nStateless apps"]
CM --> SS["StatefulSet\nStateful apps"]
CM --> DS["DaemonSet\nAgent per node"]
CM --> JOB["Job\nSingle completion task"]
CM --> CJ["CronJob\nScheduled task"]
DEP --> RS["ReplicaSet\nManages Pod count"]
RS --> P1["Pod"]
RS --> P2["Pod"]
RS --> P3["Pod"]
SS --> SP1["Pod-0\n(stable identity)"]
SS --> SP2["Pod-1\n(stable identity)"]
DS --> DP1["Pod\n(node 1)"]
DS --> DP2["Pod\n(node 2)"]
JOB --> JP["Pod\n(run to completion)"]
CJ --> JOB2["Job\n(created per schedule)"]
JOB2 --> JP2["Pod"]
5.2 Reconciliation Flow
sequenceDiagram
participant Admin as Admin
participant API as API Server
participant ETCD as etcd
participant CM as Controller Manager
participant SCH as Scheduler
participant NODE as Node / kubelet
Admin->>API: kubectl apply -f deployment.yaml
API->>ETCD: Persists Deployment object
CM->>API: Watch → detects new Deployment
CM->>API: Creates ReplicaSet
CM->>API: Creates N Pod objects
SCH->>API: Watch → detects unscheduled Pods
SCH->>API: Assigns each Pod to a node
NODE->>API: Watch → detects assigned Pods
NODE->>NODE: Pull image + start container
NODE->>API: Updates Pod status (Running/Ready)
5.3 Rolling Update — Transition Flow
graph LR
subgraph "Initial State — v1.0"
RS1["ReplicaSet-v1\n(10 replicas)"]
end
UPDATE["kubectl apply\n(image: v2.0)"] --> TRANS
subgraph "Transition"
TRANS["Deployment Controller"]
TRANS --> RS2["ReplicaSet-v2\n(scale up)"]
TRANS --> RS1B["ReplicaSet-v1\n(scale down)"]
end
subgraph "Final State — v2.0"
RS3["ReplicaSet-v2\n(10 replicas)"]
RS0["ReplicaSet-v1\n(0 replicas — kept for rollback)"]
end
6. Reference YAML Snippets
6.1 Basic Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 5
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: my-registry/hello-app:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
selector:
app: hello-world
ports:
- port: 80
protocol: TCP
targetPort: 8080
6.2 Deployment with RollingUpdate and Readiness Probe
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 20
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 10%
maxSurge: 2
revisionHistoryLimit: 20
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: my-registry/hello-app:1.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /index.html
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
6.3 DaemonSet on All Nodes
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: hello-world-ds
spec:
selector:
matchLabels:
app: hello-world-app
template:
metadata:
labels:
app: hello-world-app
spec:
containers:
- name: hello-world
image: my-registry/hello-app:1.0
6.4 DaemonSet with NodeSelector
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: hello-world-ds
spec:
selector:
matchLabels:
app: hello-world-app
template:
metadata:
labels:
app: hello-world-app
spec:
nodeSelector:
node: hello-world-ns
containers:
- name: hello-world
image: my-registry/hello-app:1.0
6.5 Simple Job
apiVersion: batch/v1
kind: Job
metadata:
name: hello-world-job
spec:
template:
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- "/bin/bash"
- "-c"
- "/bin/echo Hello from Pod $(hostname) at $(date)"
restartPolicy: Never
6.6 Parallel Job
apiVersion: batch/v1
kind: Job
metadata:
name: hello-world-job-parallel
spec:
completions: 50
parallelism: 10
template:
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- "/bin/bash"
- "-c"
- "/bin/echo Hello from Pod $(hostname) at $(date)"
restartPolicy: Never
6.7 CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello-world-cron
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- "/bin/bash"
- "-c"
- "/bin/echo Hello from Pod $(hostname) at $(date)"
restartPolicy: Never
6.8 StatefulSet (MongoDB)
apiVersion: v1
kind: Service
metadata:
name: mongo
spec:
clusterIP: None # Headless service
selector:
app: mongo
ports:
- port: 27017
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongo
spec:
selector:
matchLabels:
app: mongo
serviceName: "mongo"
replicas: 3
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: mongo:6
ports:
- containerPort: 27017
volumeMounts:
- name: data
mountPath: /data/db
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
7. Controller Reference Tables
| Controller | Type | Pod restart after completion | Scaling | Typical use case |
|---|---|---|---|---|
| Deployment | Stateless | Yes (Always) | Yes (replicas) | Web apps, APIs |
| StatefulSet | Stateful | Yes | Yes (ordered) | Databases, queues |
| DaemonSet | Per-node | Yes | Automatic (1/node) | Agents, plugins |
| Job | One-shot | No | completions + parallelism | Migrations, processing |
| CronJob | Scheduled | No | N/A | Backups, exports |
8. Essential kubectl Commands
Deployments
kubectl create deployment <name> --image=<image>
kubectl apply -f deployment.yaml
kubectl get deployments
kubectl describe deployment <name>
kubectl scale deployment <name> --replicas=<n>
kubectl rollout status deployment <name>
kubectl rollout history deployment <name>
kubectl rollout undo deployment <name>
kubectl rollout undo deployment <name> --to-revision=<n>
kubectl rollout pause deployment <name>
kubectl rollout resume deployment <name>
kubectl rollout restart deployment <name>
kubectl delete deployment <name>
DaemonSets
kubectl get daemonsets
kubectl get daemonsets --namespace kube-system
kubectl describe daemonset <name>
kubectl delete daemonset <name>
Jobs
kubectl get jobs
kubectl describe job <name>
kubectl get pods --selector=job-name=<name>
kubectl logs <pod-name>
kubectl delete job <name>
CronJobs
kubectl get cronjobs
kubectl describe cronjob <name>
kubectl patch cronjob <name> -p '{"spec": {"suspend": true}}'
kubectl delete cronjob <name>
Labels and Selectors
kubectl get pods --show-labels
kubectl label pod <pod-name> app=DEBUG --overwrite
kubectl label node <node-name> <key>=<value>
kubectl get pods -l app=hello-world
9. Best Practices
Deployments
- Always define an appropriate
strategy(RollingUpdateorRecreate) withmaxUnavailableandmaxSurgeadapted to infrastructure capacity - Always define
readinessProbesin the Pod template — without them, Kubernetes considers a Pod ready on startup - Never manage ReplicaSets directly — always use Deployments
- Manage deployments declaratively in YAML rather than imperatively — for reproducibility and version control
DaemonSets
- Use
OnDeletefor critical DaemonSets (likekube-proxy) to manually control update timing on each node - Use
nodeSelectorsornodeAffinityto limit DaemonSets to subsets of nodes with required characteristics
Jobs
- Define
backoffLimitexplicitly for critical Jobs to control retry count on failure - Define
activeDeadlineSecondsto prevent blocked Jobs from consuming resources indefinitely - Use
parallelismandcompletionsfor parallelizable Jobs to optimize cluster resource utilization
CronJobs
- Set
concurrencyPolicy: Forbidfor Jobs that must not overlap (e.g., backups) - Configure
successfulJobsHistoryLimitandfailedJobsHistoryLimitto prevent old Job accumulation
Search Terms
managing · kubernetes · controllers · deployments · containers · deployment · controller · cronjobs · daemonsets · jobs · reference · applications · daemonset · flow · job · readiness · replicaset · rollouts · statefulsets