
Прим. перев. — Этой статьёй мы начинаем цикл переводов, посвященных теме Zero Downtime Deployment. Следующие публикации осветят вопросы деплоя новых версий приложения с БД и деплой в Kubernetes.
Несмотря на то, что техническое решение, описываемое ниже достаточно спорно, целью данной статьи является знакомство читателя непосредственно с подходом Blue-Green деплоя, который, кстати, применим не только к приложениям Spring.
Целью Blue-Green деплоя является устранение простоев во время развертывания новой версии приложения.
Простой связан с недоступностью серверов, когда новая версия приложения устанавливается для замены старой. Идея Blue / Green deployment заключается в развертывании новой версии приложения в некоем отдельном месте, где можно проводить тестирование, вплоть до момента принятия окончательного решения о переключении на неё как на основную.

В этой статье мы рассмотрим, как настроить Blue-Green деплой Spring boot приложения. Мы будем использовать Nginx в качестве основного веб-сервера для перенаправления входящих запросов в наши приложения.
Настройка сервера
В этом руководстве предполагается, что у вас есть сервер и работающее Spring boot приложение, которое можно на нём развернуть.
На сервере зайдите в домашнюю директорию и с��здайте две папки: blue и green. Затем нам понадобятся две символические ссылки available и testing. Эти ссылки будут указывать либо на синюю, либо на зеленую папку. Например, если available указывает на green, тогда testing указывает на blue.
mkdir blue mkdir green ln -s ./green ./available ln -s ./blue ./testing
Каждая папка будет содержать свое собственное приложение Spring и конфигурацию Nginx. В какой-то момент во время деплоя оба приложения будут работать одновременно (хотя и на разных портах), и для переключения с синего приложения на зеленое нам потребуется только изменить конфигурацию Nginx либо на green, либо на blue.

Конфигурации Nginx
Допустим, у нас есть домен springsite.com. “Зеленая” конфигурация Nginx перенаправит все вызовы springsite.com/api/ в приложение green на порт 8080, а все вызовы springsite.com/api-test/ — в приложение blue на порт 8090.
Давайте создадим эти конфигурационные файлы. Откройте ваш любимый редактор и добавьте следующее содержимое.
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name mysite.com; location /api { proxy_pass http://localhost:8090/api; } location /api-test { proxy_pass http://localhost:8080/api; } } include servers/*; }
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name mysite.com; location /api { proxy_pass http://localhost:8080/api; } location /api-test { proxy_pass http://localhost:8090/api; } } include servers/*; }
Структура файлов должна выглядеть примерно так:
--root |--- blue |--- nginx.conf.blue |--- app-V2.jar |--- green |--- nginx.conf.green |--- app-V1.jar |--- available -> ./green |--- testing -> ./blue
Допустим, мы хотим развернуть новую версию в blue контейнере. Мы можем протестировать ее, пока предыдущая версия еще доступна. Как только все довольны новой версией, нам нужно будет всего лишь поменять ссылки!
Создайте файл swap.sh в папке, содержащей как blue, так и green папки:
touch swap.sh chmod +x swap.sh
Добавьте следующее содержимое в файл swap.sh:
#!/bin/bash testing_now=$(ls -l ./ | grep testing) if [[ "$testing_now" == *blue ]] then testing="blue" active="green" else testing="green" active="blue" fi #remove current links rm ./available rm ./testing rm -f /etc/nginx/nginx.conf #create new links with the active/inactive reversed ln -s ./$inactive ./available ln -s ./$active ./testing ln -s /home/ubuntu/spring/$active/nginx.conf /etc/nginx/nginx.conf #reload the http server service nginx reload echo swap completed $active is now available
На этом этапе мы можем запустить 2 приложения Spring на портах 8090 и 8080 и менять их, запуская sudo ./swap.sh.
Деплой
Благодаря символическим ссылкам мы знаем, что на основное приложение всегда указывает available, а на тестируемое — testing. Следовательно, мы всегда должны деплоить новую версию приложения в папке testing, используя символическую ссылку. Предполагается, что мы только что упаковали приложение, и теперь мы можем загрузить его с помощью scp.
scp -r -i ~/.ssh/MyKeyPair.pem <package name.jar> <user>@<ip>:spring/testing
Идем дальше
Настройка Blue-Green деплоя на вашем сервере позволит значительно сократить время простоя. В этом руководстве объясняется, как деплоить новые версии вашего приложения, которые находятся на одном физическом сервере. Оно может быть адаптировано к ситуациям с несколькими физическими серверами и балансировщику нагрузки. Однако, для этого потребуется иметь вдвое больше производственных сред, чем необходимо. Для очень большой инфраструктуры это либо невозможно, либо чрезвычайно дорого.
Это приводит к вопросу: Как крупным компаниям удается выпускать новые версии своих приложений без простоев? Подумайте о Google или Facebook, которые всегда доступны!
Использование Blue-Green деплоя тут нереально из-за огромного количества необходимых серверов. Обновления приложений выполняются постепенно: серверы поочередно выводятся из работы, а после обновления возвращаются обратно. Более того, новые версии также выпускаются постепенно: в начале только небольшая часть серверов будет работать с новой версией. Затем, если проблем или багов не обнаружено, всё больше и больше серверов будут запускаться с новым кодом. На этом этапе оцениваются важные метрики производительности, такие как CPU, память и производительность запросов. Если все прошло успешно, то релиз завершен, и на каждом сервере по всему миру будет запущена новая версия приложения.
Заключение
Я надеюсь, теперь вы понимаете, как решить проблему простоя благодаря Blue-Green деплою. Теперь вы сможете настроить базовый Blue-Green деплой вашего Spring приложения с NGINX.
Как вы, возможно, заметили, когда мы используем это решение, старые и текущие версии ваших приложений работают одновременно и оба подключены к базе данных. Это может привести к неожиданным проблемам при изменении структуры базы данных. Эта замечательная статья https://spring.io/blog/2016/05/31/zero-downtime-deployment-with-a-database описывает, как справиться с подобными ситуациями.
И, наконец, вас может заинтересовать то, что и AWS, и Google Cloud Compute предлагают услуги по Blue-Green Deployment из коробки:
https://aws.amazon.com/quickstart/architecture/blue-green-deployment/
https://cloud.google.com/solutions/continuous-delivery/
Также читайте другие статьи в нашем блоге:
- Как запустить несколько пайплайнов с помощью GitLab CI/CD
- /etc/resolv.conf для Kubernetes pods, опция ndots:5, как это может негативно сказаться на производительности приложения
- Разбираемся с пакетом Context в Golang
- Три простых приема для уменьшения Docker-образов
- Бэкапы Stateful в Kubernetes
- Резервное копирование большого количества разнородных web-проектов
- Telegram-бот для Redmine. Как упростить жизнь себе и людям
