Terraform
Infrastructure as a Code
Introduction
❖ IAAC | Automate Infrastructure
❖ Define Infrastructure State
❖ Ansible, puppet or chef automates mostly OS related
tasks.
➢ Defines machines state
❖ Terraform automates infra itself
➢ Like AWS, GCP, Azure, digital ocean etc
2
Introduction
❖ Terraform works with automation softwares like ansible
after infra is setup and ready.
❖ No Programming, its own syntax similar to JSON.
3
Everything
Needs
Automation
Infrastructure automation centralized.
4
Installation
Download Terraform binary from its website
❖ Linux
❖ Mac
❖ Windows
Store binary in exported PATH
e:g: Linux => /usr/local/bin
5
Launch ec2 instance
❖ AWS Account
❖ IAM User with access keys
❖ Terraform file to launch instance
❖ Run terraform apply
6
Exercise
➔ Write instance.tf file
➔ Launch instance
➔ Make some changes to instance.tf file
➔ Apply changes.
Summarizing
instance.tf
provider "aws" {
access_key = "ACCESS_KEY"
secret_key = "SECRET_KEY"
region = "ap-south-1"
}
resource "aws_instance" "intro" {
ami = "ami-009110a2bf8d7dd0a"
instance_type = "t2.micro"
}
8
Summarizing
terraform plan
+ create
Terraform will perform the following actions:
# aws_instance.intro will be created
+ resource "aws_instance" "intro" {
+ ami = "ami-009110a2bf8d7dd0a"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
9
Summarizing
terraform apply
aws_instance.intro: Creating...
aws_instance.intro: Still creating... [10s elapsed]
aws_instance.intro: Still creating... [20s elapsed]
aws_instance.intro: Still creating... [30s elapsed]
aws_instance.intro: Creation complete after 31s [id=i-047d7ea789e081807]
10
Summarizing
terraform destroy
Plan: 0 to add, 0 to change, 1 to destroy.
aws_instance.intro: Destroying... [id=i-047d7ea789e081807]
aws_instance.intro: Still destroying... [id=i-047d7ea789e081807, 10s elapsed]
aws_instance.intro: Still destroying... [id=i-047d7ea789e081807, 20s elapsed]
aws_instance.intro: Destruction complete after 29s
Destroy complete! Resources: 1 destroyed.
11
Variables
➔ Move secrets to another file
➔ Values that change
◆ AMI, tags, keypair etc
➔ Reuse your code
instance.tf
provider "aws" {
#access_key = "ACCESS_KEY"
#secret_key = "SECRET_KEY"
region = "ap-south-1"
}
resource "aws_instance" "intro" {
ami = "ami-009110a2bf8d7dd0a"
instance_type = "t2.micro"
}
13
providers.tf vars.tf
provider "aws" {
variable REGION {
region = var.REGION
default = "us-west-1"
}
}
terraform.tfvars instance.tf
AWS_ACCESS_KEY = "" resource "aws_instance" "intro" {
AWS_SECRET_KEY = "" ami = "ami-009110a2bf8d7dd0a"
instance_type = "t2.micro"
}
14
providers.tf vars.tf
variable AWS_ACCESS_KEY {}
provider "aws" {
variable AWS_SECRET_KEY {}
region = var.REGION
variable REGION {
}
default = "us-west-1"
}
variable AMIS {
instance.tf type = "map"
resource "aws_instance" "intro" { default {
ami = var.AMIS[var.REGION] us-west-1 = "ami-06397100adf427136"
instance_type = "t2.micro" us-west-2 = "ami-a042f4d8"
} }
}
15
Exercise
➔ Write providers.tf file
➔ Write vars.tf file
➔ Write instance.tf file
➔ Apply Changes
➔ Make some changes to instance.tf file
➔ Apply changes.
Provisioning
❖ Build Custom Images with tools like packer
❖ Use standard Image and use provisioner to setup softwares
and files.
➢ File uploads
➢ remote_exec
➢ Ansible, Puppet or Chef
Provisioner Connection
Requires Connection for provisioning.
WinRM
SSH provisioner "file" {
provisioner "file" { source = "conf/myapp.conf"
source = "files/test.conf" destination = "C:/App/myapp.conf"
destination = "/etc/test.conf"
connection {
connection { type = "winrm"
type = "ssh" user = "Administrator"
user = "root" password = var.admin_password
}
password = var.root_password
}
}
}
18
More Provisioner
❖ The file provisioner is used to copy files or directories
❖ remote-exec invokes a command/script on remote
resource.
❖ local-exec provisioner invokes a local executable after a
resource is created
19
More Provisioner
❖ The puppet provisioner installs, configures and runs the Puppet
agent on a remote resource.
➢ Supports both ssh and winrm type connections.
❖ The chef provisioner installs, configures and runs the Chef
Client on a remote resource.
➢ Supports both ssh and winrm type connections.
❖ Ansible : run terraform, Output IP address, run playbook with
local-exec
20
Variables
variable "PRIV_KEY_PATH" {
default = "infi-inst_key"
}
variable "PUB_KEY_PATH" {
default = "infi-inst_key.pub"
}
variable "USER" {
default = "ubuntu"
}
21
Key Pair & instance Resources
resource "aws_key_pair" "dove-key" {
key_name = "dovekey"
public_key = file("dovekey.pub")
}
resource "aws_instance" "intro" {
ami = var.AMIS[var.REGION]
instance_type = "t2.micro"
availability_zone = var.ZONE1
key_name = aws_key_pair.dove-key.key_name
vpc_security_group_ids = ["sg-833e24fd"]
}
22
File Provisioner
provisioner "file" { variable "PRIV_KEY_PATH" {
source = "web.sh" default = "infi-inst_key"
destination = "/tmp/web.sh" }
connection { variable "PUB_KEY_PATH" {
user = var.USER default = "infi-inst_key.pub"
private_key = }
file(var.PRIV_KEY_PATH) variable "USER" {
host = self.public_ip default = "ubuntu"
} }
23
Remote-exec Provisioner
provisioner "remote-exec" {
inline = [
"chmod u+x /tmp/web.sh",
"sudo /tmp/web.sh"
]
}
24
Exercise
● Generate key pair
● Write script
● Write providers.tf
● Write vars.tf
● Write instances.tf
○ key pair resource
○ aws_instance resource
■ provisioners
● file
● remote-exec
● Apply changes.
Output Information
● Terraform stores returned value of all resources created.
○ e:g aws_instance resource has the attribute public_ip
● Use output block to print these attributes.
● local-exec to save info to a file
Output Attributes
output "instance_ip_addr" {
value = aws_instance.server.public_ip
}
Elements => resourceType.resourceName.attributeName
resourceType => aws_instance
resourceName => server
attributeName => public_ip
27
Store Output in File
resource "aws_instance" "out_inst" {
ami = var.AMIS[var.REGION]
instance_type = "t2.micro"
key_name = aws_key_pair.dino-key.key_name
provisioner "local-exec" {
command = "echo aws_instance.out_inst.private_ip >>
private_ips.txt"
}
}
28