← Назад к вопросам

Что такое canary deployment?

1.3 Junior🔥 161 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Canary Deployment

Определение

Canary Deployment — это стратегия развертывания новой версии приложения, при которой новый код сначала развертывается только для небольшого процента пользователей (5-10%), а затем постепенно увеличивается количество пользователей, получающих новую версию. Если всё работает корректно, новая версия постепенно раскатывается на 100% пользователей.

Происхождение названия

"Canary" (канарейка) — историческое название от практики шахтёров, которые брали канареек в шахты. Птица была индикатором опасного газа: если канарейка падала, это означало опасность. Здесь новая версия выступает "канарейкой" для обнаружения проблем перед полным развертыванием.

Архитектура Canary Deployment

         Пользователи (100%)
              │
         ┌────┴────┐
         │          │
      90%│          │10% (Canary)
         │          │
    ┌────v───┐ ┌────v────┐
    │ Старая │ │  Новая  │
    │версия  │ │ версия  │
    │ v1.0   │ │ v1.1    │
    └────────┘ └─────────┘
         │          │
         │ Мониторинг
         │          │
    Если OK ──> Увеличить % новой версии
    Если ошибка ──> Быстрый rollback

Этапы Canary Deployment

Этап 1: Подготовка (0% → 5%)

# Конфигурация балансировщика (например, NGINX или Kubernetes)
# 5% трафика на новую версию
upstream app_v1 {
    server app-v1:8000 weight=95;
    server app-v1-new:8000 weight=5;  # Canary
}

Этап 2: Мониторинг (5%)

import logging
from prometheus_client import Counter, Histogram
import time

# Метрики для мониторинга
error_rate = Counter("app_errors_total", "Total errors", ["version"])
response_time = Histogram("response_time_seconds", "Response time", ["version"])

def handle_request(version):
    start = time.time()
    try:
        result = process_request()
        duration = time.time() - start
        response_time.labels(version=version).observe(duration)
        return result
    except Exception as e:
        error_rate.labels(version=version).inc()
        logging.error(f"Error in {version}: {e}")
        raise

Этап 3: Постепенное увеличение (5% → 25% → 50% → 100%)

# Пример с использованием Kubernetes
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: app
spec:
  hosts:
  - app
  http:
  - match:
    - headers:
        user-type:
          exact: "canary_user"  # Метка для canary
    route:
    - destination:
        host: app
        subset: v1_1  # Новая версия
  # Остальные пользователи (95%)
  - route:
    - destination:
        host: app
        subset: v1_0
      weight: 95
    - destination:
        host: app
        subset: v1_1
      weight: 5  # Начинаем с 5%

Этап 4: Полный rollout (100%)

Когда метрики в норме, 100% трафика переводится на новую версию.

Реальный пример с Docker и NGINX

# app_v1.0/main.py
from flask import Flask

app = Flask(__name__)

@app.route("/api/status")
def status():
    return {"version": "1.0", "status": "ok"}

@app.route("/api/data")
def get_data():
    # Старая логика
    return {"data": [1, 2, 3]}

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)
# app_v1.1/main.py (новая версия с улучшениями)
from flask import Flask

app = Flask(__name__)

@app.route("/api/status")
def status():
    return {"version": "1.1", "status": "ok", "improvements": ["faster", "more_data"]}

@app.route("/api/data")
def get_data():
    # Улучшенная логика
    return {"data": [1, 2, 3], "count": 3}  # Добавлено count

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)
# NGINX конфигурация для canary
upstream app_v1_0 {
    server app-v1.0:8000;
}

upstream app_v1_1 {
    server app-v1.1:8000;  # Canary
}

server {
    listen 80;
    server_name api.example.com;
    
    # 5% на canary, 95% на stable
    location / {
        # Случайный выбор с весами
        set $upstream "app_v1_0";
        set $random $msec;  # Текущее время в мс
        
        if ($random % 100 <= 5) {
            set $upstream "app_v1_1";  # 5% на новую версию
        }
        
        proxy_pass http://$upstream;
    }
}

Мониторинг и метрики

from prometheus_client import start_http_server, Counter, Gauge, Histogram
import time

# Метрики для tracking
request_count = Counter(
    "requests_total",
    "Total requests",
    ["version", "endpoint", "method"],
)

error_count = Counter(
    "errors_total",
    "Total errors",
    ["version", "error_type"],
)

response_time = Histogram(
    "response_seconds",
    "Response time",
    ["version"],
    buckets=(0.1, 0.5, 1.0, 2.5, 5.0),
)

# Запуск метрик сервера
start_http_server(8001)

def process_request(version):
    start = time.time()
    try:
        # Обработка запроса
        result = business_logic()
        duration = time.time() - start
        
        # Фиксирование метрик
        request_count.labels(version=version, endpoint="/api/data", method="GET").inc()
        response_time.labels(version=version).observe(duration)
        
        return result
    except Exception as e:
        error_count.labels(version=version, error_type=type(e).__name__).inc()
        raise

Критерии отката (Rollback)

# Если метрики показывают проблемы, откатить на старую версию
error_rate_threshold = 0.05  # 5% ошибок
latency_threshold = 1.0      # 1 секунда

def should_rollback(metrics):
    v1_1_error_rate = metrics["v1.1"]["error_rate"]
    v1_1_p99_latency = metrics["v1.1"]["p99_latency"]
    v1_0_error_rate = metrics["v1.0"]["error_rate"]
    
    # Если ошибки значительно выше
    if v1_1_error_rate > v1_0_error_rate * 2:
        return True
    
    # Если latency выше threshold
    if v1_1_p99_latency > latency_threshold:
        return True
    
    return False

Сценарий полного развертывания

Время  | Версия v1.0 | Версия v1.1 | Статус
-------|-------------|-------------|------------------
0 мин  | 100%        | 0%          | Развертывание началось
5 мин  | 95%         | 5%          | Мониторинг (canary)
15 мин | 90%         | 10%         | Увеличение (OK)
30 мин | 75%         | 25%         | Дальнейшее увеличение
45 мин | 50%         | 50%         | Полусеride
60 мин | 25%         | 75%         | Почти готово
75 мин | 0%          | 100%        | Полное развертывание

Преимущества

  • Минимальный риск: только 5% пользователей затронуты ошибками
  • Ранее обнаружение: проблемы выявляются до полного развертывания
  • Быстрый rollback: если что-то не так, легко откатить
  • Реальные данные: тестируется на реальном трафике
  • Zero-downtime: пользователи не заметят развертывания

Инструменты для Canary Deployment

  • Kubernetes с Istio/Linkerd
  • ArgoCD для GitOps
  • Flagger для automated canary
  • Nginx с custom конфигом
  • AWS CodeDeploy (managed service)
  • Jenkins с custom scripts

Итоговая схема

Canary Deployment — это безопасная стратегия развертывания, при которой новая версия сначала развертывается для малого % пользователей, затем постепенно раскатывается на всех, с мониторингом и возможностью быстрого отката при появлении проблем.

Что такое canary deployment? | PrepBro