Налаштування Rolling Update розгортання для веб-додатків
Rolling Update — постійна заміна екземплярів додатку: спочатку оновлюється 1–2 пода/контейнера, перевіряється їх здоров'я, потім наступні. На відміну від Blue-Green, не вимагає подвійних ресурсів, але коротко сосуществуют стара і нова версії.
Rolling Update в Kubernetes
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # дозволити до 2 додаткових подів при оновленні
maxUnavailable: 1 # максимум 1 під недоступний у будь-який момент
minReadySeconds: 30 # під вважається готовим через 30 сек після запуску
selector:
matchLabels: { app: myapp }
template:
metadata:
labels: { app: myapp }
spec:
containers:
- name: myapp
image: registry.example.com/myapp:v1.1.0
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
terminationGracePeriodSeconds: 60 # дати час завершити обробку запросів
# Обновити образ
kubectl set image deployment/myapp myapp=registry.example.com/myapp:v1.2.0
# Слідкувати за прогресом
kubectl rollout status deployment/myapp
# Історія
kubectl rollout history deployment/myapp
# Откат
kubectl rollout undo deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=3
Graceful Shutdown
// Node.js/Express — корректне завершення при SIGTERM
process.on('SIGTERM', async () => {
console.log('SIGTERM received, shutting down gracefully');
// Перестати приймати нові з'єднання
server.close(() => {
console.log('HTTP server closed');
});
// Дати час завершити поточні запросы
await new Promise(resolve => setTimeout(resolve, 30_000));
// Закрити з'єднання з БД
await db.destroy();
process.exit(0);
});
// Laravel/Octane — graceful stop
// Octane сам обробляє SIGTERM, дожидається завершення запросів
// В Dockerfile використовуйте:
STOPSIGNAL SIGTERM
Rolling Update у Docker Swarm
# docker-compose.yml
services:
web:
image: registry.example.com/myapp:latest
deploy:
replicas: 4
update_config:
parallelism: 1 # обновлять по 1 за раз
delay: 30s # 30 секунд між оновленнями
failure_action: rollback
monitor: 60s # мониторить 60 сек після оновлення пода
max_failure_ratio: 0.1
rollback_config:
parallelism: 2
delay: 0s
failure_action: pause
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# Обновити сервис
docker service update --image registry.example.com/myapp:v1.2.0 myapp_web
# Слідкувати
docker service ps myapp_web
# Откат
docker service rollback myapp_web
Health Check Endpoint
Для корректного rolling update потрібна health check, яка розрізняє liveness та readiness:
// Laravel — health check маршрути
Route::get('/health/live', function () {
// Просто перевірити, що процес живий
return response()->json(['status' => 'ok']);
});
Route::get('/health/ready', function () {
// Перевірити готовність приймати трафік
try {
DB::connection()->getPdo();
Cache::store()->get('health-check');
} catch (\Exception $e) {
return response()->json(['status' => 'not ready', 'error' => $e->getMessage()], 503);
}
return response()->json(['status' => 'ready']);
});
Проблема несумісних міграцій
При Rolling Update кратковременно працюють дві версії додатку. Схема БД повинна бути сумісна з обома:
Правило: міграції запускати до деплоя нового коду. Міграція повинна бути backward-compatible.
// НЕЛЬЗЯ: сразу переименовать колонку
// Схема зломає стару версію
// МОЖНО: трёхетапный деплой
// Deploy 1: додати new_column (nullable)
// Deploy 2: заповнити new_column, перейти на нього в коді
// Deploy 3: видалити old_column
Терміни реалізації
- Kubernetes Rolling Update з health checks: 2–3 дні
- Docker Swarm rolling update: 1–2 дні
- Стратегія backward-compatible міграцій: 1 день







