Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Стратегии деплоя приложений
За годы я работал с разными deployment стратегиями. Каждая имеет свои плюсы и минусы.
1. Blue-Green Deploy
Два идентичных production окружения. Трафик переключается мгновенно.
Реализация с Docker:
docker build -t myapp:v2.0 .
docker run -d --name green -p 8081:8000 myapp:v2.0
curl http://localhost:8081/health
nginx_set_upstream green
nginx_set_upstream blue # откат
docker stop blue
Преимущества: Ноль downtime, быстрый откат, полное тестирование перед переключением.
Недостатки: Требует 2x ресурсов, проблемы с DB миграциями.
2. Canary Deploy
Плавно переводим трафик на новую версию (5% → 25% → 100%).
import prometheus_client as prom
error_rate_v2 = prom.Counter('errors_v2', 'Errors in v2')
latency_v2 = prom.Histogram('latency_v2', 'Latency v2')
# Если error_rate > 5%, откатить автоматически
# Если latency > baseline + 20%, откатить
Преимущества: Минимальный риск, ранее обнаружение проблем, автоматический откат.
Недостатки: Медленный откат на 100%, нужны метрики и мониторинг.
3. Rolling Deploy
Постепенно заменяем инстансы (1-2-3-...-N).
apiVersion: apps/v1
kind: Deployment
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Преимущества: Автоматический откат, не требует 2x ресурсов, плавный деплой.
Недостатки: Временно разные версии в production, проблемы с несовместимыми миграциями БД.
4. Shadow Deploy
Дублируем трафик на новую версию, но не используем её ответы:
from functools import wraps
def shadow_deploy(shadow_handler):
def decorator(handler):
@wraps(handler)
def wrapper(request):
response = handler(request)
try:
shadow_response = shadow_handler(request)
log_shadow_metrics(response, shadow_response)
except Exception:
pass
return response
return wrapper
return decorator
Преимущества: Нулевой риск, реальные данные production, видим все edge cases.
Недостатки: Требует 2x ресурсов, сложная отладка.
5. Feature Flags (Feature Toggle)
Код уже в production, включаем через флаги:
class FeatureFlags:
def is_enabled(self, feature: str, user_id: str = None) -> bool:
key = f"{feature}:{user_id}" if user_id else feature
return self.flags.get(key, False)
features = FeatureFlags()
def process_order(order_id, user_id):
if features.is_enabled("new_payment", user_id):
return new_processor(order_id)
else:
return legacy_processor(order_id)
Преимущества: Развёртываем без деплоя, A/B тестирование, быстрый откат.
Недостатки: Код смешивается (if/else везде), техдолг от старого кода.
6. GitOps Deploy
Обновляем желаемое состояние в Git, ArgoCD синхронизирует:
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: myapp
image: myapp:v2.0
git add deployment.yaml
git commit -m "Deploy v2.0"
git push origin main
Преимущества: Single source of truth, откат через revert, полный аудит, RBAC.
Недостатки: Требует Kubernetes, нужна настройка CI/CD.
7. Database-driven Deploy
Миграции отдельно от кода:
ALTER TABLE users ADD COLUMN new_field VARCHAR(255) DEFAULT 'old';
UPDATE users SET new_field = name;
user = User.objects.get(id=1)
user.name # v1 работает
user.new_field # v2 работает
Ключ: Каждая миграция совместима с обеими версиями кода.
Матрица выбора
| Критерий | Blue-Green | Canary | Rolling | Shadow |
|---|---|---|---|---|
| Downtime | 0 | 0 | 0 | 0 |
| Risk | Низкий | Мин | Средний | Нулевой |
| Ресурсы | 2x | 1.1x | 1x | 2x |
| Откат | Быстрый | Быстрый | Медленный | N/A |
В production
- Микросервисы: GitOps (ArgoCD) + Rolling
- Монолит: Blue-Green + Feature Flags
- Critical API: Canary + Shadow
- Batch jobs: Feature Flags + Database migrations
Всегда комбинирую несколько стратегий для максимальной надёжности.