Перейти до вмісту

Модуль 2.4: Стратегії деплойменту

Hands-On Lab Available
K8s Cluster advanced 40 min
Launch Lab ↗

Opens in Killercoda in a new tab

Складність: [MEDIUM] — концептуальне розуміння з практичною реалізацією

Час на виконання: 40–50 хвилин

Передумови: Модуль 2.1 (Деплойменти), розуміння Сервісів


Що ви зможете робити

Розділ «Що ви зможете робити»

Після завершення цього модуля ви зможете:

  • Реалізувати blue/green та canary деплойменти, використовуючи нативні ресурси Kubernetes
  • Порівняти стратегії ковзного оновлення, blue/green та canary з їх компромісами
  • Спроєктувати стратегію деплойменту, що відповідає вимогам доступності та відкату
  • Оцінити стан деплойменту під час розгортання та вирішити, коли продовжувати або відкочувати

Чому цей модуль важливий

Розділ «Чому цей модуль важливий»

Те, як ви розгортаєте нові версії, має значення. Погана стратегія деплойменту може спричинити простій, пошкодження даних або помилки, видимі користувачам. CKAD очікує, що ви розумієте різні стратегії деплойменту та коли використовувати кожну.

Ви зіткнетесь із такими питаннями:

  • Реалізувати blue/green-деплоймент
  • Налаштувати canary-реліз
  • Налаштувати параметри ковзного оновлення
  • Обрати відповідну стратегію для сценарію

Аналогія з рестораном

Ковзні оновлення — це як поступова заміна страв у меню — клієнти, що замовляють у різний час, можуть отримати дещо різне меню. Blue/green — це як мати дві повноцінні кухні — ви переводите всіх клієнтів на нову кухню одночасно. Canary-релізи — це як дати нову страву спочатку 10% клієнтів — якщо їм сподобається, її отримають усі.


СтратегіяПростійВідкатВартість ресурсівРизик
Rolling UpdateНемаєПовільний (поступовий)НизькаСередній
RecreateТакШвидкий (перерозгортання старого)НизькаВисокий
Blue/GreenНемаєМиттєвий2x ресурсівНизький
CanaryНемаєМиттєвийНизька–середняДуже низький

Коли використовувати кожну

Розділ «Коли використовувати кожну»
СтратегіяНайкраще для
Rolling UpdateБільшість застосунків, вибір за замовчуванням
RecreateЗастосунки, що не можуть працювати з кількома версіями
Blue/GreenКритичні застосунки, що потребують миттєвого відкату
CanaryОбережні деплойменти, тестування з реальним трафіком

Rolling Update (за замовчуванням)

Розділ «Rolling Update (за замовчуванням)»

Kubernetes поступово замінює старі поди новими.

apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Може перевищити кількість реплік на 1
maxUnavailable: 1 # Максимум 1 недоступний
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.20

Поведінка оновлення

Розділ «Поведінка оновлення»
З replicas=4, maxSurge=1, maxUnavailable=1:
Старт: [v1] [v1] [v1] [v1] (4 працюють)
Крок 1: [v1] [v1] [v1] [--] [v2] (3 старих, 1 новий стартує)
Крок 2: [v1] [v1] [--] [v2] [v2] (2 старих, 2 нових)
Крок 3: [v1] [--] [v2] [v2] [v2] (1 старий, 3 нових)
Крок 4: [v2] [v2] [v2] [v2] (4 нових, завершено)

Запуск ковзного оновлення

Розділ «Запуск ковзного оновлення»
Terminal window
# Оновити образ
k set image deploy/web-app nginx=nginx:1.21
# Спостерігати за розгортанням
k rollout status deploy/web-app
# Перевірити перехід подів
k get pods -l app=web -w

Усі наявні поди знищуються перед створенням нових.

apiVersion: apps/v1
kind: Deployment
metadata:
name: database-app
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
containers:
- name: postgres
image: postgres:13

Поведінка оновлення

Розділ «Поведінка оновлення»
Старт: [v1] [v1] [v1]
Крок 1: [--] [--] [--] (усі старі поди завершені)
Крок 2: [v2] [v2] [v2] (усі нові поди створені)

