Infrastructure Automation With Terraform
Github repository
- https://github.com/jasvinder-aulakh/terraform-course.git
- Use the download button on the Github website (zip) or git clone this repository
AWS Setup:
Make sure you have installed the AWS CLI
- if you use my vagrant devops-box it is included by default:
- https://github.com/jasvinder-aulakh/devops-box.git
Useful Commands
$ terraform plan # plan
$ terraform apply # shortcut for plan & apply - avoid this in production
$ terraform plan -out out.terraform # terraform plan and write the plan to out file
$ terraform apply out.terraform # apply terraform plan using out file
$ terraform show # show current state
$ cat terraform.tfstate # show state in JSON format
Reference Documentation
- Download URL: https://www.terraform.io/downloads.html
- AWS Resources: https://www.terraform.io/docs/providers/aws/
- List of providers: https://www.terraform.io/docs/providers/index.html
<<<<<<<<<<<< What is Terraform>>>>>>>>>>
1. Infrastructure as a Code.
2. Automation of your infrastructure
3. Keep your infrastructure in a certain state.
4. Make your infrastructure auditable
5. Terraform can automate the provisioning of the infrastructure itself.
<<<<<<<<<<<Installing Terraform>>>>>>>>>>>
https://www.terraform.io/downloads.html
Download and install it in your system.
after installation should be run like:
$ terraform
Usage: terraform [--version] [--help] <command> [args]
The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.
Common commands:
apply Builds or changes infrastructure
console Interactive console for Terraform interpolations
destroy Destroy Terraform-managed infrastructure
env Workspace management
fmt Rewrites config files to canonical format
get Download and install modules for the configuration
graph Create a visual graph of Terraform resources
import Import existing infrastructure into Terraform
init Initialize a Terraform working directory
output Read an output from a state file
plan Generate and show an execution plan
providers Prints a tree of the providers used in the configuration
push Upload this Terraform module to Atlas to run
refresh Update local state file against real resources
show Inspect Terraform state or plan
taint Manually mark a resource for recreation
untaint Manually unmark a resource as tainted
validate Validates the Terraform files
version Prints the Terraform version
workspace Workspace management
All other commands:
debug Debug output management (experimental)
force-unlock Manually unlock the terraform state
state Advanced state management
<<<<<<<<<<< Terraform installation using vagrant>>>>>>>>>>>>
Vagrant is a tool for building and managing virtual machine environments in a single workflow. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases production parity, and makes the "works on my machine" excuse a relic of the past
1. First install the virtual box in your system: from
https://www.virtualbox.org/wiki/Downloads
2. Second install Vagrant from:
https://www.vagrantup.com/downloads.html
3. Create a new VM.
do clone devops-box from github:
After cloning there are 3 files:
-rw-r--r-- 1 jass-devops staff 137B May 20 07:42 README.md
-rw-r--r-- 1 jass-devops staff 388B May 20 10:17 Vagrantfile
drwxr-xr-x 3 jass-devops staff 96B May 20 10:17 scripts/
Write Vagrant file as per your required VM, written for ubuntu as given below:
## cat Vagrantfile
Vagrant.configure(2) do |config|
config.vm.define "devops-box" do |devbox|
devbox.vm.box = "ubuntu/xenial64"
#devbox.vm.network "private_network", ip: "192.168.199.9"
#devbox.vm.hostname = "devops-box"
devbox.vm.provision "shell", path: "scripts/install.sh"
devbox.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
end
end
## In scripts folder, write install.sh bash script to do terraform, awscli and packer installation:
## cat install.sh
#!/bin/bash
set -x
if [ -e /etc/redhat-release ] ; then
REDHAT_BASED=true
fi
TERRAFORM_VERSION="0.11.1"
PACKER_VERSION="0.10.2"
# create new ssh key
[[ ! -f /home/ubuntu/.ssh/mykey ]] \
&& mkdir -p /home/ubuntu/.ssh \
&& ssh-keygen -f /home/ubuntu/.ssh/mykey -N '' \
&& chown -R ubuntu:ubuntu /home/ubuntu/.ssh
# install packages
if [ ${REDHAT_BASED} ] ; then
yum -y update
yum install -y docker ansible unzip wget
else
apt-get update
apt-get -y install docker.io ansible unzip
fi
# add docker privileges
usermod -G docker ubuntu
# install pip
pip install -U pip && pip3 install -U pip
if [[ $? == 127 ]]; then
wget -q https://bootstrap.pypa.io/get-pip.py
python get-pip.py
python3 get-pip.py
fi
# install awscli and ebcli
pip install -U awscli
pip install -U awsebcli
#terraform
T_VERSION=$(/usr/local/bin/terraform -v | head -1 | cut -d ' ' -f 2 | tail -c +2)
T_RETVAL=${PIPESTATUS[0]}
[[ $T_VERSION != $TERRAFORM_VERSION ]] || [[ $T_RETVAL != 0 ]] \
&& wget -q https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
&& unzip -o terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin \
&& rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip
# packer
P_VERSION=$(/usr/local/bin/packer -v)
P_RETVAL=$?
[[ $P_VERSION != $PACKER_VERSION ]] || [[ $P_RETVAL != 1 ]] \
&& wget -q https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_amd64.zip \
&& unzip -o packer_${PACKER_VERSION}_linux_amd64.zip -d /usr/local/bin \
&& rm packer_${PACKER_VERSION}_linux_amd64.zip
# clean up
if [ ! ${REDHAT_BASED} ] ; then
apt-get clean
fi
## vagrant up ( To create vm, which defined in vagrant file with install.sh setup)
## vagrant ssh ( To login in new created vm)
Now you have done vagrant setup and created new vm with terraform and awscli installed.
<<<<<<<<<<<<< Terraform- spinning up an instance on AWS >>>>>>>>>>>>>>
Process:
1. Open AWS account
2. Create IAM admin user
3. Create terraform file to spin up t2.micro instance
4. Run terraform apply
<<<<<<<<<<<< Create terraform file >>>>>>>>>>>>
# vim instance.tf
provider "aws" {
access_key = "ACCESS_KEY_HERE"
secret_key = "SECRET_KEY_HERE"
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-0d729a60"
instance_type = "t2.micro"
}
<<<<<<<<<<< Variables in terraform >>>>>>>>>>>>
Everything in one file is not great.
Use variables to hide secrets
Use variables for elements that might change
Use variables to make it yourself easier to reuse terraform files
Create 4 files:
instance.tf, provider.tf, vars.tf and terraform.tfvars
# cat instance.tf
resource "aws_instance" "example" {
ami = "${lookup(var.AMIS, var.AWS_REGION)}"
instance_type = "t2.micro"
}
# cat provider.tf
provider "aws" {
access_key = "${var.AWS_ACCESS_KEY}"
secret_key = "${var.AWS_SECRET_KEY}"
region = "${var.AWS_REGION}"
}
# cat vars.tf
variable "AWS_ACCESS_KEY" {}
variable "AWS_SECRET_KEY" {}
variable "AWS_REGION" {
default = "eu-west-1"
}
variable "AMIS" {
type = "map"
default = {
us-east-1 = "ami-13be557e"
us-west-2 = "ami-06b94666"
eu-west-1 = "ami-0d729a60"
}
}
# cat terraform.tfvars
AWS_ACCESS_KEY=""
AWS_SECRET_KEY=""
Then execute terraform apply
<<<<<<<<<<<<<<<<<<<<<Software Provisioning>>>>>>>>>>>>>>>>>>>>>>
There are 2 ways to software provisioning on your instance:
1. You can build your own custom AMI and bundle your software with the image
2. Another way is to boot standardized AMIs, and then install the software on it, you need
First, define: 5 files- instance.tf, vars.tf, provider.tf, terraform.tfvars and script.sh
then create a key as name of "mykey"
# vim instance.tf
resource "aws_key_pair" "mykey" {
key_name = "mykey"
public_key = "${file("${var.PATH_TO_PUBLIC_KEY}")}"
}
resource "aws_instance" "example" {
ami = "${lookup(var.AMIS, var.AWS_REGION)}"
instance_type = "t2.micro"
key_name = "${aws_key_pair.mykey.key_name}"
provisioner "file" {
source = "script.sh"
destination = "/tmp/script.sh"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/script.sh",
"sudo /tmp/script.sh"
]
}
connection {
user = "${var.INSTANCE_USERNAME}"
private_key = "${file("${var.PATH_TO_PRIVATE_KEY}")}"
}
}
# vim vars.tf
variable "AWS_ACCESS_KEY" {}
variable "AWS_SECRET_KEY" {}
variable "AWS_REGION" {
default = "ap-south-1"
}
variable "AMIS" {
type = "map"
default = {
ap-south-1 = "ami-0189d76e"
us-west-2 = "ami-06b94666"
eu-west-1 = "ami-844e0bf7"
}
}
variable "PATH_TO_PRIVATE_KEY" {
default = "mykey"
}
variable "PATH_TO_PUBLIC_KEY" {
default = "mykey.pub"
}
variable "INSTANCE_USERNAME" {
default = "ubuntu"
}
First, define: 5 files- instance.tf, vars.tf, provider.tf, terraform.tfvars and script.sh
then create a key as name of "mykey"
# vim instance.tf
resource "aws_key_pair" "mykey" {
key_name = "mykey"
public_key = "${file("${var.PATH_TO_PUBLIC_KEY}")}"
}
resource "aws_instance" "example" {
ami = "${lookup(var.AMIS, var.AWS_REGION)}"
instance_type = "t2.micro"
key_name = "${aws_key_pair.mykey.key_name}"
provisioner "file" {
source = "script.sh"
destination = "/tmp/script.sh"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/script.sh",
"sudo /tmp/script.sh"
]
}
connection {
user = "${var.INSTANCE_USERNAME}"
private_key = "${file("${var.PATH_TO_PRIVATE_KEY}")}"
}
}
# vim vars.tf
variable "AWS_ACCESS_KEY" {}
variable "AWS_SECRET_KEY" {}
variable "AWS_REGION" {
default = "ap-south-1"
}
variable "AMIS" {
type = "map"
default = {
ap-south-1 = "ami-0189d76e"
us-west-2 = "ami-06b94666"
eu-west-1 = "ami-844e0bf7"
}
}
variable "PATH_TO_PRIVATE_KEY" {
default = "mykey"
}
variable "PATH_TO_PUBLIC_KEY" {
default = "mykey.pub"
}
variable "INSTANCE_USERNAME" {
default = "ubuntu"
}
# vim provider.tf
provider "aws" {
access_key = "${var.AWS_ACCESS_KEY}"
secret_key = "${var.AWS_SECRET_KEY}"
region = "${var.AWS_REGION}"
}
# vim terraform.tfvars
AWS_ACCESS_KEY=""
AWS_SECRET_KEY= ""
# vim script.sh
#!/bin/bash
# sleep until instance is ready
until [[ -f /var/lib/cloud/instance/boot-finished ]]; do
sleep 1
done
# install nginx
apt-get update
apt-get -y install nginx
# make sure nginx is started
service nginx start
then run terraform apply
the result should like - aws_instance.example: Creation complete after 58s (ID: i-0f0e050c4cf2a3bfe)
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
# check your nginx with IP-
Comments
Post a Comment
Thank you for visiting my blog.