What Is Blue-Green Deployment?

Blue-green deployment is a technique that enables continuous delivery to production with reduced downtime and risk. It achieves this by running two identical production environments called Blue and Green. Let's assume, Green is the existing live instance and Blue is the new version of the application. At any time, only one of the environments is live, with the live environment serving all production traffic.
Image title

What Are The Benefits?

  • It helps to reduce the downtime and even reduces it to zero depending on the application design and deployment approach.
  • It gives a rapid way of rollback of the application in case of production issue.
  • It helps to build confidence to business users as testing of new version can be done in Production in isolation before rollout.

Complexity Added By Cloud-Native Applications

Blue-Green deployment is simple when you have one instance of an application running. But with a cloud-native architecture, more and more instances are being created for each application to achieve high availability, resiliency, and distributed architecture. This adds the complexity of implementing the Blue-Green deployment without an outage. Let's understand the several use cases and see how to resolve those complexities.  
Image title

Common Use Cases and Solutions

 Applications which have a Blue version that can run along with a Green version without business disruption is the most simple use case. While instances of the Blue version are being introduced, Green can slowly be offloaded and shut down eventually. This will not have any impact on the Business application as both versions can run in parallel. No outage or wrong behavior will be observed.
Applications which have a Blue version that is not compatible with Green version is a bit complicated as both version cannot run together so we cannot introduce Blue instances one by one while Green instances being offloaded in parallel. To resolve this:            
  1. All the Blue instances have to be up and running while Router is still pointing to Green instances.
  2. Once all Blue instances are up then Router configuration to be changed to point it to Blue instances.
  3. It would cause a momentary outage as it may take time for Router to register with all the Blue instances and do load balancing as well.
Applications which have DB changes while moving from Green to Blue version is one of the complex scenarios where the Blue version will have some DB changes as well. The reason is if you apply the DB changes while Green is running it may break the existing application and outage will be caused.
Also, if there is a Production issue once Blue version is installed, rollback time will be increased and will lead to further outage to recover.
 The best approach to solve this issue:
  1. First, separate the DB changes from application changes.
  2. Second, All DB schema changes has to be scripted.
  3. Third, the script has to be refactored in such way that it supports both Green and Blue version of application.
  4. Apply those changes before deploying the Blue version. Test if Green is working fine so that we have one intermediate rollback point.
  5. Now apply Blue version change. If everything works fine, remove the support of db changes for Green version.
Applications which have transactions running on Green application while Blue is introduced is another complex use case. What happens while the user is in middle of a transaction and you switch him from Green to Blue instance? It may behave weirdly if not handled properly. To resolve this:
  1. Either handle the transaction at the application level in such a way that Blue becomes backup of the Green and any transaction which user is running can be handled by new instance without disruption.
  2. Or, make your application as read-only while you are switching from Green to Blue instances. In that way, your application will be up for certain users to view information and after deployment can be opened for all users. This option will flush out maximum of the issues may happen due to switching.
Now, if you look at all the practical scenarios, you will understand that depending on the deployment approach for Blue-Green, you may or may not have downtime. But using above solutions, you can minimize the downtime and increase the availability for your applications.
Now, let's talk about how some of the Cloud Platforms helps you implement the Blue-Green deployment.

Implementation for PCF and AWS

PCF Blue-Green Approaches

Manual Approach

PCF routes request to the application instances through its router component. When any application is pushed to PCF, it creates a router URL which is mapped to the application instance running.
Assuming a Green application is already running.
First, the FrCF Router will be mapped with the Green application e.g. sample.example.com. Here "sample" is hostname and "example.com" is a domain name.
Now push the Blue app with a different hostname. For example:                                                    
 cf push -n sample-temp

It will create the route url sample-temp.example.com
Now map the original route to Blue application. It will now do load balancing of the requests to both Green and Blue application
cf map-route Blue example.com -n sample
This will have sample.example.com pointing to both Green and Blue.
Next, un-map the route from Green application. This will stop sending requests to Green application.
The last step is to remove the temporary route mapping to Blue application. Also, the Green application be deleted as well.      
cf unmap-route Blue example.com -n sample-temp
cf delete Green

