Сине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать

  1. Главная
  2. Блог
  3. DevOps

DevOps

Сине-зеленое и канареечное развертывание: Различия, компромиссы и как выбрать

Обе стратегии позволяют выпустить релиз, не закрывая сайт, но они управляют рисками противоположными способами. Узнайте, как каждый из них работает, сколько он на самом деле стоит, как обращаться с базой данных и что подходит вашей команде.

9 мин чтения
Сине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать

Главное

  • Сине-зеленый поддерживает две полные среды и переключает весь трафик одновременно.
  • Canary сначала рассылает новую версию небольшому количеству пользователей, а затем постепенно расширяет ее.
  • Сине-зеленый предлагает очень быстрый откат. Canary ограничивает количество пользователей, на которых может повлиять плохой выпуск.
  • Оба зависят от обратно совместимых изменений базы данных и хорошего мониторинга.

Выпуск программного обеспечения раньше означал окно обслуживания и скрещенные пальцы. Современные команды используют стратегии, которые делают релизы рутинными, и выбор сине-зеленое или канареечное развертывание — один из первых, с которыми вы столкнетесь. Оба снижают риск, но делают это противоположными способами: один готовит полную замену, а другой понемногу тестирует на реальных пользователях.

В этом руководстве объясняется, как каждый из них работает и сколько это стоит на практике. Мы выполнили небольшие примеры маршрутизации пользователей и отката в Python 3.13, и в результате этого запуска были получены выходные данные. Примеры Kubernetes носят иллюстративный характер, и мы их не запускали. Рассматривайте проценты и пороговые значения как отправные примеры для адаптации.

Короткий ответ

При сине-зеленом развертывании вы запускаете две идентичные производственные среды. Один обслуживает пользователей, пока вы развертываете и тестируете новую версию на другом, а затем переключаете весь трафик одним движением.

При canary-развертывании новая версия запускается рядом со старой. Вы отправляете ему небольшой процент реального трафика, сравниваете результаты и шаг за шагом увеличиваете долю, пока она не будет обслуживать всех. Название происходит от канареек-шахтеров, которые когда-то использовались в качестве раннего предупреждения об опасности.

Сине-зеленый против канарейки бок о бок

Аспект Сине-зеленый Канарейка
Изменение трафика Все сразу Постепенный
Пользователи, столкнувшиеся с плохой версией Всё, пока ты не переключишься обратно Только канарейка доля
Откат Переключить трафик обратно Установите канареечную долю на ноль
Скорость выпуска Быстрое переключение Медленнее, поэтапно
Стоимость инфраструктуры До удвоения во время выпуска Небольшая дополнительная доля
Требуется маршрутизация трафика Простой переключатель Процентная маршрутизация
Необходим мониторинг Хорошо Отлично, с метриками для каждой версии
Версии живут вместе Вкратце, если вообще За весь выпуск
Отзывы реальных пользователей перед полным выпуском Нет Да

Как работает сине-зеленое развертывание

  1. Blue работает и обслуживает весь трафик.
  2. Разверните новую версию на зеленом, который не получает пользовательский трафик.
  3. Тщательно протестируйте «зеленость» в реальной производственной среде, используя дымовые тесты и внутренних пользователей.
  4. Переключите маршрутизатор, балансировщик нагрузки или DNS, чтобы направлять трафик на зеленый цвет.
  5. Смотрите внимательно: синий все еще работает и готов.
  6. Если что-то не так, переключитесь обратно. Если все в порядке, следующим местом ожидания станет синий цвет.

В Kubernetes вы можете выполнить переключение, изменив селектор службы, чтобы трафик перемещался к модулям с разными метками:

apiVersion: v1
kind: Service
metadata:
  name: shop
spec:
  selector:
    app: shop
    version: green   # was: blue
  ports:
    - port: 80
      targetPort: 8000

Сильные стороны: Это концептуально просто: вы можете протестировать точную производственную настройку до того, как ее увидят пользователи, а откат происходит практически мгновенно. Слабые стороны: Дублированная инфраструктура может быть дорогостоящей, ошибка, которая ускользает от ваших тестов, достигает всех сразу, а открытые сеансы и работа в реальном времени требуют осторожности во время перехода. Если вы используете DNS для переключения, кэшированные записи могут задержать его. Новое в концепциях? См. наше руководство по Kubernetes для начинающих.