Коли використовувати

Розділ «Коли використовувати»
  • Застосунки баз даних з вимогою єдиного запису
  • Застосунки з блокуванням файлової системи
  • Застосунки, що не можуть працювати з кількома версіями, які мають доступ до спільного стану
  • Stateful-застосунки без належної підтримки міграції

Запуск двох ідентичних середовищ. Миттєве перемикання трафіку через оновлення селектора Сервісу.

Крок 1: Розгортання Blue (поточний)

blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: app
image: myapp:1.0

Крок 2: Створення Сервісу (вказує на Blue)

service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # Вказує на blue
ports:
- port: 80

Крок 3: Розгортання Green (нова версія)

green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: app
image: myapp:2.0

Крок 4: Перемикання трафіку

Terminal window
# Перемикнути сервіс на green
k patch svc myapp -p '{"spec":{"selector":{"version":"green"}}}'
# Миттєвий відкат, якщо потрібно
k patch svc myapp -p '{"spec":{"selector":{"version":"blue"}}}'

Повний скрипт Blue/Green

Розділ «Повний скрипт Blue/Green»
Terminal window
# Розгорнути blue
k apply -f blue-deployment.yaml
# Створити сервіс, що вказує на blue
k apply -f service.yaml
# Протестувати blue
k run test --image=busybox --rm -it --restart=Never -- wget -qO- http://myapp
# Розгорнути green (без трафіку)
k apply -f green-deployment.yaml
# Протестувати green напряму (port-forward або окремий сервіс)
k port-forward deploy/app-green 8080:80 &
curl localhost:8080
# Перемикнути трафік на green
k patch svc myapp -p '{"spec":{"selector":{"version":"green"}}}'
# Якщо проблеми — миттєвий відкат
k patch svc myapp -p '{"spec":{"selector":{"version":"blue"}}}'
# Після підтвердження — видалити blue
k delete deploy app-blue

Направлення невеликого відсотка трафіку на нову версію. Поступове збільшення у разі успіху.

Реалізація з кількома Деплойментами

Розділ «Реалізація з кількома Деплойментами»

Стабільний Деплоймент (90% трафіку)

apiVersion: apps/v1
kind: Deployment
metadata:
name: app-stable
spec:
replicas: 9 # 90% трафіку
selector:
matchLabels:
app: myapp
track: stable
template:
metadata:
labels:
app: myapp
track: stable
spec:
containers:
- name: app
image: myapp:1.0

Canary-деплоймент (10% трафіку)

apiVersion: apps/v1
kind: Deployment
metadata:
name: app-canary
spec:
replicas: 1 # 10% трафіку
selector:
matchLabels:
app: myapp
track: canary
template:
metadata:
labels:
app: myapp
track: canary
spec:
containers:
- name: app
image: myapp:2.0

Сервіс (маршрутизує до обох)

apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp # Збігається і зі stable, і з canary
ports:
- port: 80

З 9 стабільними подами та 1 canary-подом:

  • ~90% трафіку → stable (v1.0)
  • ~10% трафіку → canary (v2.0)

Поступове canary-розгортання

Розділ «Поступове canary-розгортання»
Terminal window
# Старт: 9 стабільних, 1 canary (10%)
k scale deploy app-canary --replicas=1
k scale deploy app-stable --replicas=9
# Збільшити canary до 25%
k scale deploy app-canary --replicas=3
k scale deploy app-stable --replicas=9
# Збільшити canary до 50%
k scale deploy app-canary --replicas=5
k scale deploy app-stable --replicas=5
# Повне розгортання (100% нова версія)
k scale deploy app-canary --replicas=10
k scale deploy app-stable --replicas=0
# Очищення: перейменувати canary на stable
k delete deploy app-stable
k patch deploy app-canary -p '{"metadata":{"name":"app-stable"}}'

Параметри Rolling Update — глибоке занурення

Розділ «Параметри Rolling Update — глибоке занурення»

Максимальна кількість подів, що можуть бути створені понад бажану кількість:

rollingUpdate:
maxSurge: 25% # 25% додаткових подів (за замовчуванням)
# або
maxSurge: 2 # 2 додаткових поди

