Автор статьи: Рустем Галиев

IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM


Развитие и обновление приложений - это важная часть жизненного цикла разработки программного обеспечения. В мире микросервисов и контейнеризации, Kubernetes стал платформой выбора для развертывания и управления приложениями. Однако одним из основных вызовов при обновлении приложений в Kubernetes является минимизация времени простоя (downtime) и рисков.

Blue-Green Deployment (сине-зеленое развертывание) - это стратегия, которая позволяет разработчикам и операторам эффективно справляться с этими вызовами. Она предоставляет возможность переключаться между двумя параллельными окружениями для приложения - активным (синим) и новым (зеленым), обеспечивая бесперебойное обновление приложения без ущерба для доступности.

Сердцем шаблона декларативного развертывания является ресурс Kubernetes Deployment. Эта абстракция инкапсулирует процессы обновления и отката группы контейнеров и делает их выполнение повторяемым и автоматизированным действием.

Абстракция развертывания Kubernetes — это фундаментальная концепция, позволяющая определить, как Kubernetes переносит неизменяемые контейнеры из одной версии в другую. Мы можем использовать примитив развертывания в качестве строительного блока вместе с другими примитивами Kubernetes для реализации этой более продвинутой стратегии выпуска.

Сине-зеленое развертывание необходимо выполнить вручную, если не используется такое расширение, как Service Mesh или Knative. Технически это работает путем создания второго развертывания, при этом последняя версия контейнеров (назовем ее зеленой) еще не обслуживает никаких запросов. На этом этапе старые реплики Pod из исходного развертывания (называемые синими) все еще работают и обслуживают текущие запросы.

Мы начнем с создания начального развертывания, которое запускает версию 1.0 образа контейнера k8spatterns/random-generator в контейнерах его реплик. Добавим определение развертывания в blue-deployment.yaml. Имейте в виду, что присвоена метка version=blue:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: random-generator-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: random-generator
      version: blue
  template:
    metadata:
      labels:
        app: random-generator
        version: blue
    spec:
      containers:
      - image: k8spatterns/random-generator:1.0
        name: random-generator
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /info
            port: 8080
          initialDelaySeconds: 5

Далее

kubectl apply -f blue-deployment.yaml

Мы должны обнаружить, что созданы три реплики. Подождите, пока все модули не перейдут в статус «Running»:

kubectl get pods -l app=random-generator,version=blue

Маршрутизация трафика к репликам random-generator-blue  происходит через службу типа ClusterIP. Добавляем в файл service.yaml следующее содержимое:

apiVersion: v1
kind: Service
metadata:
  name: random-generator
spec:
  selector:
    app: random-generator
    version: blue
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Создаем: kubectl apply -f service.yaml

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

kubectl run tmp --image=alpine/curl:3.14 --restart=Never -it --rm -- curl random-generator.default.svc.cluster.local

Теперь займемся созданием еще одного модифицированного (зеленого) развертывания.

Мы создадим еще одно развертывание, которое будет запускать версию 2.0 образа контейнера k8spatterns/random-generator в контейнерах его реплик. Добавим следующее определение развертывания в green-deployment.yaml. Имейте в виду, что присвоена метка version=green:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: random-generator-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: random-generator
      version: green
  template:
    metadata:
      labels:
        app: random-generator
        version: green
    spec:
      containers:
      - image: k8spatterns/random-generator:2.0
        name: random-generator
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /info
            port: 8080
          initialDelaySeconds: 5

Создадим

kubectl apply -f green-deployment.yaml

Проверим, что все запущено:

Теперь про переключение трафика на модули, контролируемые зеленым развертыванием.

Как только мы уверены, что новая версия модулей Pod работоспособна и готова обрабатывать текущие запросы, мы переключаем трафик со старых реплик Pod на новые реплики. Вы можете сделать это в Kubernetes, обновив селектор, чтобы он соответствовал новым контейнерам (отмечены зеленым). Как показано на рисунке ниже, как только зеленые контейнеры обработают весь трафик, синие контейнеры можно удалить, а ресурсы освободить для будущих сине-зеленых развертываний:

Отредактируем определение службы в файле service.yaml так, чтобы селектор меток указывал на поды с версией назначения метки = green:

apiVersion: v1
kind: Service
metadata:
  name: random-generator
spec:
  selector:
    app: random-generator
    version: green
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Применим изменения:

kubectl apply -f service.yaml

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

kubectl delete deployment random-generator-blue

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

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

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


  1. Luchnik22
    07.09.2023 11:44

    Может есть рецепт, как направлять только часть трафика на новую версию, а часть по прежнему на старую?


    1. chemtech
      07.09.2023 11:44

      Istio canary


    1. S1M
      07.09.2023 11:44

      https://habr.com/ru/company/ru_mts/blog/695242/ я в самом начале писал, про ingress canary. Istio тоже можно, но сложнее


    1. GeorgeAbramov
      07.09.2023 11:44
      +1

      Посмотрите GitOps инструмент ArgoRollouts - реализация Canary там, как мне кажется, одна из самых понятных и удобных


  1. BasilioCat
    07.09.2023 11:44
    +2

    Да, stateless приложение типа hello world без БД отлично работает в такой схеме. Зачем, правда, таким приложениям столь сложная схема переключения? Фаулер в схеме указывает еще и две БД - для blue и green. И этот прекрасный момент все сторонники b/g подхода почему-то обходят стороной. Делов-то, обеспечить синхронизацию БД сначала blue -> green, применить миграции к green, переключить нагрузку на БД green, ...[какая-то магия]..., и blue с green поменялось местами без потери данных. Если из схемы b/g убрать раздельные БД, оставив одну центральную, то начинаются пляски с совместимыми миграциями, и начинаются вопросы к миграциям при откате приложения на предыдущую версию, если не взлетело. По сравнению с которыми плюс одномоментного переключения на новую версию и обратно несколько меркнет


    1. olku
      07.09.2023 11:44

      Для Кубера канареечное развертывание более естественно. Но обоих случаях миграция базы без даунтайма можно делать отдельной джобой, после бакапа и до развертывания нового кода. Старый код предварительно тестируется с мигрированной базой.


  1. olku
    07.09.2023 11:44

    А как выглядит переключение трафика, если мы развернем сервисы в Грин и Блю неймспейсах?