Как работает канареечное развертывание

  1. Разверните новую версию вместе со стабильной.
  2. Направьте небольшую долю трафика, например 5%, на канарейку.
  3. Сравните частоту ошибок, задержку и бизнес-показатели со стабильной версией.
  4. Если здоров, увеличьте до 25%, затем 50%, затем 100%.
  5. Если что-то ухудшится, отправьте весь трафик обратно в стабильную версию.

Многие команды начинают работу с внутренним персоналом, затем с регионом низкого риска и только потом с широкой общественностью.

Сильные стороны: Плохой релиз затрагивает только небольшую группу, и на реальном трафике вы узнаете, что ни одна тестовая среда не может полностью воспроизвести. Слабые стороны: Вам нужны процентные показатели маршрутизации и метрики для каждой версии, развертывание занимает больше времени, а две версии некоторое время работают вместе. Маленькая канарейка также может быть слишком тихой, чтобы подать значимый сигнал, особенно в периоды низкого трафика.

Стабильная маршрутизация пользователей

Случайный выбор версии при каждом запросе сбивает пользователей с толку, поскольку они могут переключаться между старым и новым. Распространенным решением является хеширование стабильного идентификатора пользователя в корзину, чтобы каждый пользователь всегда получал один и тот же ответ:

import hashlib

def bucket(user_id):
    digest = hashlib.sha256(user_id.encode()).hexdigest()
    return int(digest, 16) % 100

def version_for(user_id, canary_percent):
    return "v2" if bucket(user_id) < canary_percent else "v1"

users = [f"user-{i}" for i in range(10000)]
for percent in (5, 25, 50, 100):
    share = sum(version_for(u, percent) == "v2" for u in users) / len(users)
    print(percent, round(share * 100, 1))

# 5 5.0
# 25 24.5
# 50 49.9
# 100 100.0

Фактическая доля почти соответствовала целевому показателю. У этого метода есть еще два полезных свойства, и наш эксперимент подтвердил оба. Один и тот же пользователь всегда получал одну и ту же версию. И все в группе 5% по-прежнему были включены в группу 25%, поэтому никто из тех, у кого уже была новая версия, не был перемещен обратно по мере роста развертывания.

В реальных системах эту маршрутизацию обычно обрабатывает сервисная сетка, балансировщик нагрузки или такой инструмент, как Argo Rollouts или Flagger, поэтому вам не нужно писать ее самостоятельно. По-прежнему полезно понимать, что они делают.

Автоматизация принятия решения

Канарейка работает только в том случае, если кто-то действительно сравнивает версии. Автоматизированные проверки надежнее, чем человек, наблюдающий за графиками. Вот основная идея — сравнение частоты ошибок Canary со стабильной версией:

def should_rollback(canary_errors, canary_total, base_errors, base_total,
                    tolerance=1.5, min_requests=500):
    if canary_total < min_requests:
        return False   # not enough data to decide
    return (canary_errors / canary_total) > (base_errors / base_total) * tolerance

should_rollback(3, 100, 10, 5000)        # False: too few requests
should_rollback(30, 1000, 100, 10000)    # True:  3% against 1%
should_rollback(12, 1000, 100, 10000)    # False: 1.2% is within tolerance

Обратите внимание на первый случай. Частота ошибок выглядит высокой, но всего лишь 100 запросов — это еще недостаточно доказательств. Реальные инструменты применяют более точную статистику и рассматривают несколько сигналов вместе:

Сигнал Пример
Ошибки Частота 5xx ответов
Задержка p95 и p99, как объяснено в нагрузочном тестировании и стресс-тестировании
Насыщенность ЦП, память, пулы соединений
Бизнес Регистрация, оформление заказа, успешная оплата

Совет: Сравните Canary со стабильной версией за тот же период времени, а не с показателями прошлой недели. Трафик и поведение меняются с каждым часом, поэтому параллельное сравнение дает вам гораздо более справедливый сигнал.

Проблема с базой данных

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

Стандартный ответ — шаблон расширения и сужения. Предположим, вы хотите переименовать name в full_name:

  1. Развернуть: добавьте новый столбец. Старый код не затрагивается.
  2. Миграция: выпустите код, который записывает данные в оба столбца и заполняет старые строки.
  3. Switch: код выпуска, который считывает из нового столбца.
  4. Контракт: если старый столбец не используется, удалите его в более поздней версии.

