Terraform 101
Terraform is used for Infrastructure as Code (IaC).
Terraform is Declarative, NOT Imperative, and defines the DESIRED STATE.
What does that mean? For initial infrastructure creation, they will be very similar (e.g. both will say create 5 servers), but when you update your infrastructure there are differences.
For example, say you have 10 servers, and you want to remove 3...
Imperative commands to update your infrastructure would look like:
- remove 3 servers
Declarative commands to update your infrastructure would look like:
- have 7 servers
Terraform will work out what it needs to do to achieve the Desired state.
With Terraform, you re-run the whole configuration file to achieve your update.
Terraform Stages
refresh - query infra to get current state
plan - create an execution plan (plan to achieve the desired state, based on the current state). No changes.
apply - execute the plan
destroy - removes whole setup, removing elements in the correct order. E.g. remove servers before remove VPC. Destroy also runs a Refresh, and then a Plan before removing the resources.
Terraform plugin for VSCode
https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform
Install Terraform on Mac
First install Homebrew - https://brew.sh/
https://learn.hashicorp.com/tutorials/terraform/install-cli
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
brew update
brew upgrade hashicorp/tap/terraform
Terraform Basic Operation
In vscode, create a new directory - e.g. Documents\terraform
create the file: main.tf
provider "aws" {
region = "us-east-1"
access_key = "access-key"
secret_key = "your-secret-key"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.0.0.0/16"
}
This will create a VPC resource - for syntax see:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
In VSCode, click the 'View' menu and select "Terminal".
Now, run the command:
terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v3.72.0
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform has successfully initialised the plugin for AWS.
terraform plan
The terraform plan command examines the current state, and works out what needs to be changed in order to achieve the desired state.
In the main.tf file we specified a VPC with CIDR 10.0.0.0/16, and here terraform can see that it currently doesn't exist - hence the (known after apply) lines.
For example the arn (amazon resource name) for the VPC is unknown because we haven't created it yet.
Terraform Apply
Again, the apply command examines the current state, and says what it will do in order to achieve the desired state.
Type 'yes' to continue to perform the actions.
Terraform Destroy
This will destroy the resources listed in your main.tf file.
Terraform will examine the current state, and will say what actions it will take to destroy the resources.
Type 'yes' to continue.
State File
The state file is called 'terraform.tfstate'. This contains the current state.
There is also a back file called 'terraform.tfstate.backup', but this isn't the latest.
When you run an plan, apply, or destroy command, the terraform.tfstate file will be updated. The old contents of the file will be copied to the backup file.
Variables
Defined in the main.tf file.
Variables are a way of setting a value which can be used multiple times.
Variables can be a string, number, boolean, list, map, tuple, or object.
String Variables
Number Variables
Boolean Variables
List Variables
Lists can contain strings, numbers, or boolean values.
Note for lists, like an array, the first element is accessed by item number 0.
The value of item 0 = 'Value1'
Map Variables
Maps are key-value pairs.
The elements of a map are accessed using the key you gave,
For example:
When you access key1, its value is 'Value1'.
Tuples
Tuples are similar to Lists, but can contain different data types.
variable "mytuple" {
type = tuple([string, number, string])
default = ["cat",1,"dog"]
}
Objects
variable "myobject"{
type = object({name = string, port = list(number)})
default = {
name = "fw"
port = [22,25,80]
}
}
Using Variables
Variables are referenced using 'var.'
variable "vpcname" {
type = string
default = "myvpc"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = var.vpcname
}
}
Or to access a list variable:
variable "mylist" {
type = list(string)
default = [ "Value1","Value2" ]
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = var.mylist[0]
}
}
Or to access a map variable:
variable "mymap" {
type = map
default = {
key1 = "Value1"
key2 = "Value2"
}
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = var.mymap["key1"]
}
}
Note, the key name is in quotes!
Input Variables
Allows user to manually specify a value when running terraform plan
variable "inputname" {
type = string
description = "set the name of the vpc"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = var.inputname
}
}
Now when running terraform plan, you will see:
Outputs
After Terraform creates a resource, you may want to know some information about it such as the arn or id. Note, this will only work with terraform apply.
resource "aws_vpc" "myvpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = var.inputname
}
}
output "vpcid" {
value = aws_vpc.myvpc.id
}
output "vpcarn" {
value = aws_vpc.myvpc.arn
}
Note: the outputs get saved to the State file terraform.tfstate
Creating an EC2 instance
The documentation for EC2 instance is 'aws_instance'
main.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "ec2instance" {
ami = "ami-08e4e35cccc6189f4"
instance_type = "t2.micro"
}
output "ec2_arn" {
value = aws_instance.ec2instance.arn
}
No comments:
Post a Comment