Максимум подів, що можуть бути недоступні під час оновлення:

rollingUpdate:
maxUnavailable: 25% # 25% можуть бути вимкнені (за замовчуванням)
# або
maxUnavailable: 0 # Нульовий час простою

Типові конфігурації

Розділ «Типові конфігурації»
# Нульовий час простою (консервативний)
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# Швидке оновлення (агресивний)
rollingUpdate:
maxSurge: 100%
maxUnavailable: 50%
# Збалансований (за замовчуванням)
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%

Правильні проби забезпечують гладке розгортання.

Проба готовності для Деплойментів

Розділ «Проба готовності для Деплойментів»
spec:
template:
spec:
containers:
- name: app
image: myapp
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5

Без проб готовності Kubernetes вважає поди готовими одразу — трафік може потрапити до подів, які ще не повністю ініціалізовані.

spec:
minReadySeconds: 10 # Под має бути готовим 10 с, перш ніж буде вважатися доступним

Це додає буфер для виявлення ранніх збоїв.


Практичні сценарії для іспиту

Розділ «Практичні сценарії для іспиту»

Сценарій 1: Ковзне оновлення з нульовим простоєм

Розділ «Сценарій 1: Ковзне оновлення з нульовим простоєм»
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0 # Ключове: ніколи не зменшувати нижче бажаного
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: nginx
image: nginx:1.20
readinessProbe: # Важливо для нульового простою
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 3

Сценарій 2: Швидке перемикання Blue/Green

Розділ «Сценарій 2: Швидке перемикання Blue/Green»
Terminal window
# Створити blue-деплоймент
k create deploy app-blue --image=nginx:1.20 --replicas=3
k label deploy app-blue version=blue
# Додати мітку версії до шаблону подів
k patch deploy app-blue -p '{"spec":{"template":{"metadata":{"labels":{"version":"blue"}}}}}'
# Створити сервіс
k expose deploy app-blue --name=myapp --port=80 --selector=version=blue
# Розгорнути green
k create deploy app-green --image=nginx:1.21 --replicas=3
k patch deploy app-green -p '{"spec":{"template":{"metadata":{"labels":{"version":"green"}}}}}'
# Перемикнути на green
k patch svc myapp -p '{"spec":{"selector":{"version":"green"}}}'

  • Ковзні оновлення Kubernetes є самовідновлювальними. Якщо новий под не проходить пробу готовності, розгортання автоматично призупиняється, запобігаючи повному розгортанню поганої версії.

  • Blue/green-деплойменти потребують 2x ресурсів під час перемикання. Це їхній головний недолік, але дозволяє миттєвий відкат.

  • Canary-деплойменти виникли в Google. Термін походить від «канарки у вугільній шахті» — шахтарі використовували канарок для виявлення токсичних газів. Якщо канарка гинула, шахтарі знали, що треба евакуюватися.


ПомилкаЧому це шкодитьРішення
Немає проби готовностіТрафік на неготові подиЗавжди додавайте проби готовності
maxUnavailable: 100%Усі поди знищуються одночасноТримайте на 25% або менше
Неправильний селектор сервісу для blue/greenТрафік не перемикаєтьсяПеревіряйте збіг міток
Не тестували canary окремоПроблеми canary не виявленіСпочатку протестуйте canary-поди напряму
Забули зменшити старий деплойментМарнування ресурсівЗменшуйте після успішного перемикання

  1. Яка стратегія деплойменту знищує всі старі поди перед створенням нових?

    Відповідь `Recreate`. Усі наявні поди завершуються перед створенням нових подів, що спричиняє простій.
  2. Як миттєво перемикнути трафік у blue/green?

    Відповідь Запатчити селектор Сервісу, щоб вказати на мітки нового деплойменту: `kubectl patch svc myapp -p '{"spec":{"selector":{"version":"green"}}}'`
  3. З 10 репліками та maxSurge=2, maxUnavailable=1 — скільки подів може існувати під час оновлення?

    Відповідь Максимум 12 подів (10 + maxSurge 2). Мінімум 9 доступних подів (10 - maxUnavailable 1).
  4. Як досягти 10% canary-трафіку за допомогою кількості подів?

    Відповідь Запустити 9 стабільних подів та 1 canary-под, із Сервісом, що вибирає обох. Трафік розподіляється приблизно пропорційно кількості подів: ~90% stable, ~10% canary.

