It’s a common practice to create a VPC to provide logically isolated section of the cloud and the freedom of creating IP address range, subnets, route tables and network gateways. It brings flexibility of access control and multiple layers of security. But it’s a non-trivial task to create the VPC environment using the AWS Web Interface, you have to click here and there, jumping from page to page, and it’s not replayable and portable, e.g. if you want to replicate one setup, or you want to have the same configuration in another AWS account, you gotta have to re-do it all over again.
AWS has opened APIs and provided a CLI tool to manage all its services, we can write shell scripts to programatically do the process and make it replayable. But there’re a lot of other tools developed to make life even easier, and one of the best is Terraform.
Terraform treats the provisioning of infrastructure as programming. To create the resources, you write scripts, validate them and use them to build, change, and version the infrastructure. Terraform supports existing popular service providers such as AWS, GCE, Open Stack, Digital Ocean and etc. This post shows you how to provision a VPC environment using Terraform on AWS.
Getting Started
Let’s getting started, first of all, download Terraform and install. This post assumes that you’re using MacOS.
terraform help usage: terraform [--version] [--help] <command> [<args>]
Available commands are: apply Builds or changes infrastructure destroy Destroy Terraform-managed infrastructure fmt Rewrites config files to canonical format get Download and install modules for the configuration graph Create a visual graph of Terraform resources init Initializes Terraform configuration from a module output Read an output from a state file plan Generate and show an execution plan push Upload this Terraform module to Atlas to run refresh Update local state file against real resources remote Configure remote state storage show Inspect Terraform state or plan taint Manually mark a resource for recreation untaint Manually unmark a resource as tainted validate Validates the Terraform files version Prints the Terraform version
For security reason, you should not explicitly put your AWS credentials in your Terraform script, instead you can let Terraform read from your aws configuration located at “~/.aws/credentials”. You can manually create the file and put in your credentials, or you can use aws-cli to set it up for you. To install aws-cli, make sure that you have python and pip installed and then run the following command:
1
sudo pip install aws-cli
Now run the following command and fill in your credentials to set up the aws profile:
1
aws configure --profile your_profile
And when this is done, you can find your credentials save at “~/.aws/credentials”
First of all, create a folder and name it as “terraform/aws”
1 2
mkdir -p terraform/aws cd terraform/aws
We’re going to take advantage of terraform’s module function, name the module “vpc” and we assume that “region” is a required parameter to pass to the module:
1 2 3 4 5 6 7 8 9 10
vi aws.tf ... provider "aws" { profile = "your_aws_profile" region = "${var.region}" } module "vpc" { source = "./vpc" region = "${var.region}" }
Now create the module folder and the code to create the vpc.
1 2
mkdir vpc vi vpc/main.tf
In the script, I will create the following resources:
One VPC
One public subnet with one route table associated, which routes to the internet gateway.
One Elastic IP address and one NAT gateway
One private subnet associated with one route table associated, which routes to the NAT gateway.
Before you run the script, you can actually run “terraform plan” to check whether the behaviour is intended, if everything is fine, then apply and create the resources:
1 2 3
terraform get terraform plan terraform apply
If it sucessfully runs, go to your AWS console and check, your VPC environment should be there already. Use “terraform show” to see the current state of terraform, and make some little changes to the script and use “terraform plan” to how terraform recognize the difference.