Модуль 5 / 19
ReplicaSet і Deployment: rollout, rollback та доступність
Зміст
1. Цілі та результат модуля
Після модуля ви зможете пояснити ланцюжок Deployment → ReplicaSet → Pod, розрахувати межі RollingUpdate, відрізнити scale від нової revision, зупинити й продовжити rollout та відновити доступність після невдалого релізу.
- ReplicaSet підтримує кількість відповідних Pods
- Deployment керує ReplicaSets і декларативними rollout
- Нова revision виникає за зміни Pod template
- readiness визначає участь Pod в available capacity
- rollback повертає збережений Pod template, але не всі зовнішні залежності
2. Теорія: ReplicaSet і reconciliation
ReplicaSet порівнює spec.replicas із кількістю Pods, що відповідають selector, і створює або видаляє Pods. Він пов’язує створені Pods через ownerReferences. Зазвичай ReplicaSet не створюють вручну: Deployment додає керування revisions і стратегією оновлення.
Selector ReplicaSet не означає ексклюзивне володіння будь-яким відповідним Pod. Adoption можливий лише за дотримання умов ownership; selectors різних controllers, що перетинаються, створюють небезпечну поведінку.
3. Теорія: Deployment, template і revisions
Deployment зберігає selector і Pod template. Зміна spec.template створює новий ReplicaSet та збільшує deployment.kubernetes.io/revision. Scale змінює capacity наявної revision і сам по собі нову revision не створює.
pod-template-hash обчислюється controller і додається до ReplicaSet/Pods, щоб різні templates не перетиналися. Не задавайте й не змінюйте цей label вручну.
revisionHistoryLimit обмежує кількість старих ReplicaSets для rollback. Нульова історія економить об’єкти, але позбавляє вбудованого відкату. Історія не замінює Git і release metadata.
4. Теорія: RollingUpdate і доступність
RollingUpdate поступово масштабує новий ReplicaSet вгору, старий униз. maxSurge обмежує кількість Pods понад desired replicas, maxUnavailable — допустиму кількість недоступних відносно desired. Значення бувають цілими або відсотками; відсотки округлюються за правилами controller.
За replicas=3, maxSurge=1 і maxUnavailable=1 під час rollout допускається до 4 створених Pods і потрібно щонайменше 2 available. На одному Node це не HA: стратегія зберігає логічну capacity лише доки працює сам Node.
minReadySeconds вимагає, щоб Ready Pod залишався готовим заданий час до Available. progressDeadlineSeconds позначає відсутність прогресу умовою Progressing=False/ProgressDeadlineExceeded, але автоматично rollback не виконує.
5. Теорія: status, Conditions і спостереження rollout
replicas — загальна кількість Pods, updatedReplicas — Pods поточного template, readyReplicas — Ready зараз, availableReplicas — Ready не менше minReadySeconds, unavailableReplicas — відсутня available capacity. observedGeneration показує, чи обробив controller актуальний spec.
kubectl rollout status спостерігає controller status, а не виконує оновлення. Успішний rollout підтверджує стан workload, але не замінює HTTP smoke test, метрики та перевірку користувацького шляху.
6. Теорія: pause, resume і rollback
Pause дає змогу накопичити кілька змін Pod template без запуску проміжних revisions. Поки Deployment paused, controller не завершує rollout; після resume формується узгоджена revision.
Rollback відновлює template обраної збереженої revision. ConfigMap, Secret, schema бази, зовнішній API та mutable image tag могли вже змінитися, тому технічна можливість undo не гарантує сумісність даних і поведінки.
7. Методичні вказівки
- Зберігайте Deployment manifest у Git і фіксуйте immutable image digest для production
- Перед apply використовуйте server dry-run і diff
- Розраховуйте surge з урахуванням requests та вільної capacity
- Спостерігайте Deployment, обидва ReplicaSets, Pods і Events
- Не змінюйте ReplicaSet, яким володіє Deployment
- Не вважайте ProgressDeadlineExceeded автоматичним rollback
- Після rollout виконуйте smoke test і дивіться SLI
- Для rollback заздалегідь перевіряйте сумісність конфігурації та даних
8. Лабораторна робота: перший Deployment
Створіть Deployment із трьох replicas та явною стратегією. Readiness probe тут потрібна для правильного поняття Available; докладно probes розглядаються в модулі 11.
mkdir -p /tmp/k8s-m05
cat > /tmp/k8s-m05/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: k8s-m05
labels:
app.kubernetes.io/name: storefront
app.kubernetes.io/component: web
annotations:
kubernetes.io/change-cause: "initial nginx 1.29"
spec:
replicas: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 120
minReadySeconds: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app.kubernetes.io/name: storefront
app.kubernetes.io/component: web
template:
metadata:
labels:
app.kubernetes.io/name: storefront
app.kubernetes.io/component: web
spec:
containers:
- name: nginx
image: nginx:1.29-alpine
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
periodSeconds: 2
failureThreshold: 3
EOF
kubectl wait --for=condition=Ready node --all --timeout=120s
kubectl create namespace k8s-m05
kubectl apply --dry-run=server -f /tmp/k8s-m05/deployment.yaml
kubectl apply --server-side --field-manager=course-lab -f /tmp/k8s-m05/deployment.yaml
kubectl -n k8s-m05 rollout status deployment/web --timeout=120skubectl -n k8s-m05 get deployment,replicaset,pod -o wide
kubectl -n k8s-m05 get pods --show-labels
kubectl -n k8s-m05 describe deployment web
kubectl -n k8s-m05 rollout history deployment/web
kubectl -n k8s-m05 get deployment web -o jsonpath='generation={.metadata.generation}{"\n"}observedGeneration={.status.observedGeneration}{"\n"}replicas={.status.replicas}{"\n"}updated={.status.updatedReplicas}{"\n"}ready={.status.readyReplicas}{"\n"}available={.status.availableReplicas}{"\n"}'9. Лабораторна робота: revision і RollingUpdate
Змініть image у manifest, спочатку дослідіть diff, потім спостерігайте створення нового ReplicaSet. Старий ReplicaSet залишається з нулем replicas для можливого rollback.
sed -i 's/nginx:1.29-alpine/nginx:1.28-alpine/' /tmp/k8s-m05/deployment.yaml
sed -i 's/initial nginx 1.29/update to nginx 1.28/' /tmp/k8s-m05/deployment.yaml
kubectl diff -f /tmp/k8s-m05/deployment.yaml || [ "$?" -eq 1 ]
kubectl apply --server-side --field-manager=course-lab -f /tmp/k8s-m05/deployment.yaml
kubectl -n k8s-m05 rollout status deployment/web --timeout=120s
kubectl -n k8s-m05 get replicasets
kubectl -n k8s-m05 rollout history deployment/web10. Лабораторна робота: scale, pause і resume
Scale до п’яти Pods не змінює template і revision. Потім pause об’єднує зміну image та env в один rollout після resume.
revision_before=$(kubectl -n k8s-m05 get deployment web -o jsonpath='{.metadata.annotations.deployment\.kubernetes\.io/revision}')
kubectl -n k8s-m05 scale deployment/web --replicas=5
kubectl -n k8s-m05 rollout status deployment/web --timeout=120s
revision_after=$(kubectl -n k8s-m05 get deployment web -o jsonpath='{.metadata.annotations.deployment\.kubernetes\.io/revision}')
printf 'revision before=%s after=%s\n' "$revision_before" "$revision_after"
kubectl -n k8s-m05 get deployment,replicaset,podkubectl -n k8s-m05 rollout pause deployment/web
kubectl -n k8s-m05 set image deployment/web nginx=nginx:1.29-alpine
kubectl -n k8s-m05 set env deployment/web RELEASE_STAGE=verified
kubectl -n k8s-m05 rollout status deployment/web --timeout=5s || true
kubectl -n k8s-m05 get deployment web -o jsonpath='paused={.spec.paused}{"\n"}generation={.metadata.generation}{"\n"}observed={.status.observedGeneration}{"\n"}'
kubectl -n k8s-m05 rollout resume deployment/web
kubectl -n k8s-m05 rollout status deployment/web --timeout=120s
kubectl -n k8s-m05 rollout history deployment/web11. Діагностика: завислий rollout і rollback
Неіснуючий image створює новий ReplicaSet, але нові Pods не стають Ready. За maxUnavailable=1 старі available Pods зберігають сервісну capacity. Після deadline Deployment повідомляє про відсутність прогресу, але лишається зламаним до дії оператора.
kubectl -n k8s-m05 patch deployment web --type=merge -p '{"spec":{"progressDeadlineSeconds":30}}'
kubectl -n k8s-m05 annotate deployment web kubernetes.io/change-cause='intentional broken image' --overwrite
kubectl -n k8s-m05 set image deployment/web nginx=nginx:does-not-exist
kubectl -n k8s-m05 rollout status deployment/web --timeout=35s || true
kubectl -n k8s-m05 get deployment,replicaset,pod
kubectl -n k8s-m05 describe deployment web
kubectl -n k8s-m05 get pods -l app.kubernetes.io/component=web -o jsonpath='{range .items[*]}{.metadata.name}{" image="}{.spec.containers[0].image}{" ready="}{.status.containerStatuses[0].ready}{" waiting="}{.status.containerStatuses[0].state.waiting.reason}{"\n"}{end}'
kubectl -n k8s-m05 get events --sort-by=.metadata.creationTimestamp
kubectl -n k8s-m05 rollout history deployment/web
kubectl -n k8s-m05 annotate deployment web kubernetes.io/change-cause='rollback after broken image' --overwrite
kubectl -n k8s-m05 rollout undo deployment/web
kubectl -n k8s-m05 rollout status deployment/web --timeout=120s
kubectl -n k8s-m05 get deployment web -o jsonpath='image={.spec.template.spec.containers[0].image}{"\n"}ready={.status.readyReplicas}{"\n"}available={.status.availableReplicas}{"\n"}'Діагностичний порядок: Conditions і counts Deployment → нові/старі ReplicaSets → Pod states та Events → точний image/config → рішення roll forward або rollback → smoke test.
12. Контроль, критерії засвоєння та cleanup
- Що підтримує ReplicaSet?
- Яка зміна створює нову revision?
- Навіщо потрібен pod-template-hash?
- Скільки Pods дозволено за replicas=3 і maxSurge=1?
- Чим Ready відрізняється від Available?
- Чи створює scale нову revision?
- Що відбувається під час pause?
- Чи виконує progressDeadline автоматичний rollback?
- Чому undo не гарантує сумісність даних?
kubectl delete namespace k8s-m05 --wait=true
rm -rf /tmp/k8s-m05
kubectl get namespace k8s-m05 2>&1 || trueМодуль засвоєно, якщо ви прогнозуєте кількість Pods під час rollout, читаєте status без здогадок, доводите відсутність нової revision за scale та відновлюєте workload після невдалого image update.