Для этого потребуется несколько релизов, но каждый шаг можно безопасно откатить. Запуск RENAME COLUMN ​​за один раз приведет к поломке той версии, которая ожидала другого имени. Будьте осторожны с долговременными изменениями схемы, поскольку они могут удерживать блокировки. Подробнее об этом читайте о транзакциях SQL.

Роллинг и другие стратегии

Стратегия Как это работает Хорошо для
Воссоздать Остановите старое, затем начните новое, с простоем Внутренние инструменты, пакетные системы
Роллинг Заменяйте экземпляры по несколько за раз Распространенное значение по умолчанию, в том числе в Kubernetes.
Сине-зеленый Переключение между двумя средами Быстрое переключение и откат
Канарейка Постепенно расширяйте небольшую долю Высокий трафик, высокий риск
Тень Скопируйте трафик в новую версию и отбросьте ее ответы. Тестирование с реальной нагрузкой без влияния на пользователя

Развертывание Kubernetes по умолчанию выполняет скользящее обновление, что подходит для многих сервисов. Прокатное обновление также смещается постепенно, но его доля привязана к количеству экземпляров, и оно само по себе не анализирует результаты и не делает паузу на плохих показателях.

А как насчет флагов функций?

При развертывании код размещается на серверах, а релиз делает функцию доступной для пользователей. Флаги функций разделяют их, позволяя вам включить функцию для выбранных пользователей, не развертывая ничего. Они очень хорошо работают с обеими стратегиями: развернуть со снятым флагом, а затем постепенно включать его. Они не заменяют эти стратегии, поскольку флаг не может защитить вас от сбоя выпуска при запуске. Не забудьте удалить старые флаги, так как они накапливаются как технический долг.

Как выбрать

Ваша ситуация Разумный выбор
Простое приложение и мало пользователей Постоянное обновление
Требуется очень быстрое переключение и откат Сине-зеленый
Хотите протестировать в производстве перед переходом Сине-зеленый
Высокий трафик и высокая цена отказа Канарейка
Надежный мониторинг и метрики для каждой версии Канарейка
Низкий трафик Сине-зеленый, поскольку сигналы канарейки слишком слабые.
Ограниченный бюджет на инфраструктуру Канарейка или прокатка

Их также можно комбинировать. Некоторые команды развертывают зеленую среду, а затем постепенно переносят туда движение транспорта, получая чистую среду и ограниченный радиус взрыва. Что бы вы ни выбрали, автоматизируйте это с помощью конвейера CI/CD, как объясняется в нашем руководстве по действиям GitHub.

Распространенные ошибки

  • Внесение критических изменений в схему. Откат не помогает, если старый код не может прочитать данные.
  • Отсутствие критериев отката. Решите, что означает «плохо», до начала выпуска, а не во время инцидента.
  • Позволить окружающей среде дрейфовать. Если зеленый цвет отличается от синего, ваши тесты докажут меньший результат. Определите оба с инфраструктурой как кодом.
  • Измерение только технических показателей. Релиз может быть безошибочным, но все равно нарушать проверку.
  • Никогда не практикуйте откат. Репетируйте это, чтобы оно работало, когда вы находитесь под давлением.
  • Забываем о фоновых заданиях. Рабочим и запланированным задачам также требуется план во время переключения.

Итоги

Сине-зеленый обеспечивает чистое и быстрое переключение. Canary дает вам небольшую, размеренную экспозицию. Если ваш мониторинг по-прежнему базовый, начните с чередующихся обновлений или сине-зеленых и инвестируйте в метрики для каждой версии, прежде чем пробовать канарейки. Затем порепетируйте откат следующей версии, включая базу данных. Это единственное упражнение, как правило, показывает, что действительно нуждается в исправлении.

Часто задаваемые вопросы

В чем разница между сине-зеленым и канареечным развертыванием?

Сине-зеленый переключает весь трафик из одной полноценной среды в другую одновременно. Canary направляет небольшую долю трафика на новую версию и постепенно расширяет ее.

Что безопаснее, сине-зеленый или канареечный?

Canary ограничивает количество пользователей, на которых влияет плохой выпуск, а сине-зеленый предлагает очень быстрый откат. Более безопасный выбор зависит от вашего трафика, инструментов и мониторинга.

Дорого ли развертывание сине-зеленой системы?

