Workloads & Scheduling¶
Overview¶
This domain represents 15% of the CKA exam. It covers deploying applications, managing workload resources, configuring scheduling behavior, and using ConfigMaps and Secrets.
Workloads - Workloads overview
Deployments¶
Deployments are the primary way to manage stateless applications in Kubernetes. A Deployment manages a ReplicaSet, which in turn manages Pods.
Creating Deployments¶
# Imperative creation (fast for exam)
kubectl create deployment nginx --image=nginx:1.25 --replicas=3
# Generate YAML for customization
kubectl create deployment nginx --image=nginx:1.25 --replicas=3 \
--dry-run=client -o yaml > deployment.yaml
Deployment YAML Structure¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
Deployments - Complete Deployment documentation
Rolling Updates and Rollbacks¶
# Update the image (triggers rolling update)
kubectl set image deployment/nginx-deployment nginx=nginx:1.26
# Check rollout status
kubectl rollout status deployment/nginx-deployment
# View rollout history
kubectl rollout history deployment/nginx-deployment
# View details of a specific revision
kubectl rollout history deployment/nginx-deployment --revision=2
# Rollback to previous version
kubectl rollout undo deployment/nginx-deployment
# Rollback to a specific revision
kubectl rollout undo deployment/nginx-deployment --to-revision=1
# Pause a rollout (for making multiple changes)
kubectl rollout pause deployment/nginx-deployment
# Resume a paused rollout
kubectl rollout resume deployment/nginx-deployment
Update Strategies: - RollingUpdate (default) - gradually replaces old pods with new ones - maxUnavailable - max pods that can be unavailable during update (default 25%) - maxSurge - max pods that can be created above desired count (default 25%) - Recreate - terminates all existing pods before creating new ones (causes downtime)
Performing a Rolling Update - Update tutorial
Scaling¶
# Scale a deployment
kubectl scale deployment/nginx-deployment --replicas=5
# Autoscale based on CPU (requires metrics-server)
kubectl autoscale deployment/nginx-deployment --min=3 --max=10 --cpu-percent=80
ReplicaSets¶
ReplicaSets ensure a specified number of pod replicas are running at any given time. Deployments manage ReplicaSets - you rarely create them directly.
Key Facts: - selector.matchLabels must match template.metadata.labels - Scaling a ReplicaSet directly is overridden by the owning Deployment - Old ReplicaSets are retained for rollback (controlled by revisionHistoryLimit)
ReplicaSets - ReplicaSet documentation
StatefulSets¶
StatefulSets manage stateful applications that require stable identities and persistent storage.
Key Characteristics: - Pods get stable, unique hostnames: <name>-0, <name>-1, <name>-2 - Ordered deployment and scaling (pods created in order 0, 1, 2...) - Ordered, graceful deletion (pods deleted in reverse order) - Stable persistent storage via volumeClaimTemplates - Require a headless Service for network identity
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
Use Cases: - Databases (MySQL, PostgreSQL, MongoDB) - Distributed systems (ZooKeeper, Kafka, Elasticsearch) - Applications requiring stable network identity
StatefulSets - StatefulSet documentation StatefulSet Tutorial - Hands-on tutorial
DaemonSets¶
DaemonSets ensure that a copy of a Pod runs on all (or selected) nodes in the cluster.
Key Facts: - One pod per node (automatically scheduled) - New pods are created when new nodes join the cluster - Pods are removed when nodes are removed - Use nodeSelector or affinity to target specific nodes
Common Use Cases: - Log collectors (Fluentd, Filebeat) - Monitoring agents (Prometheus Node Exporter, Datadog agent) - Network plugins (Calico, Cilium, Weave Net) - Storage daemons (Ceph, GlusterFS)
# No imperative command for DaemonSets - use YAML
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: fluentd
image: fluentd:v1.16
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
DaemonSets - DaemonSet documentation
Jobs and CronJobs¶
Jobs¶
Jobs create one or more Pods and ensure that a specified number of them successfully terminate.
# Create a job imperatively
kubectl create job my-job --image=busybox -- /bin/sh -c "echo hello; sleep 30; echo done"
apiVersion: batch/v1
kind: Job
metadata:
name: backup-job
spec:
completions: 3 # Number of successful completions needed
parallelism: 2 # Number of pods running in parallel
backoffLimit: 4 # Number of retries before marking as failed
activeDeadlineSeconds: 300 # Timeout for the entire job
template:
spec:
restartPolicy: Never # Must be Never or OnFailure
containers:
- name: backup
image: busybox
command: ["sh", "-c", "echo backing up data"]
Jobs - Job documentation
CronJobs¶
CronJobs create Jobs on a schedule using cron syntax.
# Create a cronjob imperatively
kubectl create cronjob backup --image=busybox --schedule="0 2 * * *" \
-- /bin/sh -c "echo running backup"
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *" # At 2:00 AM daily
concurrencyPolicy: Forbid # Don't run if previous is still running
successfulJobsHistoryLimit: 3 # Keep last 3 successful jobs
failedJobsHistoryLimit: 1 # Keep last 1 failed job
startingDeadlineSeconds: 200 # Deadline to start if missed schedule
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: busybox
command: ["sh", "-c", "echo backup completed"]
Cron Schedule Format: minute hour day-of-month month day-of-week - */5 * * * * - every 5 minutes - 0 2 * * * - daily at 2:00 AM - 0 0 * * 0 - weekly on Sunday at midnight - 0 0 1 * * - monthly on the 1st at midnight
CronJobs - CronJob documentation
Resource Requests and Limits¶
Requests vs Limits¶
- Requests - the minimum amount of resources guaranteed to the container
- Used by the scheduler to decide which node to place the pod on
- A pod will not be scheduled if no node has enough available resources
- Limits - the maximum amount of resources the container can use
- CPU: container is throttled when it exceeds the limit
- Memory: container is OOM-killed when it exceeds the limit
spec:
containers:
- name: app
image: myapp:1.0
resources:
requests:
cpu: 250m # 0.25 CPU cores
memory: 64Mi # 64 mebibytes
limits:
cpu: 500m # 0.5 CPU cores
memory: 128Mi # 128 mebibytes
CPU Units: 1 = 1 vCPU/core, 100m = 0.1 CPU (millicores) Memory Units: Ki, Mi, Gi (binary), K, M, G (decimal)
Resource Management - Resource configuration
LimitRange¶
Sets default requests/limits and min/max constraints for containers in a namespace.
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: dev
spec:
limits:
- default:
cpu: 500m
memory: 256Mi
defaultRequest:
cpu: 100m
memory: 64Mi
max:
cpu: "2"
memory: 1Gi
min:
cpu: 50m
memory: 32Mi
type: Container
LimitRange - LimitRange documentation
ResourceQuota¶
Limits the total resource consumption in a namespace.
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "4"
requests.memory: 4Gi
limits.cpu: "8"
limits.memory: 8Gi
pods: "20"
persistentvolumeclaims: "10"
ResourceQuota - ResourceQuota documentation
Scheduling¶
Node Selectors¶
The simplest way to constrain pod scheduling to specific nodes.
spec:
nodeSelector:
disktype: ssd
region: us-east
# Label a node
kubectl label nodes worker-1 disktype=ssd
Node Affinity¶
More expressive node selection rules than nodeSelector.
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- nvme
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1a
Operators: In, NotIn, Exists, DoesNotExist, Gt, Lt
Assigning Pods to Nodes - Scheduling reference
Pod Affinity and Anti-Affinity¶
Schedule pods relative to other pods.
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
Taints and Tolerations¶
Taints are applied to nodes to repel pods. Tolerations are applied to pods to allow scheduling on tainted nodes.
# Apply a taint to a node
kubectl taint nodes worker-1 key=value:NoSchedule
# Remove a taint
kubectl taint nodes worker-1 key=value:NoSchedule-
Taint Effects: - NoSchedule - pods without matching toleration will not be scheduled - PreferNoSchedule - scheduler tries to avoid, but not guaranteed - NoExecute - existing pods without matching toleration are evicted
# Pod toleration
spec:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
- key: "special"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 3600 # Evict after 1 hour if taint is added
Taints and Tolerations - Reference documentation
Static Pods¶
Pods managed directly by the kubelet on a specific node (not through the API server).
Key Facts: - Defined as YAML files in /etc/kubernetes/manifests/ (default path) - kubelet watches this directory and manages the pods - Control plane components (API server, etcd, scheduler, controller manager) are static pods - Mirror pods appear in the API server but cannot be controlled from there - Useful for running essential node-level services
Static Pods - Static pod documentation
ConfigMaps and Secrets¶
ConfigMaps¶
Store non-confidential configuration data as key-value pairs.
# Create from literal values
kubectl create configmap app-config \
--from-literal=DB_HOST=mysql \
--from-literal=DB_PORT=3306
# Create from a file
kubectl create configmap app-config --from-file=config.properties
# Create from an env file
kubectl create configmap app-config --from-env-file=app.env
Using ConfigMaps in Pods:
# As environment variables
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
# As a volume mount
spec:
containers:
- name: app
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
ConfigMaps - ConfigMap documentation
Secrets¶
Store sensitive data with base64 encoding.
# Create from literal values
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=s3cret
# Create TLS secret
kubectl create secret tls tls-secret \
--cert=tls.crt \
--key=tls.key
# Create docker registry secret
kubectl create secret docker-registry regcred \
--docker-server=https://index.docker.io/v1/ \
--docker-username=user \
--docker-password=pass
Using Secrets in Pods:
# As environment variables
spec:
containers:
- name: app
envFrom:
- secretRef:
name: db-secret
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# As a volume mount
spec:
containers:
- name: app
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret
Secrets - Secret documentation
Key Exam Tips for This Domain¶
- Use imperative commands to create Deployments, Jobs, and CronJobs quickly
- Know rolling update parameters -
maxUnavailableandmaxSurge - Practice rollback commands -
kubectl rollout undo - Understand the difference between nodeSelector, nodeAffinity, and taints/tolerations
- Remember ConfigMap/Secret consumption methods - env vars vs volume mounts
- Know Job restartPolicy must be
NeverorOnFailure(notAlways) - Practice CronJob schedule syntax - the five-field cron format