Terraform create EC2 Instance on AWS
This guide will help you to Create your first AWS EC2 using terraform.
When it comes to IAC(Infrastructure As Code) Terraform is always the first choice of DevOps although there are many alternatives available in the market such as Ansible, Chef, Puppet, SaltStack, CloudFormation but due the fact that -
- Terraform is really easy install
- Terraform has very good API documentation
- It is widely adopted in the DevOps community
- Great support for a popular cloud service provider such as Google Cloud Platform, AWS.
(To know more on How to setup Virtual Machine on Google Cloud - Click Here)
Prerequisite
- The only prerequisite is - You must install Terraform before jumping to Google Cloud Setup.
Table of Content
- Setup AWS Account
- Generate Access keys (access key ID and secret access key)
- Create your first Terraform infrastructure (main.tf)
- terraform commands
- Setup up a custom startup script for an Amazon Elastic Compute Cloud (EC2)
- Copy and Execute the script from local machine to remote EC2 instance using file and remote-exec provisioner
1. Setup AWS Account
As our aim of this article to setup an AWS EC2 instance the first step would be to create an AWS account.
If you are a beginner and want to learn the Terraform then AWS provides you free tier - 12 months or 750 Hours/month, where you can experiment.
1.1 Sign up for AWS account
Goto https://aws.amazon.com/ and click on Complete sign-up
You need to choose AMAZON EC2 Free Tier. This tier is sufficient enough for learning purposes.
Amazon will ask for your Credit card number to complete the sign-up process, AWS will debit around 1$ so that they can verify your card details. Amazon will refund the amount after the authorization.
1.2 After Signup LogIn as ROOT user
After signup, you need to log in as a ROOT user for your AWS account.
Once you login into your AWS account you should see a dashboard, I know the dashboard can be little overwhelming for the first time user but do not worry we are gonna take one item at a time.
2.Generate Access keys (access key ID and secret access key)
Terraform installed on your Desktop/Laptop needs to communicate with AWS and to make this communication terraform needs to be authenticated.
For authentication, we need to generate Access Keys (access key ID and secret access key). These access keys can be used for making - programmatic calls to AWS from the AWS CLI, Tools for PowerShell, AWS SDKs, or direct AWS API calls.
- Goto My Security Credentials
- On Your Security Credentials page click on Access keys (access key ID and secret access key)
-
Click on Create New Access key
-
Copy the Access Key ID and Secret Access Key (Note:- You can view the Secret Access Key only once, so make sure to copy it.)
3. Create your first Terraform infrastructure (main.tf)
Before we start writing terraform script, the first thing to learn over here is - "You need to save your configuration with .tf extension"
As Terraform is developed by HashiCorp, so we use HCL for writing the terraform scripts.
We will start by creating an empty main.tf
file.
3.1 Provider
The first line of code in which we are going to write is provider.
We need to tell terraform which cloud provider we are going to connect .e.g - AWS, Google, or Azure
As this article is focused on AWS, so we are going to mention AWS as our provider.
Here is the basic syntax for the provider
1resource "<PROVIDER>_<TYPE>" "<NAME>" {
2 [CONFIG …]
3}
- "PROVIDER _ TYPE" - aws, google
- "NAME" - You can define your name.
This is how our final main.tf
will look like for AWS -
1provider "aws" {
2 region = "eu-central-1"
3 access_key = "XXXXXXXXXXXXXXXXXXXX"
4 secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
5}
Note: You can copy access_key and secret_key from Step-2
3.2 resource - "aws_instance"
Now after defining the provider, next we are going define is resource
.
So what do you mean by resource?
Resource - It is something that we are going to provision/start on AWS.
Now for this article, we are going to provision EC2 instance on AWS.
But before we provision the EC2 instance, we need to gather few points -
- ami = you need to tell Terraform which AMI(Amazon Machine Image) you are going to use. Is it going to be Ubuntu, CentOS or something else
- instance_type = Also based on your need you have to choose the instance_type and it can be t2.nano, t2.micro, t2. small etc.
3.3 How to find ami(Amazon Machine Image)
- To find the correct ami you need to Goto:
Services -> EC2
- In the left Navigation you will find
Images -> AMIs
- On the search menu click on
public images
and then typeUbuntu
.
- Copy the AMI ID from the search result.
3.4 How to find correct instance_type
You can find the correct ìnstance_type` by visiting this page.
Since I am looking for a very basic instance_type
not production level instance, so I choose t2.micro
Here is the aws_instance
configuration -
1resource "aws_instance" "ec2_example" {
2 ami = "ami-0767046d1677be5a0"
3 instance_type = "t2.micro"
4 tags = {
5 Name = "Terraform EC2"
6 }
7}
4. terraform commands
Alright, now we have completed all the pre-requisites for provisioning our first ec2
instance on the AWS.
4.1 terraform plan
The first command which we are going to run is -
1terraform init
1Initializing the backend...
2
3Initializing provider plugins...
4- Reusing the previous version of hashicorp/aws from the dependency lock file
5- Installing hashicorp/aws v3.32.0...
6- Installed hashicorp/aws v3.32.0 (signed by HashiCorp)
7
8Terraform has been successfully initialized!
9
10You may now begin working with Terraform. Try running "terraform plan" to see
11any changes that are required for your infrastructure. All Terraform commands
12should now work.
13
14If you ever set or change modules or backend configuration for Terraform,
15rerun this command to reinitialize your working directory. If you forget, other
16commands will detect it and remind you to do so if necessary
The terraform init command is responsible for downloading all the dependencies which are required for the provider AWS
.
Once you issue the terraform init
command it will download all the provider's dependencies on your local machine.
4.2 terraform plan
This command will help you to understand how many resources you are gonna add or delete.
Here is the command -
1terraform plan
1An execution plan has been generated and is shown below.
2Resource actions are indicated with the following symbols:
3 + create
4
5Terraform will perform the following actions:
6
7 # aws_instance.ec2_example will be created
8 + resource "aws_instance" "ec2_example" {
9 + ami = "ami-0767046d1677be5a0"
10 + arn = (known after apply)
11 + associate_public_ip_address = (known after apply)
12 + availability_zone = (known after apply)
13 + cpu_core_count = (known after apply)
14 + cpu_threads_per_core = (known after apply)
15 + get_password_data = false
16 + host_id = (known after apply)
17 + id = (known after apply)
18 + instance_state = (known after apply)
19 + instance_type = "t2.micro"
20 + ipv6_address_count = (known after apply)
21 + ipv6_addresses = (known after apply)
22 + key_name = (known after apply)
23 + outpost_arn = (known after apply)
24 + password_data = (known after apply)
25 + placement_group = (known after apply)
26 + primary_network_interface_id = (known after apply)
27 + private_dns = (known after apply)
28 + private_ip = (known after apply)
29 + public_dns = (known after apply)
30 + public_ip = (known after apply)
31 + secondary_private_ips = (known after apply)
32 + security_groups = (known after apply)
33 + source_dest_check = true
34 + subnet_id = (known after apply)
35 + tags = {
36 + "Name" = "Terraform EC2"
37 }
38 + tenancy = (known after apply)
39 + vpc_security_group_ids = (known after apply)
40
41 + ebs_block_device {
42 + delete_on_termination = (known after apply)
43 + device_name = (known after apply)
44 + encrypted = (known after apply)
45 + iops = (known after apply)
46 + kms_key_id = (known after apply)
47 + snapshot_id = (known after apply)
48 + tags = (known after apply)
49 + throughput = (known after apply)
50 + volume_id = (known after apply)
51 + volume_size = (known after apply)
52 + volume_type = (known after apply)
53 }
54
55 + enclave_options {
56 + enabled = (known after apply)
57 }
58
59 + ephemeral_block_device {
60 + device_name = (known after apply)
61 + no_device = (known after apply)
62 + virtual_name = (known after apply)
63 }
64
65 + metadata_options {
66 + http_endpoint = (known after apply)
67 + http_put_response_hop_limit = (known after apply)
68 + http_tokens = (known after apply)
69 }
70
71 + network_interface {
72 + delete_on_termination = (known after apply)
73 + device_index = (known after apply)
74 + network_interface_id = (known after apply)
75 }
76
77 + root_block_device {
78 + delete_on_termination = (known after apply)
79 + device_name = (known after apply)
80 + encrypted = (known after apply)
81 + iops = (known after apply)
82 + kms_key_id = (known after apply)
83 + tags = (known after apply)
84 + throughput = (known after apply)
85 + volume_id = (known after apply)
86 + volume_size = (known after apply)
87 + volume_type = (known after apply)
88 }
89 }
90
91Plan: 1 to add, 0 to change, 0 to destroy.
92
93------------------------------------------------------------------------
94
95Note: You didn't specify an "-out" parameter to save this plan, so Terraform
96can't guarantee that exactly these actions will be performed if
97"terraform apply" is subsequently run.
As you can see the output of terraform plan
, at the end it will show all the resources added and deleted.
**(Note:- This command is not going to provision start your t2.micro instance)**
4.3 terraform apply
This command will do some real stuff on AWS. Once you will issue this command, it will be going to connect to AWS and then finally going to provision AWS instance.
Here is the command -
1terraform apply
1Plan: 1 to add, 0 to change, 0 to destroy.
2
3Do you want to perform these actions?
4 Terraform will perform the actions described above.
5 Only 'yes' will be accepted to approve.
6
7 Enter a value: yes
8
9aws_instance.ec2_example: Creating...
10aws_instance.ec2_example: Still creating... [10s elapsed]
11aws_instance.ec2_example: Still creating... [20s elapsed]
12aws_instance.ec2_example: Still creating... [30s elapsed]
13aws_instance.ec2_example: Creation complete after 33s [id=i-0a948ac635a2010f1]
14
15Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
As you can see the log output has created t2.micro
instance.
4.4 Verify the EC2 setup
Let's verify the setup by going back to AWS console.
Goto -> Services -> EC2
you should see 1 instance running.
You can also see the Tag name - Terraform EC2 which we mentioned in the terraform script.
4.4 terraform destroy
Now we have seen how to write your terraform script and how to provision your EC2 instance.
Let see how to remove or delete everything from AWS.
We are going to use the command -
1terraform destroy
1Plan: 0 to add, 0 to change, 1 to destroy.
2
3Do you want to destroy all resources?
4 Terraform will destroy all your managed infrastructure, as shown above.
5 There is no undo. Only 'yes' will be accepted to confirm.
6
7 Enter a value: yes
8
9aws_instance.ec2_example: Destroying... [id=i-0a948ac635a2010f1]
10aws_instance.ec2_example: Still destroying... [id=i-0a948ac635a2010f1, 10s elapsed]
11aws_instance.ec2_example: Still destroying... [id=i-0a948ac635a2010f1, 20s elapsed]
12aws_instance.ec2_example: Still destroying... [id=i-0a948ac635a2010f1, 30s elapsed]
13aws_instance.ec2_example: Still destroying... [id=i-0a948ac635a2010f1, 40s elapsed]
14aws_instance.ec2_example: Destruction complete after 40s
15
16Destroy complete! Resources: 1 destroyed.
It will remove all the running EC2 Instances.
The previous steps were very basic Terraform examples for setting up an EC2 instance. But in the actual project I think you need to do a little more than just basic EC2 Instance setup. The remaining part of this blog post will help you to do some advanced setup with your EC2 Instance using Terraform.
For example -
Setup up a custom startup script for an Amazon Elastic Compute Cloud (EC2) using Terraform
5. Setup up a custom startup script for an Amazon Elastic Compute Cloud (EC2) using Terraform
To set up a custom startup script for an Amazon Elastic Compute Cloud (EC2) instance using Terraform, you can use the user_data attribute of the aws_instance resource. The user_data attribute allows you to specify data (such as a script) that will be used by cloud-init to configure the instance when it is launched.
Here is an example of how to use the user_data
attribute to specify a custom startup script for an EC2 instance in Terraform. In this example -
- First we will setup the EC2 instance
- Secondly we are going to install Apache Web Server
- At last we are going to set up a very basic HTML page and deploy it on the Apache web server
1
2provider "aws" {
3 region = "eu-central-1"
4 access_key = "<INSERT_YOUR_ACCESS_KEY>"
5 secret_key = "<INSERT_YOUR_SECRET_KEY>"
6}
7
8resource "aws_instance" "ec2_example" {
9
10 ami = "ami-0767046d1677be5a0"
11 instance_type = "t2.micro"
12 key_name= "aws_key"
13 vpc_security_group_ids = [aws_security_group.main.id]
14
15 user_data = <<-EOF
16 #!/bin/sh
17 sudo apt-get update
18 sudo apt install -y apache2
19 sudo systemctl status apache2
20 sudo systemctl start apache2
21 sudo chown -R $USER:$USER /var/www/html
22 sudo echo "<html><body><h1>Hello this custom page built with Terraform User Data</h1></body></html>" > /var/www/html/index.html
23 EOF
24}
6. Copy and Execute the script from local machine to remote EC2 instance using file and remote-exec provisioner
In the previous section, you have seen how to execute custom scripts using the user_data block of terraform. But it is not recommended to use user_data
for long and complex scripts.
In case of long and complex scripts, you should use file
as well as remote-exec
provisioner. (For more in-depth tutorial please refer to this blog post on - What is terraform provisioner )
file provisioner- First we will use file
provisioner to copy the file to the remote EC2 instance.
remote-exec provisioner- To execute the script copied using file
provisioner
Here is an example where you can also use the file provisioner
in Terraform to copy a script file from the local machine to the instance and execute it.
1#main.tf
2
3provider "aws" {
4 region = "eu-central-1"
5 access_key = "<INSERT_YOUR_ACCESS_KEY>"
6 secret_key = "<INSERT_YOUR_SECRET_KEY>"
7}
8
9resource "aws_instance" "ec2_example" {
10
11 ami = "ami-0767046d1677be5a0"
12 instance_type = "t2.micro"
13 key_name= "aws_key"
14 vpc_security_group_ids = [aws_security_group.main.id]
15
16 # file provisioner -
17 # It will copy the "startup.sh" to remote machine
18 provisioner "file" {
19 source = "/home/rahul/Jhooq/startup.sh"
20 destination = "/home/ubuntu/startup.sh"
21 }
22
23 # connection -
24 # This block will be used for ssh connection to initiate the copy
25 connection {
26 type = "ssh"
27 host = self.public_ip
28 user = "ubuntu"
29 private_key = file("/home/rahul/Jhooq/keys/aws/aws_key")
30 timeout = "4m"
31 }
32}
33
34 # remote-exec -
35 # Execute the "startup.sh" script copied using "file" provisoner
36 provisioner "remote-exec" {
37 inline = [
38 "chmod +x /home/ubuntu/startup.sh",
39 "/home/ubuntu/startup.sh"
40 ]
41 }
42
43resource "aws_security_group" "main" {
44 egress = [
45 {
46 cidr_blocks = [ "0.0.0.0/0", ]
47 description = ""
48 from_port = 0
49 ipv6_cidr_blocks = []
50 prefix_list_ids = []
51 protocol = "-1"
52 security_groups = []
53 self = false
54 to_port = 0
55 }
56 ]
57 ingress = [
58 {
59 cidr_blocks = [ "0.0.0.0/0", ]
60 description = ""
61 from_port = 22
62 ipv6_cidr_blocks = []
63 prefix_list_ids = []
64 protocol = "tcp"
65 security_groups = []
66 self = false
67 to_port = 22
68 }
69 ]
70}
71
72# aws_key_pair -
73# You need to generate the public as well as private key using - ssh-keygen
74# Place the public key here
75resource "aws_key_pair" "deployer" {
76 key_name = "aws_key"
77 public_key = "<PLACE_YOU_PUBLIC_KEY>"
78}
Read More - Terragrunt -
Posts in this Series
- Securing Sensitive Data in Terraform
- Boost Your AWS Security with Terraform : A Step-by-Step Guide
- How to Load Input Data from a File in Terraform?
- Can Terraform be used to provision on-premises infrastructure?
- Fixing the Terraform Error creating IAM Role. MalformedPolicyDocument Has prohibited field Resource
- In terraform how to handle null value with default value?
- Terraform use module output variables as inputs for another module?
- How to Reference a Resource Created by a Terraform Module?
- Understanding Terraform Escape Sequences
- How to fix private-dns-enabled cannot be set because there is already a conflicting DNS domain?
- Use Terraform to manage AWS IAM Policies, Roles and Users
- How to split Your Terraform main.tf File into Multiple Files
- How to use Terraform variable within variable
- Mastering the Terraform Lookup Function for Dynamic Keys
- Copy files to EC2 and S3 bucket using Terraform
- Troubleshooting Error creating EC2 Subnet InvalidSubnet Range The CIDR is Invalid
- Troubleshooting InvalidParameter Security group and subnet belong to different networks
- Managing strings in Terraform: A comprehensive guide
- How to use terraform depends_on meta argument?
- What is user_data in Terraform?
- Why you should not store terraform state file(.tfstate) inside Git Repository?
- How to import existing resource using terraform import comand?
- Terraform - A detailed guide on setting up ALB(Application Load Balancer) and SSL?
- Testing Infrastructure as Code with Terraform?
- How to remove a resource from Terraform state?
- What is Terraform null Resource?
- In terraform how to skip creation of resource if the resource already exist?
- How to setup Virtual machine on Google Cloud Platform
- How to use Terraform locals?
- Terraform Guide - Docker Containers & AWS ECR(elastic container registry)?
- How to generate SSH key in Terraform using tls_private_key?
- How to fix-Terraform Error acquiring the state lock ConditionalCheckFiledException?
- Terraform Template - A complete guide?
- How to use Terragrunt?
- Terraform and AWS Multi account Setup?
- Terraform and AWS credentials handling?
- How to fix-error configuring S3 Backend no valid credential sources for S3 Backend found?
- Terraform state locking using DynamoDB (aws_dynamodb_table)?
- Managing Terraform states?
- Securing AWS secrets using HashiCorp Vault with Terraform?
- How to use Workspaces in Terraform?
- How to run specific terraform resource, module, target?
- How Terraform modules works?
- Secure AWS EC2s & GCP VMs with Terraform SSH Keys!
- What is terraform provisioner?
- Is terraform destroy needed before terraform apply?
- How to fix terraform error Your query returned no results. Please change your search criteria and try again?
- How to use Terraform Data sources?
- How to use Terraform resource meta arguments?
- How to use Terraform Dynamic blocks?
- Terraform - How to nuke AWS resources and save additional AWS infrastructure cost?
- Understanding terraform count, for_each and for loop?
- How to use Terraform output values?
- How to fix error configuring Terraform AWS Provider error validating provider credentials error calling sts GetCallerIdentity SignatureDoesNotMatch?
- How to fix Invalid function argument on line in provider credentials file google Invalid value for path parameter no file exists
- How to fix error value for undeclared variable a variable named was assigned on the command line?
- What is variable.tf and terraform.tfvars?
- How to use Terraform Variables - Locals,Input,Output
- Terraform create EC2 Instance on AWS
- How to fix Error creating service account googleapi Error 403 Identity and Access Management (IAM) API has not been used in project before or it is disabled
- Install terraform on Ubuntu 20.04, CentOS 8, MacOS, Windows 10, Fedora 33, Red hat 8 and Solaris 11