Это возможно, поскольку во время выпуска вы можете запустить две полные среды. Автоматическое масштабирование облака и отключение неактивной среды могут снизить затраты.

С какого процента следует начинать канарейке?

Обычно команды начинают с 1–5 процентов, если это обеспечивает достаточный трафик для значимого сигнала. Системам с низким трафиком может потребоваться большая доля.

Как канареечные и сине-зеленые обрабатывают изменения в базе данных?

Обычно с обратно совместимыми изменениями, такими как расширение и сжатие, поскольку обе версии могут использовать одну базу данных и обе должны работать во время развертывания.

Продолжайте учиться

Работайте с Stack Quora

Нужна помощь с тестированием, WordPress или SEO?

Мы помогаем командам выпускать лучшее программное обеспечение и развивать свои сайты. Расскажите нам, над чем вы работаете, и мы предложим четкий следующий шаг.

Продолжайте читать

Больше руководств по тестирование, искусственный интеллект и современные разработки

Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.

Искусственный интеллект

Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить

Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…

Читать статью →
DevOps

Объяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация

Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…

Читать статью →
Разработка ПО

Объяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429

Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…

Читать статью →
Автоматизация тестирования

Издевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут

Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …

Читать статью →
Тестирование ПО

Объяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%

Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…

Читать статью →
Базы данных и SQL

DELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них

Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…

Читать статью →
Базы данных и SQL

Объяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами

Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…

Читать статью →
Разработка ПО

Интерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора

Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…

Читать статью →
Разработка ПО

Объяснение Python *args и **kwargs: гибкие функции с понятными примерами

Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…

Читать статью →
Разработка ПО

Лямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать

Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …

Читать статью →
Искусственный интеллект

Что такое ИИ-агенты? Как они работают: можно запустить простой цикл агента

Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…

Читать статью →
DevOps

Мониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками

Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…

Читать статью →
DevOps

Docker Volumes против Bind Mounts: правильное сохранение данных контейнера

Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…

Читать статью →
Автоматизация тестирования

TDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый

TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…

Читать статью →
Тестирование ПО

Пользовательское приемочное тестирование (UAT): процесс, контрольный список и реальные примеры

Приемочное тестирование пользователей объяснило: кто его проводит, чем оно отличается от контроля качества, семиэтапный процесс, шаблон тестового сц…

Читать статью →
Базы данных и SQL

Объяснение значений NULL в SQL: IS NULL, COALESCE, NULLIF и ловушки, которых следует избегать

Значения SQL NULL объяснены с помощью запросов, которые мы выполнили: трехзначная логика, IS NULL, COALESCE, NULLIF, как агрегаты, соединения и сорт…

Читать статью →
Базы данных и SQL

Оператор SQL CASE WHEN: синтаксис, реальные примеры и распространенные ошибки

SQL CASE WHEN объяснен с помощью запросов, которые мы выполняли: простые формы и формы для поиска, порядок условий, повороты с помощью SUM, трюки CO…

Читать статью →
Разработка ПО

Что такое JWT? Веб-токены JSON, объясненные на рабочем примере

Что такое JWT? Объяснение JSON Web Tokens: три части: токен, созданный и измененный в коде, который мы запускали, JWT и сеансы, хранилище, токены об…

Читать статью →
Разработка ПО

Объяснение цикла событий JavaScript: стек вызовов, микрозадачи и таймеры с примерами

Цикл событий JavaScript объясняется с помощью кода, который мы запускали: стек вызовов, очереди задач и микрозадач, почему setTimeout 0 не является …

Читать статью →
Разработка ПО

Генераторы Python и объяснение доходности: экономьте память с помощью реальных примеров

Генераторы Python и доходность, объясненные с помощью кода, который мы запускали: как они приостанавливаются и возобновляются, измеряют экономию пам…

Читать статью →
Искусственный интеллект

Что такое вложения? Простое объяснение векторов и косинусного сходства

Что такое вложения? Простое руководство по векторам, косинусному подобию и семантическому поиску с небольшим примером, который мы использовали, общи…

Читать статью →
DevOps

Сине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать

Объяснение сине-зеленого и канареечного развертывания: как каждый из них работает, стоимость, риски и откат, стабильное группирование пользователей,…

Читать статью →
Автоматизация тестирования

Ненадежные тесты: что их вызывает и как их исправить навсегда