Automated Approach

CF community provides a plugin which automates the above manual process. The plugin takes care of the following steps packaged into one command:
  • Pushes the current version of the app with a new name
  • Optionally runs smoke tests against the newly pushed app to verify the deployment
    • If smoke the tests fail, the newly pushed app gets marked as failed and left around for investigation.
    • If smoke tests pass, remaps routes from the currently live app to the newly deployed app.
  • Cleans up versions of the app no longer in use
//Install plugin
cf add-plugin-repo CF-Community https://plugins.cloudfoundry.org
cf install-plugin blue-green-deploy -r CF-Community
//Run Plugin
cf blue-green-deploy app_name
//Deploy with optional smoke tests
cf blue-green-deploy app_name --smoke-test <path to test script>
//Deploy with specific manifest file
cf blue-green-deploy app_name -f <path to manifest>
//Deploy with a hard clean-up of the 'blue' (original) app
cf blue-green-deploy app_name --delete-old-apps

AWS Blue-Green Approaches

Use Case 1 - Application Has One EC2 Instance with Elastic IP address

In this case, Elastic IPs are the simplest way to implement the blue-green.
  • Launch a new EC2 instance, configure it, deploy the Blue version of your system, and test it.
  • When it is ready for production, reassign the Elastic IP from the Green instance to the Blue one. The switch will be transparent to the users and traffic will be redirected almost immediately to the new instance.

Use Case 2 - Application Having Multiple EC2 Instances and Running Using Auto Scaling Group Along with ALB.

Auto Scaling Group helps to configure scaling out and down of the EC2 instances. It also can be associate with ALB which helps to register and de-register the EC2 instances with ALB.
  1. Let's assume that there is already a Launch Configuration done for Green version of application instances and registered with ALB.
  2. Create a Launch Configuration for Blue version. Create the Auto Scaling Group and attach it with ALB serving the Blue Instances. 
  3. Once Registration is completed of EC2 instances with ALB, ALB will load balance the requests to go to both Green and Blue version.
  4. Now, Change the configuration for Green version marking desired number of instances to zero. This will shut down all the Green instances.
  5. Delete the Green Auto scaling group and launch configuration.
Note: Please note that in this approach, there will be time duration when requests will be handled by both Green and Blue instances. So, this can be applied only when both are compatible to each other.

Use Case 3 - Application Running Behind Route53

Most applications would configure Route53 to have a meaningful short name of the URL as ALB would be generally a long URL. So now, we can implement the Blue Green deployment outside AWS by changing the CNAME records in DNS.
  1. Create a Blue environment. It can be single EC2 instance or ALB. 
  2. Update the resource record set to point the domain to the Blue instance or the Blue ALB.
  3. Route53 has an AWS-specific extension to DNS that integrates with the other AWS services, and is cheaper too -- alias resource record sets.  This can be used for pointing to ALB as they point to a specific AWS resource: a CloudFront distribution, an ELB, an S3 bucket serving a static website, or another Route53 resource record set in the same hosted zone.
  4. Route53 also does have a Weighted Round Robin. To use it, it needs to be associated with multiple answers for the same domain/sub-domain and assign a weight between 0-255 to each entry. When processing a DNS query, Route53 will select one answer using a probability calculated based on those weights. To perform the Blue-Green switch it needs to have an existing entry for the current “Green” environment with weight 255 and a new entry for the “Blue” environment with weight 0. Then, simply swap those weights to redirect traffic from Green to Blue.
Note: Please note, DNS record changes take time to reflect and we don't have any control when user will perceive it.
I know, AWS has a lot of other architectures using ECS, Lambda, etc. And there will be a different strategy to handle the Blue-Green deployment. There are other cloud platforms as well which do have one or other strategy to implement the Blue-Green deployment. I may talk about them once I get a chance to do some hands-on with those features.
Please do share your thoughts through comments if you find any other way of implementing this in PCF and AWS.
Rajesh Bhojwani November 01, 2018
Read more ...

Background

