Terraforming your Infrastructure
Transcript of Terraforming your Infrastructure
November15,2016
TerraformingYourInfrastructureFromBeginnertoSemi-Proin30Minutes
BrittTreeceProductionEngineeratPhishMe
@abtreece
November15,2016
November15,2016
Load
Web
App
Data
region-a region-b
November15,2016
November15,2016
Load
Web
App
Data
providera providerb
November15,2016
Weneeded
Atoolthatwasn’tspecifictoAWS
Somethingthatwaseasiertoreadandunderstand
Tofullyunderstandwhatwasgoingtochangeupon execution
Theabilitytocollaboratemoreeasilyonourinfrastructure
November15,2016
TERRAFORM
November15,2016
WhatisTerraform
“…isatoolforbuilding,changing,andversioninginfrastructuresafelyandefficiently.”
Usesconfigurationfilestodescribethedesiredinfrastructure.
HasproviderswhicharetheinterfacebetweenTerraformandcloudservices
Hasprovisionerswhichitcanexecutetoinitializearesourceinsomeway
Canbepackagedbycreatingmodules…DRYIaC?
November15,2016
WhatTerraformisn’t
Aprogramminglanguage
Apreclusionforunderstandingbestpracticesofyourproviders
Goingtosaveyoufromdoingsomethingdumb
November15,2016
K.I.S.S.KeepItSimpleStupid
November15,2016
KISS
Pickapatternandstickwithit
addo├── main.tf├── outputs.tf└── vars.tf
addo├── instances.tf├── load-balancers.tf├── variables.tf└── provider.tf
addo└── main.tf
November15,2016
KISS
Putallyourvariabledeclarationsinonefile
addo├── main.tf├── outputs.tf└── vars.tf
addo├── instances.tf├── load-balancers.tf├── variables.tf└── provider.tf
addo└── main.tf
November15,2016
KISS
Nameyourresourceswithintention
resource "aws_instance" ”web-1” {ami = "ami-b73b63a0”instance_type = "t2.medium”
}
resource "aws_instance" ”web-2” {ami = "ami-153e6470”instance_type = ”c4.large”
}
resource "aws_instance" ”haproxy” {ami = "ami-b73b63a0”instance_type = "t2.medium”
}
resource "aws_instance" ”nodejs” {
ami = "ami-153e6470”instance_type = ”c4.large”
}
November15,2016
KISS
Usetags!
resource "aws_instance" ”haproxy” {ami = "ami-b73b63a0”instance_type = ”t2.medium”
tags {Name = “haproxy“Environment = “production“
}}
November15,2016
K.Y.S.S.KeepYourSecretsSecret
November15,2016
KeepYourSecretsSecret
Yourkeysandpems don’tbelong inyourconfigurations
provider "aws" {access_key = ”AKIEYUS7VABTGDC4AP4Q”secret_key = ”W/akHyLA8ScewFNDsOYS8/KJoYSci2yoqrewlCp”region = "us-east-1”
}
November15,2016
KeepYourSecretsSecret
UseTF_VARstostoreyoursecretsasenvironmentvariables
TF_VAR_access_key = ”AKIEYUS7VABTGDC4AP4Q”TF_VAR_secret_key = ”W/akHyLA8ScewFNDsOYS8/KJoYSci2yoqrewlCp”
main.tfvariable “access_key” {}
variable “secret_key” {}
provider "aws" {region = "us-east-1”
}
November15,2016
KeepYourSecretsSecret
Takeadotfiles approachtosettingtheTF_VARs
.env.d/aws_credentialsexport TF_VAR_access_key=”AKIEYUS7VABTGDC4AP4Q”export TF_VAR_secret_key=”W/akHyLA8ScewFNDsOYS8/KJoYSci2yoqrewlCp”
main.tf
variable “access_key” {}variable “secret_key” {}
provider "aws" {region = "us-east-1”
}
November15,2016
KeepYourSecretsSecret
Usedirenv toswitchyourenvironment variablesfordifferentconfigurations
.envrcsource ~/.env.d/aws_credentialssource ~/.env.d/us-east-1.tfvars
$ cd productiondirenv: loading .envrc
direnv: export +TF_VAR_access_key +TF_VAR_key_name +TF_VAR_public_key_path+TF_VAR_secret_key$ cd ..direnv: unloading
November15,2016
STATEOFTHETERRAFORM
November15,2016
ProtectyourState
Thestatefileisthe*actual* stateofyourinfrastructure!Itmustbeprotected!
Directeditingofthisfile,whilepossible,isgenerallyabadidea.
Ifyouaregoingtotinkerwithyourstatefiles makesureyouhaveacopysavedsomewhere!
November15,2016
RemoteState
CheckyourconfigurationsintoGit,notyourstatefiles.
Remotestateallowsforeasiercollaborationbetweenteams
Itprovideswaystoexposeinformationbetweenenvironmentsusingoutputs
Additionally,wherepossibleenableversioningandencryption…S3
November15,2016
UseTerragrunt
Terragrunt isathinwrapperforTerraformcreatedbyGruntwork (gruntwork.io)
Itenforcesbestpractices forTerraformstate
ItsupportslockingusingAmazon’sDynamoDB asthelockingmechanism
IfyourGolang isonpoint,contributetotheproject!
https://github.com/gruntwork-io/terragrunt
November15,2016
SEPARATIONOFPOWERS
November15,2016
BlastRadius– Wide
Onestatefileperenvironment
S3://tfstate/addo/stagingS3://tfstate/addo/productionS3://tfstate/addo/global
staging├── …└── vars.tf
production├── …└── vars.tf
global├── …└── vars.tf
November15,2016
BlastRadius– Narrow
Onestatefileperserviceperenvironment
networking├── …└── vars.tf
compute├── …└── vars.tf
database├── …└── vars.tf
storage├── …└── vars.tf
S3://tfstate/addo/production/networkingS3://tfstate/addo/production/computeS3://tfstate/addo/production/databaseS3://tfstate/addo/production/storage
November15,2016
BlastRadius– Regional
Onestatefileperserviceperenvironment
networking├── …└── vars.tf
compute├── …└── vars.tf
database├── …└── vars.tf
storage├── …└── vars.tf
S3://tfstate/addo/us-east-1/production/networkingS3://tfstate/addo/us-east-1/production/compute…S3://tfstate/addo/us-west-1/production/networkingS3://tfstate/addo/us-west-1/production/compute…
November15,2016
UseTerragrunt
DidImentionTerragrunt?
lock = {backend = "dynamodb”config {state_file_id = ”addo_production”
}}
remote_state = {backend = "s3”config {encrypt = "true”bucket = "add-tf-state”key = ”addo/production/terraform.tfstate”region = "us-east-1"
}}
addo/production├── main.tf├── outputs.tf├── vars.tf└── .terragrunt
November15,2016
USEMODULES
November15,2016
UseModules
Modulesareawayto“package”Terraformconfigurations
ModulesarejustanisolatedTerraformconfiguration
Module takeinputsasvariablesandprovideoutputs asattributes
Gitignore your .terraformdirectory
November15,2016
UseModules
Whenyourconfigurations starttolooklikethis…
addo/production/├── compute│ ├── main.tf│ ├── outputs.tf│ └── vars.tf├── database│ ├── …│ └── vars.tf├── networking│ ├── …│ └── vars.tf└── storage
├── …└── vars.tf
addo/staging/├── compute│ ├── main.tf│ ├── outputs.tf│ └── vars.tf├── database│ ├── …│ └── vars.tf├── networking│ ├── …│ └── vars.tf└── storage
├── …└── vars.tf
addo/test/├── compute│ ├── main.tf│ ├── outputs.tf│ └── vars.tf├── database│ ├── …│ └── vars.tf├── networking│ ├── …│ └── vars.tf└── storage
├── …└── vars.tf
November15,2016
UseModules
Youshoulddothis…
addo/modules/├── compute│ ├── main.tf│ ├── outputs.tf│ └── vars.tf├── database│ ├── …│ └── main.tf├── networking│ ├── …│ └── main.tf└── storage
├── …└── main.tf
addo/production/├── main.tf├── output.tf└── vars.tf
addo/staging/├── main.tf├── output.tf└── vars.tf
November15,2016
UseModules
Youshoulddothis…
addo/modules/compute/main.tf
resource "aws_instance" ”haproxy” {ami = "${var.ami_id}”instance_type = ”${var.inst_type}”
tags {Name = “haproxy“Environment = “${var.environment}“
}}
addo/production/main.tf
module “haproxy” {source = “../modules/haproxy”
ami = “ami-b73b63a0”inst_type = “t2.medium”environment = “production”
}
November15,2016
November15,2016