Модуль 11 / 19
StatefulSet, DaemonSet, Job і CronJob
Зміст
1. Цілі модуля
Ви навчитеся обирати Deployment, StatefulSet, DaemonSet, Job або CronJob, пояснювати їхні гарантії та діагностувати невдалу batch-задачу.
2. Теорія: вибір контролера
Deployment керує взаємозамінними stateless Pods. StatefulSet дає стабільні ordinal names, порядок і зв’язок identity зі storage. DaemonSet запускає node-local Pod на кожному відповідному Node.
Job виконує скінченну задачу до потрібної кількості успішних completions. CronJob за розкладом створює Jobs, а не Pods напряму.
3. Теорія: StatefulSet і DaemonSet
StatefulSet потребує headless Service для network identity. Stable identity не робить застосунок stateful автоматично: потрібні PVC, replication та backup.
DaemonSet застосовують для node agents, CNI/CSI, logs і monitoring. Кількість Pods визначають відповідні Nodes, а не replicas.
4. Теорія: Job і CronJob
Job керує retries через backoffLimit, parallelism та completions; Indexed mode дає кожній роботі індекс. ttlSecondsAfterFinished очищає завершені Jobs.
CronJob підтримує timeZone, concurrencyPolicy та startingDeadlineSeconds. Запуск приблизний, тому задача має бути idempotent. TZ/CRON_TZ не можна записувати в schedule.
5. Методичні вказівки
- Обирайте controller за identity та completion semantics
- Не запускайте довготривалий server через Job
- Робіть batch operations idempotent
- Обмежуйте history і TTL Jobs
- Перевіряйте headless Service та PVC
- Задавайте timeZone і concurrencyPolicy явно
6. Лабораторна робота: workload controllers
Збережіть об’єкти як controllers-lab.yaml.
apiVersion: v1
kind: Namespace
metadata: {name: lab-controllers}
---
apiVersion: v1
kind: Service
metadata: {name: database, namespace: lab-controllers}
spec:
clusterIP: None
selector: {app: database}
ports: [{name: peer, port: 8080}]
---
apiVersion: apps/v1
kind: StatefulSet
metadata: {name: database, namespace: lab-controllers}
spec:
serviceName: database
replicas: 2
selector:
matchLabels: {app: database}
template:
metadata:
labels: {app: database}
spec:
containers:
- {name: app, image: "busybox:1.37.0", command: ["sh", "-c", "echo $HOSTNAME; sleep 3600"]}
---
apiVersion: apps/v1
kind: DaemonSet
metadata: {name: node-agent, namespace: lab-controllers}
spec:
selector:
matchLabels: {app: node-agent}
template:
metadata:
labels: {app: node-agent}
spec:
containers:
- {name: agent, image: "busybox:1.37.0", command: ["sh", "-c", "sleep 3600"]}
---
apiVersion: batch/v1
kind: Job
metadata: {name: indexed, namespace: lab-controllers}
spec:
completions: 3
parallelism: 2
completionMode: Indexed
ttlSecondsAfterFinished: 600
template:
spec:
restartPolicy: Never
containers:
- {name: task, image: "busybox:1.37.0", command: ["sh", "-c", "echo index=$JOB_COMPLETION_INDEX"]}
---
apiVersion: batch/v1
kind: CronJob
metadata: {name: report, namespace: lab-controllers}
spec:
schedule: "*/5 * * * *"
timeZone: Etc/UTC
concurrencyPolicy: Forbid
startingDeadlineSeconds: 120
successfulJobsHistoryLimit: 2
failedJobsHistoryLimit: 1
suspend: true
jobTemplate:
spec:
ttlSecondsAfterFinished: 600
template:
spec:
restartPolicy: Never
containers:
- {name: report, image: "busybox:1.37.0", command: ["date", "-u"]}kubectl apply -f controllers-lab.yaml
kubectl rollout status statefulset/database -n lab-controllers --timeout=120s
kubectl rollout status daemonset/node-agent -n lab-controllers --timeout=120s
kubectl wait job/indexed -n lab-controllers --for=condition=Complete --timeout=120s
kubectl get statefulset,daemonset,job,cronjob,pod -n lab-controllers -o wide
kubectl get pods -n lab-controllers -l app=database
kubectl logs -n lab-controllers -l job-name=indexed --prefix
kubectl create job report-now -n lab-controllers --from=cronjob/report
kubectl wait job/report-now -n lab-controllers --for=condition=Complete --timeout=120s
kubectl logs job/report-now -n lab-controllersКритерій: StatefulSet створює database-0/1, DaemonSet Ready на відповідних Nodes, Indexed Job завершує три індекси, ручний Job з CronJob успішний.
7. Діагностика: failed Job
Збережіть failing-job.yaml. Контейнер навмисно завершується з exitCode 42; wait Complete очікувано отримує timeout.
apiVersion: batch/v1
kind: Job
metadata: {name: failing, namespace: lab-controllers}
spec:
backoffLimit: 2
activeDeadlineSeconds: 60
template:
spec:
restartPolicy: Never
containers:
- {name: task, image: "busybox:1.37.0", command: ["sh", "-c", "echo deliberate failure >&2; exit 42"]}kubectl apply -f failing-job.yaml
kubectl wait job/failing -n lab-controllers --for=condition=Complete --timeout=45s
kubectl get job,pod -n lab-controllers
kubectl get job failing -n lab-controllers -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" reason="}{.reason}{"\n"}{end}'
kubectl logs -n lab-controllers -l job-name=failing --prefix
kubectl describe job failing -n lab-controllers
kubectl events -n lab-controllers --for job/failing
kubectl delete namespace lab-controllersЛанцюжок: Job Conditions → counters → Pods та exitCode → logs → Events → backoffLimit/deadline. Не збільшуйте retries, доки причина детермінована.
8. Контроль і шпаргалка
- Коли StatefulSet кращий за Deployment?
- Чому DaemonSet не має replicas?
- Що означає Indexed completion?
- Навіщо batch-задачі idempotency?
- Чим suspend CronJob відрізняється від видалення?
Модуль засвоєно, якщо ви обґрунтовуєте controller і доводите причину failed Job за status, exitCode та logs.
PDF для роботи офлайн
Завантажте оформлену версію модуля для читання без підключення до мережі.