Завдання: Реалізувати всі три стратегії деплойменту.

Частина 1: Rolling Update з параметрами

Terminal window
# Створити деплоймент з кастомним ковзним оновленням
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: rolling-demo
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: rolling
template:
metadata:
labels:
app: rolling
spec:
containers:
- name: nginx
image: nginx:1.20
EOF
# Оновити та спостерігати (має бути макс. 5 подів)
k set image deploy/rolling-demo nginx=nginx:1.21
k get pods -l app=rolling -w
# Очищення
k delete deploy rolling-demo

Частина 2: Blue/Green-деплоймент

Terminal window
# Blue-деплоймент
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: blue
spec:
replicas: 3
selector:
matchLabels:
app: demo
version: blue
template:
metadata:
labels:
app: demo
version: blue
spec:
containers:
- name: nginx
image: nginx:1.20
EOF
# Сервіс, що вказує на blue
cat << 'EOF' | k apply -f -
apiVersion: v1
kind: Service
metadata:
name: demo-svc
spec:
selector:
app: demo
version: blue
ports:
- port: 80
EOF
# Green-деплоймент
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: green
spec:
replicas: 3
selector:
matchLabels:
app: demo
version: green
template:
metadata:
labels:
app: demo
version: green
spec:
containers:
- name: nginx
image: nginx:1.21
EOF
# Перемикнути на green
k patch svc demo-svc -p '{"spec":{"selector":{"version":"green"}}}'
# Відкат на blue
k patch svc demo-svc -p '{"spec":{"selector":{"version":"blue"}}}'
# Очищення
k delete deploy blue green
k delete svc demo-svc

Частина 3: Canary-деплоймент

Terminal window
# Стабільний деплоймент (9 реплік)
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: stable
spec:
replicas: 9
selector:
matchLabels:
app: canary-demo
track: stable
template:
metadata:
labels:
app: canary-demo
track: stable
spec:
containers:
- name: nginx
image: nginx:1.20
EOF
# Canary-деплоймент (1 репліка = ~10%)
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary
spec:
replicas: 1
selector:
matchLabels:
app: canary-demo
track: canary
template:
metadata:
labels:
app: canary-demo
track: canary
spec:
containers:
- name: nginx
image: nginx:1.21
EOF
# Сервіс маршрутизує до обох
cat << 'EOF' | k apply -f -
apiVersion: v1
kind: Service
metadata:
name: canary-svc
spec:
selector:
app: canary-demo
ports:
- port: 80
EOF
# Поступове збільшення canary
k scale deploy canary --replicas=3 # ~25%
k scale deploy stable --replicas=7
# Повне розгортання
k scale deploy canary --replicas=10
k scale deploy stable --replicas=0
# Очищення
k delete deploy stable canary
k delete svc canary-svc

Вправа 1: Конфігурація Rolling Update (Ціль: 3 хвилини)

Розділ «Вправа 1: Конфігурація Rolling Update (Ціль: 3 хвилини)»
Terminal window
# Створити зі специфічними налаштуваннями ковзного оновлення
k create deploy drill1 --image=nginx:1.20 --replicas=4
# Запатчити стратегію
k patch deploy drill1 -p '{"spec":{"strategy":{"type":"RollingUpdate","rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
# Оновити та спостерігати
k set image deploy/drill1 nginx=nginx:1.21
k rollout status deploy/drill1
# Очищення
k delete deploy drill1

Вправа 2: Стратегія Recreate (Ціль: 2 хвилини)

Розділ «Вправа 2: Стратегія Recreate (Ціль: 2 хвилини)»
Terminal window
# Створити зі стратегією recreate
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: drill2
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app: drill2
template:
metadata:
labels:
app: drill2
spec:
containers:
- name: nginx
image: nginx:1.20
EOF
# Оновити (спостерігати, як усі поди спочатку завершуються)
k set image deploy/drill2 nginx=nginx:1.21
k get pods -l app=drill2 -w
# Очищення
k delete deploy drill2

