image


Прим. перев. — Этой статьёй мы начинаем цикл переводов, посвященных теме Zero Downtime Deployment. Следующие публикации осветят вопросы деплоя новых версий приложения с БД и деплой в Kubernetes.


Несмотря на то, что техническое решение, описываемое ниже достаточно спорно, целью данной статьи является знакомство читателя непосредственно с подходом Blue-Green деплоя, который, кстати, применим не только к приложениям Spring.


Целью Blue-Green деплоя является устранение простоев во время развертывания новой версии приложения.


Простой связан с недоступностью серверов, когда новая версия приложения устанавливается для замены старой. Идея Blue / Green deployment заключается в развертывании новой версии приложения в некоем отдельном месте, где можно проводить тестирование, вплоть до момента принятия окончательного решения о переключении на неё как на основную.


image


В этой статье мы рассмотрим, как настроить 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.


image


Конфигурации 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/


Также читайте другие статьи в нашем блоге:


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


  1. jashcka
    08.10.2019 13:15

    спасибо интересно, но думаю это просто
    а как быть с базой / миграциями
    где почитать про это?


    1. AlexeyTokar
      08.10.2019 14:15

      liquibase решает. А с недавних версий MySQL, например, поддерживает online ddl. А мейнтененс СУБД — это вопрос вашей архитектуры. Для Mongo — это, например, mongos. А для того же MySQL — mysql proxy… Масса вариантов. Исходить надо из задачи


      1. fori1ton
        08.10.2019 15:31

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


        1. AlexeyTokar
          08.10.2019 16:00

          ну вот же — вы все правильно расписали :) менеджится в две-три стадии в зависимости от комплексности изменения. автоматизированных средств я пока не встречал да и сложно себе их представляю.


    1. borisershov Автор
      09.10.2019 16:25

      Здравствуйте!

      Скоро от нас будут ещё переводы статей, продолжающие тему Zero Downtime, в которых как раз будет рассказываться про миграции БД )


  1. 3draven
    08.10.2019 18:41

    Кубернетис и контейнеры наше все.