Ненадежные тесты объясняются на демонстрациях, которые мы запускали: основные причины, способы подтверждения и диагностики, правильные исправления в…

Читать статью →
Тестирование ПО

Нагрузочное тестирование и стресс-тестирование: различия, метрики и примеры k6

Объяснение нагрузочного и стресс-тестирования: что доказывает каждое из них, тесты на всплески и выдержки, важные метрики, почему средние значения в…

Читать статью →
Тестирование ПО

Тестовый пример и тестовый сценарий: ключевые различия, примеры и когда использовать каждый

Объяснение тестового случая и тестового сценария: четкие определения, параллельная таблица, одна функция сброса пароля, взятая из сценариев в случаи…

Читать статью →
Базы данных и SQL

Оптимизация SQL-запросов: чтение планов выполнения и исправление медленных запросов с указанием времени

Оптимизация SQL-запросов проверена на миллионе строк: читайте планы выполнения, добавляйте правильные индексы, исправляйте неразмещаемые фильтры, ис…

Читать статью →
Базы данных и SQL

SQL UNION против UNION ALL: различия, примеры и проверка производительности

SQL UNION и UNION ALL объяснены с помощью запросов, которые мы выполнили: дубликаты, правила, которым следуют оба, реальная ошибка данных, измеренна…

Читать статью →
Разработка ПО

Учебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты

Учебное пособие по API JavaScript Fetch, протестированное на локальном сервере: GET и POST, почему не выдается ошибка 404, многоразовый помощник, ст…

Читать статью →
Разработка ПО

Обработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами

Обработка файлов Python объясняется с помощью кода, который мы запускали: открытые режимы, чтение больших файлов, CSV, JSON, pathlib, двоичные файлы…

Читать статью →
Разработка ПО

Классы и объекты Python: учебник ООП с реальными примерами

Классы и объекты Python, объясненные с помощью кода, который мы запускали: __init__, методы, атрибуты класса и экземпляра, наследование, свойства, м…

Читать статью →
Искусственный интеллект

Что такое большая языковая модель? Как работают LLM, объяснено без шумихи

Что такое большая языковая модель? LLM объясняется простым языком: токены, встраивания, внимание, обучение, температурные и контекстные окна, крошеч…

Читать статью →
DevOps

Команды Linux для начинающих: основное руководство по терминалу с примерами

Команды Linux для начинающих, сгруппированные по задачам: навигация, файлы, просмотр журналов, grep, каналы, разрешения, процессы и архивы, с практи…

Читать статью →
Автоматизация тестирования

Selenium vs Playwright: ключевые различия, сравнение кода и что выбрать

Сравнение Selenium и Playwright: архитектура, ожидание, поддержка браузера и языка, отладка, одинаковый тест в обоих инструментах, советы по миграци…

Читать статью →
Тестирование ПО

Разделение эквивалентности: метод проектирования тестов, объясненный на рабочих примерах

Объяснение эквивалентного разделения: как найти действительные и недействительные разделы, рабочие примеры для возрастов, паролей и купонов, проведе…

Читать статью →
Тестирование ПО

Серьезность и приоритет в тестировании программного обеспечения: различия, матрица и реальные примеры

Объяснение серьезности и приоритета при тестировании программного обеспечения: четкие определения, четырехсторонняя матрица с примерами, шкалы уровн…

Читать статью →
Базы данных и SQL

Учебное пособие по подзапросам SQL: типы, коррелирующие подзапросы и EXISTS с примерами

Руководство по подзапросам SQL с выполненными нами запросами: скалярные подзапросы, IN, FROM и SELECT, коррелированные подзапросы, EXISTS, ловушка N…

Читать статью →
Базы данных и SQL

Объяснение транзакций SQL и ACID: COMMIT, ROLLBACK и уровни изоляции

Транзакции SQL и ACID, объясненные с помощью банковского перевода, который мы выполнили: COMMIT, ROLLBACK, точки сохранения, блокировки, уровни изол…

Читать статью →
Разработка ПО

Git merge vs rebase: отличия, примеры и когда что использовать

Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.

Читать статью →
Разработка ПО

Генераторы списков в Python: синтаксис, примеры и когда их избегать

Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.

Читать статью →
Базы данных и SQL

SQL JOIN: объяснение с примерами (Inner, Left, Right, Full)

Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…

Читать статью →