Angular has become the primary choice for developers to build a web and SPA application. However, most of the tutorials available talk about running the Angular app using "ng serve." "ng serve" is a command provided by the AngularJS CLI. It will  serve a project that is 'Angular CLI aware,' i.e. a project that has been created using the Angular CLI,  particularly using:  ng new app-name 
This is useful when you are developing the app on your system and want to see the changes reflected in browser while coding. However, once the application is ready to deploy, you'll need to host it on a web server like Node.js or NGINX. PCF also supports buildback for nodejs and nginx.
Let's add a little complexity here. With Angular 6, we'll be using TypeScript files for developing code. If you don't know, TypeScript is a language created by Microsoft, which gets compiled into JavaScript. As the name itself suggests, TypeScript brings type checking capabilities into JavaScript.
Once you have typscript (.ts) files, they need to be compiled to .js files and are supposed to be deployed on a web server to run. 
Let's talk about how to deploy on Node.js first and then NGINX in detail.

Node.js Server

Step 1: Run the 'ng build' Command

The Angular CLI has a command ng build. This command builds the artificat (compiles .ts files and converts them to .js files) and stores all files including index.html in the  /dist  directory.

Step 2: Create a server.js File

To start a Node.js server, we need a JavaScript file which will have Node.js code to listen the port 8080 and route each request to the /index.html residing in /dist directory created by Step 1. See the sample code below:
//server.js file
var express = require('express');
var app = express(); 
const path = require('path');
var rootPath = path.normalize(__dirname + '/dist/');
var port = process.env.PORT || 8080; 
app.use(express.static(rootPath)); 
app.get('*', (req, res) => {
  res.sendFile(rootPath + '/index.html');
});
app.listen(port);
console.log("App listening on port " + port);

Step 3: Run the 'npm start' Command

To start the application, a server.js file has to be loaded by the Node.js server. The npm start command is used for the same purpose. This command will check what script is configured in package.json and run those commands as per the script. In this case, the script command is:
 "start": "npm install && node server.js" 
//package.json file
{
  "name": "angular-ui-app",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "npm install && node server.js",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^5.2.0",
    "@angular/common": "^5.2.0",
    "@angular/compiler": "^5.2.0",
    "@angular/core": "^5.2.0",
    "@angular/forms": "^5.2.0",
    "@angular/http": "^5.2.0",
    "@angular/platform-browser": "^5.2.0",
    "@angular/platform-browser-dynamic": "^5.2.0",
    "@angular/router": "^5.2.0",
    "angular-pdf": "^2.0.0",
    "core-js": "^2.4.1",
    "file-saver": "^1.3.8",
    "rxjs": "^5.5.6",
    "zone.js": "^0.8.19"
  },
  "devDependencies": {
    "@angular/cli": "^6.0.8",
    "@angular/compiler-cli": "^5.2.0",
    "@angular/language-service": "^5.2.0",
    "@types/jasmine": "~2.8.3",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "^4.0.1",
    "jasmine-core": "~2.8.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1",
    "typescript": "~2.5.3",
    "@angular-devkit/build-angular": "~0.6.8"
  }
}
Once these three steps are completed, the server.js application will be initialized and route each request hitting the following URL: https://<ip>:8080 to /dist/index.html.
This way, our Angular application can be hosted on a Node.js server.

NGINX Server

Step 1: Download the NGINX Server and Start it

You can download the nginx server from the below site:

Step 2: Configure the nginx.conf File

We need to ensure that the root field points to the /dist folder. It will pick up the index.html file. Restart the NGINX server to reflect the changes.
//nginx.conf
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    root /var/www/frontend/dist;
    try_files $uri $uri/ index.html;
    error_log /var/log/nginx/angular4_error.log;
    access_log /var/log/nginx/angular4_access.log;
}

Step 3: Build the Angular Application

Use the ng build --prod command and it will compile and build the artificats in the /dist folder.

Step 4: Run the Application

Hit the application with the NGINX domain name or public IP address. 
In this way, an Angular application can be hosted on an NGINX server.
So both the Node.js and NGINX setup discusseed above work in PCF the same way. There is no extra configuration needed. 
That's all for this post. Please do let me know your views through the comments.
Rajesh Bhojwani November 01, 2018
Read more ...