Skip to content

Latest commit

 

History

History
146 lines (107 loc) · 8.45 KB

continuous-deployment-of-cloudformation.md

File metadata and controls

146 lines (107 loc) · 8.45 KB

Continuous Deployment of CloudFormation

Background

What is Continuous Delivery?

Continuous Deployment (CD) is a software release process where verified changes to a codebase are deployed immediately, and autonomously to a production environment. The main benefit of CD is the removal of human error, as the platform will perform the same steps over and over.

At the Guardian, Riff-Raff is our standard CD platform. Riff-Raff is configured with a riff-raff.yaml file.

Tip

  • Use this tool to validate your riff-raff.yaml configuration file.
  • If using @guardian/cdk, you can auto-generate the riff-raff.yaml file.

What is CloudFormation?

CloudFormation is a service that allows you to define your AWS infrastructure as code. It has various benefits, including changes being made via Pull Requests, confidence in changes to PROD, as they can be tested in CODE beforehand, documentation of non-obvious decisions.

What are the benefits of deploying CloudFormation w/Riff-Raff?

Riff-Raff offers some specific benefits when deploying CloudFormation templates.

Application of tags

When deploying CloudFormation stacks, Riff-Raff will apply the Stack, Stage, and App tags (source), and the gu:repo and gu:build-tool tags (source) to the CloudFormation stack.

A feature of CloudFormation is that (taggable) resources inherit the tags of their parent stack. A change was made to enable the AWS Resource Tagging Standard, which helps DevX understand tag usage. Therefore, using Riff-Raff to deploy CloudFormation is the easiest way to meet the tagging obligation.

For example, let’s say we have this template creating an S3 bucket:

Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: my-bucket

The bucket does not have any tags set. When deployed via Riff-Raff, the S3 bucket will have the Stack, Stage, App, gu:repo, and gu:build-tool tags “for free”. If tags were explicitly declared on the resource, the parent’s tags will be additive to them.

Protection of stateful resources

We'll define a stateful resource as one that will cause downtime for users of the application if accidentally deleted. This may include, for example:

  • Databases
  • Messaging streams (Kinesis, SNS, SQS)
  • S3 Buckets

Riff-Raff has two modes of deploying CloudFormation stacks. By default, MostlyHarmless is used. In this mode, the stack’s policy is set such that stateful resources are prevented from being deleted. This helps protect against unintentional changes that could cause service interruption. The Dangerous mode is the opposite - all actions are enabled.

Automatic rotation of AMIs

For our EC2 based applications, there are various requirements for the underlying instances, including regular rotation. This can be done when deploying CloudFormation stacks with Riff-Raff via the amiParametersToTags configuration.

It’s worth noting a scheduled deployment needs to be created and rotation can also be achieved with the ami-cloudformation-parameter type.

History / Ability to rollback to an arbitrary version

This isn’t exclusive to CloudFormation deployments. Riff-Raff keeps a history of deployments, with information such as the date, the commit, the status, etc.

It is also possible to rollback to a previous version, either by triggering a deployment with an older build number, or redeploying a previous deployment.

How can I tell if a CloudFormation stack is deployed w/Riff-Raff?

As mentioned above, Riff-Raff applies some tags to the CloudFormation stack. Riff-Raff also assumes an IAM role when applying changes. Therefore, searching for CloudFormation stacks without the gu:repo tag, or this role, is a good approximation.

How do I start deploying a CloudFormation stack w/Riff-Raff?

The best code infrastructure is the code infrastructure that doesn’t exist! That is, before starting this work, it might be worth checking if the CloudFormation stack is still needed. If it isn’t, delete it.

Identify the GitHub repository

The first place to start is to locate the repository where the CloudFormation template resides. This might be the application’s repository, or a “platform” repository. If you’re unable to immediately identify the repository, an available option is to identify a unique string in the stack’s template, and perform a GitHub search for that string.

Tip

See https://github.com/guardian/editorial-tools-platform for some examples of deploying CloudFormation templates within a "platform" repository.

Create the riff-raff.yaml file

With the GitHub repository identified we create, or update, a riff-raff.yaml file.

In the most minimal form, the file would look similar to this:

# This application has a CODE and PROD stage
allowedStages:
  - CODE
  - PROD

# This application is deployed in eu-west-1
regions:
  - eu-west-1

# The stack determines the AWS account this application deploys into.
# See https://riffraff.gutools.co.uk/deployinfo/data?key=credentials%3Aaws-cfn-role
stacks:
  - deploy

deployments:
  cloudformation:
    type: cloud-formation
    app: my-application

    # See https://riffraff.gutools.co.uk/docs/magenta-lib/types#cloudformation for all configuration options
    parameters:
      templatePath: my-template.yaml

      # Discover the CFN stack via the Stack, Stage, App tags...
      cloudFormationStackByTags: true

      # ...if it can't be found, do NOT create a new CFN stack
      createStackIfAbsent: false

Upload the files to Riff-Raff

With the riff-raff.yaml file created, we can use the GitHub Action guardian/actions-riff-raff to upload the riff-raff.yaml file, and the CloudFormation template file(s) for deployment with Riff-Raff.

Check Riff-Raff targets the desired Cloudformation stack

With your project configuration uploaded to Riff-Raff, we can preview the deployment to understand which Cloudformation stack it’ll use.

There are three possible outcomes:

  1. When using cloudFormationStackByTags: true, the preview will show something similar to this:

    cloudFormationStackByTags

  2. When using cloudFormationStackName, the preview will show something similar to this:

    cloudFormationStackName

  3. Riff-Raff will error at the preview stage if it cannot find a CloudFormation stack at all.

Perform a deployment

We’ve now confirmed Riff-Raff will impact the correct CloudFormation stack, let’s deploy!

Up until this point, we’ve not made any changes to the template. You might expect this first deployment to be a no-op, however, as described above, Riff-Raff will apply some tags to the CloudFormation stack. Therefore, the changes in this first deployment will be the application of these tags.