Terraform 10 of 10: Provisioners using AWS Cloud9

Background

This tutorial deals with Provisioners. AWS Cloud9 is the environment. Please note that Terraform only recommends Provisioners as a "last resort" and that you should attempt other methods before dealing with provisioners. Provisioners run within the resources themselves, so Provisioners add complexity and uncertainty.

1 of 14. Open the documentation for "Provisioners"

This documentation is not all-inclusive. You may find other documentation in the "Reference" section.

Provisioners

2 of 14. Open your AWS Cloud9 environment

Creating An Integrated Developer Environment (IDE) in the Cloud in Two Minutes!: AWS Cloud9(Step-by-Step)

3 of 14. Setup project directory and create files

Make sure to start from your "environment" before creating the directory. This directory will be used for this project. Make sure to run project operations from within that directory.

pwd mkdir terraform-provisioners-example && cd terraform-provisioners-example touch main.tf resources.tf outputs.tf

4 of 14. Generate SSH-Keys

ssh-keygen -f ec2-key

5 of 14. Modify terraform files: "main.tf", "resources.tf" and "outputs.tf"

"main.tf

provider "aws" { region = "us-east-1" }

"resources.tf". Keep in mind that the AMI is region-specific. This lab was run on this specific OS/image. It refers to the ssh key you previously made.

resource "aws_security_group" "example" { name = "example" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_key_pair" "key" { key_name = "aws_tf_key" public_key = file("./ec2-key.pub") } resource "aws_instance" "ec2" { ami = "ami-0c7217cdde317cfec" #Canonical, Ubuntu, 22.04 LTS, amd64 jammy image build on 2023-12-07 instance_type = "t2.micro" key_name = aws_key_pair.key.key_name vpc_security_group_ids = [aws_security_group.example.id] }

"outputs.tf"

output "ec2_pub_ip" { value = aws_instance.ec2.public_ip }

6 of 14. Create the resources

terraform init && terraform apply -auto-approve

7 of 14. Validate SSH

Note that the IP address here should match what was in the output of your 'terraform apply'

ssh -i ec2-key ubuntu@203.0.113.20

8 of 14. Destroy resources.

Make sure to exit your Ubuntu session first, else your command might not be understood.

exit terraform destroy -auto-approve

9 of 14. Create a sample dump file

echo "This is a sample dump file" > dump echo "Beep Boop Bleep Bloop Whoops!" >> dump cat dump

10 of 14. Update "resources.tf" with provisioners.

Think of provisioners as running operations on the resource itself. All additions will be to the "ec2" resource, because these Provisioners run inside the ec2 instance itself. Look at the various types of commands: "local-exec" runs on the host running terraform. "remote-exec" is a remote command, "file" is a file operation. The "connection" refers to the connection that Terraform will make to the host to run the commands.

resource "aws_security_group" "example" { name = "example" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_key_pair" "key" { key_name = "aws_tf_key" public_key = file("./ec2-key.pub") } resource "aws_instance" "ec2" { ami = "ami-0c7217cdde317cfec" #Canonical, Ubuntu, 22.04 LTS, amd64 jammy image build on 2023-12-07 instance_type = "t2.micro" key_name = aws_key_pair.key.key_name vpc_security_group_ids = [aws_security_group.example.id] tags = { "Name" = "webserver01" } provisioner "local-exec" { command = "echo ${self.public_ip} >> ec2-public-ip.txt" } provisioner "file" { source = "./dump" ## Do not forget to create fictitious 'dump' file destination = "/tmp/dump-onp" } provisioner "file" { content = "EC2 AZ: ${self.availability_zone}" destination = "/tmp/ec2-az.txt" } provisioner "remote-exec" { inline = [ "echo EC2 ARN: ${self.arn} >> /tmp/arn.txt", "echo EC2 Public DNS: ${self.public_dns} >> /tmp/public_dns.txt", "echo EC2 Private IP: ${self.private_ip} >> /tmp/private_ip.txt" ] } connection { type = "ssh" user = "ubuntu" private_key = file("./ec2-key") host = self.public_ip } }

11 of 14. Init and apply

This is a lab environment, but be wary of "auto-approve" in production unless it has been approved.

terraform fmt terraform validate terraform init && terraform apply -auto-approve

12 of 14. Check what ran for "local-exec"

Check for that "ec2-public-ip.txt" file

cat ec2-public-ip.txt

13 of 14. Check your Ubuntu host

Logon the Ubuntu host, then check for the created files and their contents. The previous warning about checking for the correct IP for your host before connecting still applies.

ssh -i ec2-key ubuntu@203.0.113.20 ls /tmp cat /tmp/dump-onp cat /tmp/ec2-az.txt cat /tmp/arn.txt cat /tmp/public_dns.txt cat /tmp/private_ip.txt

14 of 14. Cleanup

>Cleanup what you did. Exit your Ubuntu host first. I could have auto-approved here also, but it's a habit I don't want to start.

exit terraform destroy

Reference

Provisioners

Creating An Integrated Developer Environment (IDE) in the Cloud in Two Minutes!: AWS Cloud9(Step-by-Step)

ssh-keygen (Ubuntu man-pages)

Finding an Amazon Machine Image (AMI)

Manage users on your Linux instance

Resource: aws_key_pair

RFC 5737 IPv4 Address Blocks Reserved for Documentation

Comments

Popular posts from this blog

Orphaned No More: Adopting AWS Lambda

Containing the Chaos! | A Three-Part Series Demonstrating the Usefulness of Containerization to HumanGov

Ansible is the Answer! | A Three-Part Series Demonstrating the Usefulness of Ansible to HumanGov