Working With Terraform For Managing AWS
- If you just started learning terraform I will recommend visiting this blog post
- The S3 Bucket and Random ID
- Environment setup:
mkdir -p ~/terraform/AWS/storage cd ~/terraform/AWS/storage
- Create main.tf:
vi main.tf
Content
main.tf
:#---------storage/main.tf--------- # Create a random id resource "random_id" "tf_bucket_id" { byte_length = 2 } # Create the bucket resource "aws_s3_bucket" "tf_code" { bucket = "${var.project_name}-${random_id.tf_bucket_id.dec}" acl = "private" force_destroy = true tags { Name = "tf_bucket" } }
- Create variables.tf:
vi variables.tf
Content
variables.tf
:#----storage/variables.tf---- variable "project_name" {}
- Create outputs.tf:
vi outputs.tf
content
outputs.tf
:#----storage/outputs.tf---- output "bucketname" { value = "${aws_s3_bucket.tf_code.id}" }
- Initialize Terraform:
terraform init
- Validate your files:
terraform validate
- Plan the deployment:
export AWS_ACCESS_KEY_ID="[ACCESS_KEY]" export AWS_SECRET_ACCESS_KEY="[SECRET_KEY]" export AWS_DEFAULT_REGION="us-east-1" terraform plan -out=tfplan -var project_name=la-terraform
- Deploy the S3 bucket:
terraform apply tfplan
- Destroy S3 bucket:
terraform destroy -auto-approve -var project_name=la-terraform
- Environment setup:
- VPC, IGW, and Route Tables
- Environment setup:
mkdir -p ~/terraform/AWS/networking cd ~/terraform/AWS/networking
- Touch the files:
touch {main.tf,variables.tf,outputs.tf,terraform.tfvars}
- Edit
main.tf
:vi main.tf
Content
main.tf
:#----networking/main.tf---- data "aws_availability_zones" "available" {} resource "aws_vpc" "tf_vpc" { cidr_block = "${var.vpc_cidr}" enable_dns_hostnames = true enable_dns_support = true tags { Name = "tf_vpc" } } resource "aws_internet_gateway" "tf_internet_gateway" { vpc_id = "${aws_vpc.tf_vpc.id}" tags { Name = "tf_igw" } } resource "aws_route_table" "tf_public_rt" { vpc_id = "${aws_vpc.tf_vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.tf_internet_gateway.id}" } tags { Name = "tf_public" } } resource "aws_default_route_table" "tf_private_rt" { default_route_table_id = "${aws_vpc.tf_vpc.default_route_table_id}" tags { Name = "tf_private" } } resource "aws_subnet" "tf_public_subnet" { count = 2 vpc_id = "${aws_vpc.tf_vpc.id}" cidr_block = "${var.public_cidrs[count.index]}" map_public_ip_on_launch = true availability_zone = "${data.aws_availability_zones.available.names[count.index]}" tags { Name = "tf_public_${count.index + 1}" } } resource "aws_route_table_association" "tf_public_assoc" { count = "${aws_subnet.tf_public_subnet.count}" subnet_id = "${aws_subnet.tf_public_subnet.*.id[count.index]}" route_table_id = "${aws_route_table.tf_public_rt.id}" } resource "aws_security_group" "tf_public_sg" { name = "tf_public_sg" description = "Used for access to the public instances" vpc_id = "${aws_vpc.tf_vpc.id}" #SSH ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["${var.accessip}"] } #HTTP ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["${var.accessip}"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
- Edit variables.tf:
vi variables.tf
Content
variables.tf
:#----networking/variables.tf---- variable "vpc_cidr" {} variable "public_cidrs" { type = "list" } variable "accessip" {}
- Edit outputs.tf:
vi outputs.tf
Content
outputs.tf
:#-----networking/outputs.tf---- output "public_subnets" { value = "${aws_subnet.tf_public_subnet.*.id}" } output "public_sg" { value = "${aws_security_group.tf_public_sg.id}" } output "subnet_ips" { value = "${aws_subnet.tf_public_subnet.*.cidr_block}" }
- terraform.tfvars:
vpc_cidr = "10.123.0.0/16" public_cidrs = [ "10.123.1.0/24", "10.123.2.0/24" ] accessip = "0.0.0.0/0"
- Initialize Terraform:
export AWS_ACCESS_KEY_ID="[ACCESS_KEY]" export AWS_SECRET_ACCESS_KEY="[SECRET_KEY]]" terraform init
- Validate code:
terraform validate
- Deploy Network:
terraform apply -auto-approve
- Destroy Network:
terraform destroy -auto-approve
- Delete terraform.tfvars:
rm terraform.tfvars
- Environment setup:
- AMI Data, Key Pair, and the File Function
- Environment setup:
mkdir -p ~/terraform/AWS/compute cd ~/terraform/AWS/compute
- Touch the files:
touch {main.tf,variables.tf,outputs.tf,userdata.tpl}
- Create a SSH key.
ssh-keygen
- Edit main.tf:
vi main.tf
Content
main.tf
:#-----compute/main.tf data "aws_ami" "server_ami" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["amzn-ami-hvm*-x86_64-gp2"] } } resource "aws_key_pair" "tf_auth" { key_name = "${var.key_name}" public_key = "${file(var.public_key_path)}" } data "template_file" "user-init" { count = 2 template = "${file("${path.module}/userdata.tpl")}" vars { firewall_subnets = "${element(var.subnet_ips, count.index)}" } } resource "aws_instance" "tf_server" { count = "${var.instance_count}" instance_type = "${var.instance_type}" ami = "${data.aws_ami.server_ami.id}" tags { Name = "tf_server-${count.index +1}" } key_name = "${aws_key_pair.tf_auth.id}" vpc_security_group_ids = ["${var.security_group}"] subnet_id = "${element(var.subnets, count.index)}" user_data = "${data.template_file.user-init.*.rendered[count.index]}" }
- Edit variables.tf:
vi variables.tf
Content variables.tf:
#----compute/variables.tf---- variable "key_name" {} variable "public_key_path" {}
- Edit userdata.tpl:
vi userdata.tpl
Content userdata.tpl
#!/bin/bash
yum install httpd -y
echo "Subnet for Firewall: ${firewall_subnets}" >> /var/www/html/index.html
service httpd start
chkconfig httpd on
- Initialize Terraform:
export AWS_ACCESS_KEY_ID="[ACCESS_KEY]" export AWS_SECRET_ACCESS_KEY="[SECRET_KEY]]" terraform init
- Validate changes:
terraform validate
- Plan the changes:
terraform plan -out=tfplan -var 'key_name=tfkey' -var 'public_key_path=/home/cloud_user/.ssh/id_rsa.pub'
- Apply the changes:
terraform apply -auto-approve
- Provide the values for key_name and public_key_path: key_name: tfkey public_key_path: /home/cloud_user/.ssh/id_rsa.pub
- Destroy environment:
terraform destroy -auto-approve
- Provide the values for key_name and public_key_path: key_name: tfkey public_key_path: /home/cloud_user/.ssh/id_rsa.pub
- Environment setup:
- The Root Module
- Change directory
cd ~/terraform/AWS
- Edit main.tf:
vi main.tf
Content
main.tf
:provider "aws" { region = "${var.aws_region}" } # Deploy Storage Resources module "storage" { source = "./storage" project_name = "${var.project_name}" } # Deploy Networking Resources module "networking" { source = "./networking" vpc_cidr = "${var.vpc_cidr}" public_cidrs = "${var.public_cidrs}" accessip = "${var.accessip}" } # Deploy Compute Resources module "compute" { source = "./compute" instance_count = "${var.instance_count}" key_name = "${var.key_name}" public_key_path = "${var.public_key_path}" instance_type = "${var.server_instance_type}" subnets = "${module.networking.public_subnets}" security_group = "${module.networking.public_sg}" subnet_ips = "${module.networking.subnet_ips}" }
- Edit variables.tf:
vi variables.tf
Content
variables.tf
:#----root/variables.tf----- variable "aws_region" {} #------ storage variables variable "project_name" {} #-------networking variables variable "vpc_cidr" {} variable "public_cidrs" { type = "list" } variable "accessip" {} #-------compute variables variable "key_name" {} variable "public_key_path" {} variable "server_instance_type" {} variable "instance_count" { default = 1 }
- Edit outputs.tf:
vi outputs.tf
Content
outputs.tf
:#----root/outputs.tf----- #----storage outputs------ output "Bucket Name" { value = "${module.storage.bucketname}" } #---Networking Outputs ----- output "Public Subnets" { value = "${join(", ", module.networking.public_subnets)}" } output "Subnet IPs" { value = "${join(", ", module.networking.subnet_ips)}" } output "Public Security Group" { value = "${module.networking.public_sg}" } #---Compute Outputs ------ output "Public Instance IDs" { value = "${module.compute.server_id}" } output "Public Instance IPs" { value = "${module.compute.server_ip}" }
- Edit terraform.tfvars:
vi terraform.tfvar
Content
terraform.tfvar
:aws_region = "us-west-1" project_name = "la-terraform" vpc_cidr = "10.123.0.0/16" public_cidrs = [ "10.123.1.0/24", "10.123.2.0/24" ] accessip = "0.0.0.0/0" key_name = "tf_key" public_key_path = "/home/cloud_user/.ssh/id_rsa.pub" server_instance_type = "t2.micro" instance_count = 2
- Initialize Terraform:
export AWS_ACCESS_KEY_ID="[ACCESS_KEY]" export AWS_SECRET_ACCESS_KEY="[SECRET_KEY]" terraform init
- Validate changes:
terraform validate
- Plan the changes:
terraform plan
- Apply the changes:
terraform apply
- Destroy environment:
terraform destroy
- Change directory