Blue-Green Deployment with CloudFoundry

July 31, 2016 4 mins read

Blue-Green Deployment with CloudFoundry

Blue-green deployments are a powerful technique to achieve zero-downtime deployments. With the CloudFoundry CLI, it is super easy to execute a blue-green deployment - even from a CI server. In a nutshell, a blue-green deployment spins up a whole new production environment with the new application version and once that is done, switches over the traffic from the old version to the new version. If you are unfamiliar with blue-green deployments be sure to read this article by Martin Fowler.

Deployment Configuration

The blue-green deployment I describe here has been setup in Codeship CI to continuously deploy updates of an application to CloudFoundry. It requires certain environment variables to be configured, namely:

  • CF_API: URL to the CloudFoundry API, e.g. api.run.pivotal.io
  • CF_USER: the username to authenticate with
  • CF_PASSWORD: the password to authenticate with
  • CF_ORG: the organization to deploy to
  • CF_SPACE: the space to deploy to
  • CF_APPLICATION: the name of the application to deploy
  • CF_DOMAIN: the domain used to serve the application
  • CF_HOSTNAME: the hostname used to serve the application (optional)

The following sections describe the script in detail, if you are familiar with the CF CLI commands, you may see the full script at the end of this blog post.

Authenticate

It is necessary to authenticate with the CloudFoundry API from the CLI. Additionally, it is required to target the organization and space to which the application will be deployed:

cf api "${CF_API}"
cf auth "${CF_USER}" "${CF_PASSWORD}"
cf target -o "${CF_ORG}" -s "${CF_SPACE}"

It is recommended to add a new “deployment” user to your CloudFoundry space, as the credentials must be specified on the CI server.

Push Green

We can leverage the cf push command to push the new version to CloudFoundry. Make sure to set common deployment options for your app in the mainfest.yml file, such as the amount of memory to be used by each instance.

Executing cf push without further arguments will spin up a single instance of your application. If you leverage the auto-scaling capabilities of CloudFoundry, the number of instances would be reset to a single instance on each fresh deploy. Switching over the traffic would not be a good idea, right? So lets determine the current number of instances in use with the CloudFoundry CLI and push the green version with the same number of instances.

INSTANCES=$(cf app $CF_APPLICATION|grep ^instances|awk '{print $2}'|awk -F/ '{print $2}')
cf push "${CF_APPLICATION}-green" -i ${INSTANCES}

Next, we’ll need to map the existing route to the app to start handling traffic over to the fresh green version. Depending on whether the app runs with a hostname or not, we’ll need to execute different commands. Right after the route was added to the green version we can safely remove the route from the old version of the application. Users will then immediately have the new version of your application. Make sure to safely persist your sessions in a persistent service, as otherwise your users will lose their current session during the deployment.

if [ -z "CF_HOSTNAME" ]; then
    cf map-route "${CF_APPLICATION}-green" ${CF_DOMAIN}
    cf unmap-route "${CF_APPLICATION}" ${CF_DOMAIN}
else
    cf map-route "${CF_APPLICATION}-green" ${CF_DOMAIN} -n "${CF_HOSTNAME}"
    cf unmap-route "${CF_APPLICATION}" ${CF_DOMAIN} -n "${CF_HOSTNAME}"
fi

Remove Blue

As we now do not need the blue (i.e. old) version of the application anymore, we can safely remove the old application. After the application was removed, we’ll rename the ${CF_APPLICATION}-green application to ${CF_APPLICATION} in order to make sure this script updates the application properly on the next run.

cf delete "${CF_APPLICATION}" -f
cf rename "${CF_APPLICATION}-green" "${CF_APPLICATION}"

Ideally, you include some monitoring and smoke tests to make sure the new version handles the traffic correctly before removing the old version. That allows you to rollback in case of failure.

The Blue-Green Deployment Script for CloudFoundry

Merging the pieces, here is the full deployment script:

# authenticate
cf api "${CF_API}"
cf auth "${CF_USER}" "${CF_PASSWORD}"
cf target -o "${CF_ORG}" -s "${CF_SPACE}"

# push green
INSTANCES=$(cf app $CF_APPLICATION|grep ^instances|awk '{print $2}'|awk -F/ '{print $2}')
cf push "${CF_APPLICATION}-green" -i ${INSTANCES}
if [ -z "CF_HOSTNAME" ]; then
    cf map-route "${CF_APPLICATION}-green" ${CF_DOMAIN}
    cf unmap-route "${CF_APPLICATION}" ${CF_DOMAIN}
else
    cf map-route "${CF_APPLICATION}-green" ${CF_DOMAIN} -n "${CF_HOSTNAME}"
    cf unmap-route "${CF_APPLICATION}" ${CF_DOMAIN} -n "${CF_HOSTNAME}"
fi

# remove blue
cf delete "${CF_APPLICATION}" -f
cf rename "${CF_APPLICATION}-green" "${CF_APPLICATION}"

Note: When using Codeship to setup the pipeline make sure to use the cf6 command instead of cf. See their documentation for more information.

Use this script as a baseline to define your own blue-green deployment pipeline for zero-downtime deployments on CloudFoundry.

Comments

👋 I'd love to hear your opinion and experiences. Share your thoughts with a comment below!

comments powered by Disqus