Автор статьи: Рустем Галиев
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)
BasilioCat
07.09.2023 11:44+2Да, stateless приложение типа hello world без БД отлично работает в такой схеме. Зачем, правда, таким приложениям столь сложная схема переключения? Фаулер в схеме указывает еще и две БД - для blue и green. И этот прекрасный момент все сторонники b/g подхода почему-то обходят стороной. Делов-то, обеспечить синхронизацию БД сначала blue -> green, применить миграции к green, переключить нагрузку на БД green, ...[какая-то магия]..., и blue с green поменялось местами без потери данных. Если из схемы b/g убрать раздельные БД, оставив одну центральную, то начинаются пляски с совместимыми миграциями, и начинаются вопросы к миграциям при откате приложения на предыдущую версию, если не взлетело. По сравнению с которыми плюс одномоментного переключения на новую версию и обратно несколько меркнет
olku
07.09.2023 11:44Для Кубера канареечное развертывание более естественно. Но обоих случаях миграция базы без даунтайма можно делать отдельной джобой, после бакапа и до развертывания нового кода. Старый код предварительно тестируется с мигрированной базой.
olku
07.09.2023 11:44А как выглядит переключение трафика, если мы развернем сервисы в Грин и Блю неймспейсах?
Luchnik22
Может есть рецепт, как направлять только часть трафика на новую версию, а часть по прежнему на старую?
chemtech
Istio canary
S1M
https://habr.com/ru/company/ru_mts/blog/695242/ я в самом начале писал, про ingress canary. Istio тоже можно, но сложнее
GeorgeAbramov
Посмотрите GitOps инструмент ArgoRollouts - реализация Canary там, как мне кажется, одна из самых понятных и удобных