Blue-Green Deployment of Spring Applications

6
minutes
Mis à jour le
12/9/2019

Share this post

Blue-Green deployment aims to remove downtime due to the deployment of a new version of an application. Downtime refers to the unavailability of servers...

#
DevOps
#
Spring Boot
Blue-Green deployment aims to remove downtime due to the deployment of a new version of an application.

Downtime refers to the unavailability of servers when the new version of an app is installed to replace the old one. The idea of Blue/Green deployment is to deploy the new version of the app in a separate place where you can test it until you decide to switch to make the new version the main one.

classicd

In this article, we will learn how to set up Blue-Green deployment of a Spring boot application. We will use Nginx as the main webserver to redirect incoming requests to our apps.

Setting up the server

In this tutorial, we will assume that you have a server and working Spring boot application that you can deploy on it.

On the server, go to your home and create two folders: blue and green. Then we will need two symbolic links available and testing. These links will alternatively point to either the blue or the green folder. For example, if available points to green then testing point to blue.


mkdir blue
mkdir green
ln -s ./green ./available
ln -s ./blue ./testing

Each folder will contain its own Spring application and Nginx configuration. At some point during the deployment, both apps will be running at the same time (on different ports though) and to swap from the blue app to the green one we will only need to change the Nginx configuration to either the green one or the blue one.

spring

Nginx Configurations

Let’s say we have the domain “springsite.com”. The green Nginx configuration will redirect all calls to springsite.com/api/ to the green app on the 8080 port and all calls to springsite.com/api-test/ to the blue app on the 8090 port.

Let’s create these configuration files. Use your favorite command-line editor to add the following content.


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/*;
}

The structure of the files should look like the one below:


--root
 |--- blue
      |--- nginx.conf.blue
      |--- app-V2.jar
 |--- green
      |--- nginx.conf.green
      |--- app-V1.jar
 |--- available -> ./green
 |--- testing -> ./blue

Let’s say we want to deploy a new version to the blue container, we can test it while the previous version is still available. Once we are happy with the new version we just need to swap the links!

Create a new file called swap.sh in the folder containing both blue and green folders:


touch swap.sh
chmod +x swap.sh

Add this content to the file:


#!/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

At this point, we can launch 2 Spring applications on the ports 8090 and 8080 and swap them by running sudo ./swap.sh .

Deployment

Thanks to the symbolic links, we know that the main app is always pointed by available and that the testing app is pointed by testing . Hence, we should always deploy the new version of the app in the testing folder using the symbolic link. Assuming we just packaged the app we can upload it with scp


scp -r -i ~/.ssh/MyKeyPair.pem  <package name.jar> <user>@<ip>:spring/testing

Going further

Setting up Blue-Green deployment on your server will allow you to reduce downtime significantly. This tutorial explained how to deploy new versions of your application based on a single physical server. This principle can be adapted with several physical servers and a load-balancer. However, this would require having twice as many production environments than needed. For very large infrastructure, this is either not possible or extremely costly.

this leads us to the following question: How do big companies manage to release new versions of their applications without downtime? Think of Google or Facebook, which are always available!

Deploying these apps with Blue-Green deployment is not realistic because of the gigantic number of servers needed. Application updates are done progressively by taking out servers, updating them and putting them back in production. Moreover, new versions are progressively released: at the beginning, only a small fraction of the servers will run the new version. Then, if no problems or bugs are detected, a larger number of servers will run the new code. At this point, important metrics about CPU, memory, and query performances are evaluated. If everything is successful then the release is completed and every server around the world will run the new version of the software.

Conclusion

I hope you now understand how to overcome downtime issues thanks to Blue-Green deployment. You should now be able to set up a basic Blue-Green deployment of your Spring application with an NGINX webserver.

As you may have noticed, when we use this solution both old and current versions of your apps run at the same time and are both connected to the database. This can lead to unexpected issues when there is a change in the database structure. This great article https://spring.io/blog/2016/05/31/zero-downtime-deployment-with-a-database shows how to handle this kind of situation.

One last thing which might interest you it that both AWS and Google Cloud Compute offer services to perform Blue-Green deployment out of the box!

Bibliography