Automating with Ansible: Building a VPC

Networking on AWS made easy!

Tom Wright
5 min readFeb 8, 2018

In this article we’re looking at using Ansible for automating the configuration of cloud networking in an AWS VPC. If you’re not sure what you’re doing here, maybe peek at the introduction. The scope of the automation we will build will handily configure all of the following:

  • VPC and Subnets: create the VPC itself, along with public and private subnets across three availability zones: a, b, and c
  • Internet Gateway: configure a gateway for our public resources to access the internet
  • NAT Gateway: configure a NAT gateway to allow our private resources to access the public internet
  • VPC Route Tables: define the routing to make our subnets public or private (route public traffic using either the public or NAT gateway)
  • Security Groups: define some useful security groups for limiting communication only within the VPC, and/or to allow SSH or HTTP/S traffic from the public internet
  • Private DNS: create a private Route53 hosted zone for resolution of resources within the VPC

Take note this article is not here to explain how these AWS resources work, or even how to configure them, but specifically how to automate their configuration with Ansible. Let’s get started!

VPC and Subnets

Configure hosts and group vars

We’re going to start by defining an Ansible host for our VPC. This host will act as a “logical host” (as in it is not an actual host that we can connect to to run commands) that will represent all the VPC configuration. So in our inventory we define a vpc group with a single vpc.ansibled (the name is just a name, nothing special) host, and then place this vpc group into a high-level “project” group called project.ansibled.

Now let’s define the variables we need when configuring the VPC and subnets. Globally, in group_vars/all.yml, we just want to define that by default we don’t want to attempt an SSH connection to our hosts, and just run Ansible tasks locally (almost all of our automation will be AWS cloud and serverless):

General global variables for our universal “all” group

Our project.ansibled group is going to do some heavy lifting and supply high-level definitions such as the VPC name and our AWS credentials. All our hosts we will place in this group so that this configuration is available when Ansible is executing. So in group_vars/project.ansibled.yml:

Next we define some particulars of our VPC itself: the IP address block for the VPC, security groups, and subnet configuration. These we will define as host vars of our vpc.ansibled host, because we want them to be specific to this host, and other hosts (when we get around to them), won’t need to reference these definitions themselves.

Specific configuration for our “vpc.ansibled” logical host

Protect sensitive information with Ansible Vault

You might be wondering why the aws_access_key and aws_secret_key vars that store our IAM credentials look like that. Given that we’re going to commit our automation to a repository, we need to make sure this sensitive information isn’t visible as plain-text — enter Ansible Vault, a feature of Ansible that allows us to encrypt files and strings, making them safe for version control.

To generate these encrypted strings that we can decrypt at runtime, first we write an encryption password to a (git-ignored, or preferably not even in the repo directory) file:

echo "my_vault_pass" > ~/ansibled.vault

Second, feed our plain-text value to the ansible-vault program, specifying our password file, and out pops an encrypted string that we can safely store in our Ansible vars!

You get an image because the Vault string rendered horribly in a code block

Later, when we want to execute our automation, we simply specify our vault password file, or specify that Ansible should prompt us for it:

# prompt the user for the Vault password
ansible-playbook -i ansibled.inventory vpc.yml --ask-vault-pass
# read the Vault password from file
ansible-playbook -i ansibled.inventory vpc.yml --vault-password-file ~/ansibled.vault

Tasks

Our Ansible tasks (the “code”) will all live under a tasks/ directory, and under a tasks/vpc/ subdirectory for all our tasks related to creating our VPC. Our playbook will then dynamically include these task lists at runtime, allowing us to organise our tasks to create modular blocks of “code”.

The first stage of our VPC automation will concern itself with the following steps:

  • create the VPC
  • create the VPC subnets
  • create the VPC security groups
  • create the Route53 private zone for the VPC

With our main VPC components in place we can now configure the routing and gateways for our VPC:

  • create internet gateway
  • create NAT gateway (and update VPC DNS)
  • create route table for private subnets
  • create route table for public subnets

Playbook

Now that we’ve written some tasks to build our VPC, we just need to tie it together with a playbook. We simply target the vpc group, populate our environment with our AWS credential details, and use the include_tasks directive to pull in our VPC tasks. Easy!

Get your facts straight

The last piece of the puzzle is to provide an easy way for other parts of our automation to access and utilise the details of the VPC infrastructure we’ve just put up. For example, we will want to able to easily lookup the IDs of our VPC subnets by the human-readable names we assigned them (private-a, public-b, etc.), just like we did when setting up our route tables above. So, we create a “facts” task list in tasks/vpc/facts.yml:

This “facts” task list for our VPC can now be included by other playbooks to peek at AWS and discover some important information about our VPC!

And… Action!

Now to automatically build our VPC, simply execute Ansible:

# prompt the user for the Vault password
ansible-playbook -i ansibled.inventory vpc.yml --ask-vault-pass
# read the Vault password from file
ansible-playbook -i ansibled.inventory vpc.yml --vault-password-file ansibled.vault

Finally, grab a coffee while that runs :) Happy automating!

I love automation. This series of articles, Automation with Ansible, is the documenting of some of the Ansible bits ‘n bobs that make my life easier when managing software infrastructure.

Check it all out on GitHub, or the other entries in the series:

--

--

Tom Wright

I like automation, productivity, team process, and watching the thing actually get out the door. @tomwwright on GitHub