Deploying to AWS with the Serverless Framework is a snap. Deploying to AWS with Terraform is not quite as easy as with Serverless, but it's pretty straightforward. Deploying infrastructure that's composed of both Terraform & Serverless configurations? That's crazy talk. Bash scripts, branches, and CLI output parsing will be needed to manage that mess. Right? Not quite...
Enter runway
Runway is...
A lightweight wrapper around linting (e.g. yamllint) & infrastructure deployment tools (e.g. CloudFormation, Terraform, Serverless) to ease management of per-environment configs & deployment.
In short, runway is good at making deployments consistent between the various Infrastructure-as-Code tools.
Runway is a layer of abstraction between your pipeline and configurations therein. Those configurations can be implemented in Terraform, Serverless, Stacker (CloudFormation), or cdk. Runway knows how to inject variables into each framework, configure backends (in the case of terraform), specify stages/workspaces/environments, etc.
For the purposes of this post, I'm just going to focus on Terraform and Serverless.
A simple example
This simple runway.yml file defines a deployment of a Serverless app and a Terraform configuration (in that order). The deployment will occur in us-east-1, and the dev and prod environments are enabled (but have no specific configuration associated with either).
---
deployments:
- modules:
- myapp.sls # directory w/ Serverless stack
- infrastructure.terraform # directory w/ terraform configuration
regions:
- us-east-1
environments:
dev: true
prod: true
To deploy this to prod, you could run DEPLOY_ENVIRONMENT=prod && runway deploy. You can also use Git branch names or folder names to specify the environment.
A little more real-world
This slightly more complicated example shows how you can specify unique variables & values into each module.
---
deployments:
- modules:
- path: myapp.sls
environments:
dev:
api_gateway_custom_domain_name: dev.my-api.com
prod:
api_gateway_custom_domain_name: my-api.com
- path: infrastructure.terraform
environments:
dev:
golden_image_ami: ami-zyx123456
prod:
golden_image_ami: ami-zyx654321
regions:
- us-east-1
Here I'm providing new values in the environments property for each module. These variables will be passed into the module deployments via syntax native to each deployment tool. This makes it very easy to build the multi-stack configuration in one place and maintaining native variable reference syntax within each configuration.
SSM: cross-configuration glue
For values that needs to cross configurations, my team has made heavy use of AWS Systems Manager Parameter Store parameters. We've found that this is the easiest construct (to use in AWS) that all of the infrastructure-as-code tools that we use can natively understand.
Terraform
You can use an aws_ssm_parameter
data source to import an SSM parameter set somewhere else.
data "aws_ssm_parameter" "foo" {
name = "/foo/${terraform.workspace}/value"
}
To create an SSM parameter, add an aws_ssm_parameter
resource to the configuration.
resource "aws_ssm_parameter" "foo" {
name = "/foo/${terraform.workspace}/lb-access-key-secret"
type = "SecureString"
value = aws_iam_access_key.lb.secret
}
Serverless
Referencing SSM parameters from a Serverless stack is a little more straightforward. You can use their native syntax to reference variables stored in SSM like this...
${ssm:/foo/${self:provider.stage}/value}
To create an SSM parameter, add a Cloudformation resource to the Resources
section of the template.
resources:
Resources:
foo:
Type: AWS::SSM::Parameter
Properties:
Name: "/foo/${self:provider.stage}/lb-access-key-secret"
Type: SecureString
Value: "${self:custom.secret_value}"
Summary
Runway is a great option to use if:
- You want a common CLI to use for multiple Infrastructure-as-Code tools
- You have multiple configurations and want to deploy them in one go
- You'd like to standardize the deploy jobs of your CI pipeline
It has certainly helped the productivity of my team in many ways. I could talk about it more than I have, but I'd love to hear your feedback! What would you like to hear more about? What could use some more explanation?
Top comments (0)