Вправа 3: Перемикання Blue/Green (Ціль: 4 хвилини)

Розділ «Вправа 3: Перемикання Blue/Green (Ціль: 4 хвилини)»
Terminal window
# Створити blue
k create deploy blue --image=nginx:1.20 --replicas=2
k patch deploy blue -p '{"spec":{"selector":{"matchLabels":{"version":"blue"}},"template":{"metadata":{"labels":{"version":"blue"}}}}}'
# Сервіс
k expose deploy blue --name=app --port=80 --selector=version=blue
# Створити green
k create deploy green --image=nginx:1.21 --replicas=2
k patch deploy green -p '{"spec":{"selector":{"matchLabels":{"version":"green"}},"template":{"metadata":{"labels":{"version":"green"}}}}}'
# Перемикнути
k patch svc app -p '{"spec":{"selector":{"version":"green"}}}'
# Перевірити
k get ep app
# Очищення
k delete deploy blue green
k delete svc app

Вправа 4: Відсоток Canary (Ціль: 3 хвилини)

Розділ «Вправа 4: Відсоток Canary (Ціль: 3 хвилини)»
Terminal window
# 10% canary
k create deploy stable --image=nginx:1.20 --replicas=9
k create deploy canary --image=nginx:1.21 --replicas=1
# Додати спільну мітку
k patch deploy stable -p '{"spec":{"template":{"metadata":{"labels":{"app":"myapp"}}}}}'
k patch deploy canary -p '{"spec":{"template":{"metadata":{"labels":{"app":"myapp"}}}}}'
# Сервіс для обох
k expose deploy stable --name=myapp --port=80 --selector=app=myapp
# Перевірити, що endpoints включають обох
k get ep myapp
# Очищення
k delete deploy stable canary
k delete svc myapp

Вправа 5: Перевірка нульового простою (Ціль: 3 хвилини)

Розділ «Вправа 5: Перевірка нульового простою (Ціль: 3 хвилини)»
Terminal window
# Створити деплоймент з пробою готовності
cat << 'EOF' | k apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: drill5
spec:
replicas: 3
strategy:
rollingUpdate:
maxUnavailable: 0
selector:
matchLabels:
app: drill5
template:
metadata:
labels:
app: drill5
spec:
containers:
- name: nginx
image: nginx:1.20
readinessProbe:
httpGet:
path: /
port: 80
EOF
# Сервіс
k expose deploy drill5 --port=80
# Оновити (нульовий простій)
k set image deploy/drill5 nginx=nginx:1.21
k rollout status deploy/drill5
# Очищення
k delete deploy drill5
k delete svc drill5

Вправа 6: Повний сценарій стратегії деплойменту (Ціль: 6 хвилин)

Розділ «Вправа 6: Повний сценарій стратегії деплойменту (Ціль: 6 хвилин)»

Сценарій: Production-деплоймент з canary-тестуванням.

Terminal window
# 1. Розгорнути стабільну версію
k create deploy prod --image=nginx:1.20 --replicas=5
# 2. Створити сервіс
k expose deploy prod --name=production --port=80
# 3. Створити canary (10%)
k create deploy canary --image=nginx:1.21 --replicas=1
# 4. Спрямувати сервіс на обох
k patch deploy prod -p '{"spec":{"template":{"metadata":{"labels":{"release":"production"}}}}}'
k patch deploy canary -p '{"spec":{"template":{"metadata":{"labels":{"release":"production"}}}}}'
k patch svc production -p '{"spec":{"selector":{"release":"production"}}}'
# 5. Протестувати canary
k logs -l app=canary
# 6. Поступове розгортання
k scale deploy canary --replicas=3
k scale deploy prod --replicas=3
# 7. Повне розгортання
k scale deploy canary --replicas=5
k scale deploy prod --replicas=0
# 8. Очищення
k delete deploy prod canary
k delete svc production

Кумулятивний тест Частини 2 — перевірте свої знання з розгортання застосунків.