Slide 1

Slide 1 text

Infrastructure as Code Sebastian Grodzicki @ phpCE 2017 !@sebgrodzicki

Slide 2

Slide 2 text

$ whoami Sebastian Grodzicki
 • CTO at SHOWROOM • PHP developer for 15+ years • DevOps enthusiast !@sebgrodzicki

Slide 3

Slide 3 text

module "stack" {
 source = "github.com/segmentio/stack"
 environment = "demo"
 key_name = "sgrodzicki"
 name = "phpCE"
 } main.tf

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

How did we get here?

Slide 9

Slide 9 text

Data center evolution DC

Slide 10

Slide 10 text

Data center evolution DC

Slide 11

Slide 11 text

Data center evolution DC

Slide 12

Slide 12 text

Data center evolution DC VM VM VM VM VM VM VM VM VM VM VM VM

Slide 13

Slide 13 text

Data center evolution DC VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C VM C C C C C C

Slide 14

Slide 14 text

Data center evolution 
 DNS 
 CDN

Slide 15

Slide 15 text

Data center evolution PaaS IaaS SaaS

Slide 16

Slide 16 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 


Slide 17

Slide 17 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR

Slide 18

Slide 18 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS

Slide 19

Slide 19 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR SYSADMIN DC OPS

Slide 20

Slide 20 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS SYSADMIN DC OPS

Slide 21

Slide 21 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS SYSADMIN DC OPS WEEKS

Slide 22

Slide 22 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS SYSADMIN DC OPS WEEKS DAYS

Slide 23

Slide 23 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS SYSADMIN DC OPS WEEKS DAYS DAYS

Slide 24

Slide 24 text

Data center evolution ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS SYSADMIN DC OPS WEEKS DAYS DAYS DAYS

Slide 25

Slide 25 text

Cloud computing

Slide 26

Slide 26 text

Cloud computing ACQUIRE
 
 
 
 
 
 
 
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 SECONDS SECONDS SECONDS SECONDS

Slide 27

Slide 27 text

How do I provision resources?

Slide 28

Slide 28 text

How do I manage resource lifecycles?

Slide 29

Slide 29 text

How do I balance service providers providing core technology for my datacenter?

Slide 30

Slide 30 text

How do I enforce policy across all these resources?

Slide 31

Slide 31 text

How do I automate and share those configurations?

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

TERRAFORM'S GOAL Provide a single workflow…

Slide 34

Slide 34 text

TERRAFORM'S GOAL …with a unified view…

Slide 35

Slide 35 text

TERRAFORM'S GOAL …using Infrastructure as Code…

Slide 36

Slide 36 text

TERRAFORM'S GOAL …that can be iterated
 and changed safely…

Slide 37

Slide 37 text

TERRAFORM'S GOAL …capable of complex
 N-tier applications.

Slide 38

Slide 38 text

resource "digitalocean_droplet" "demo" {
 image = "ubuntu-17-10-x64"
 name = "phpCE"
 region = "fra1"
 size = "512mb"
 }
 
 resource "cloudflare_record" "demo" {
 domain = "grodzicki.pl"
 name = "phpce"
 type = "A"
 value = "${digitalocean_droplet.demo.ipv4_address}"
 }
 main.tf

Slide 39

Slide 39 text

$ terraform init
 
 Initializing provider plugins...
 - Downloading plugin for provider "digitalocean" (0.1.2)...
 - Downloading plugin for provider "cloudflare" (0.1.0)...
 
 Terraform has been successfully initialized! Terminal

Slide 40

Slide 40 text

$ terraform plan
 
 Terraform will perform the following actions:
 
 + cloudflare_record.demo
 id: 
 domain: "grodzicki.pl"
 hostname: 
 name: "phpce"
 proxied: "false"
 ttl: 
 type: "A"
 value: "${digitalocean_droplet.demo.ipv4_address}"
 zone_id: 
 
 + digitalocean_droplet.demo
 id: 
 disk: 
 image: "ubuntu-17-10-x64"
 ipv4_address: 
 ipv4_address_private: 
 ipv6_address: 
 ipv6_address_private: 
 locked: 
 name: "phpCE"
 price_hourly: 
 price_monthly: 
 region: "fra1"
 resize_disk: "true"
 size: "512mb"
 status: 
 vcpus: 
 
 Plan: 2 to add, 0 to change, 0 to destroy. Terminal

Slide 41

Slide 41 text

$ terraform apply
 
 digitalocean_droplet.demo: Creating...
 disk: "" => ""
 image: "" => "ubuntu-17-10-x64"
 ipv4_address: "" => ""
 ipv4_address_private: "" => ""
 ipv6_address: "" => ""
 ipv6_address_private: "" => ""
 locked: "" => ""
 name: "" => "phpCE"
 price_hourly: "" => ""
 price_monthly: "" => ""
 region: "" => "fra1"
 resize_disk: "" => "true"
 size: "" => "512mb"
 status: "" => ""
 vcpus: "" => ""
 digitalocean_droplet.demo: Creation complete after 26s (ID: 69048017)
 cloudflare_record.demo: Creating...
 domain: "" => "grodzicki.pl"
 hostname: "" => ""
 name: "" => "phpce"
 proxied: "" => "false"
 ttl: "" => ""
 type: "" => "A"
 value: "" => "207.154.225.151"
 zone_id: "" => ""
 cloudflare_record.demo: Creation complete after 1s (ID: 4a59cffb21560ea257b2567d362fec2b)
 
 Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Terminal

Slide 42

Slide 42 text

$ terraform destroy
 
 digitalocean_droplet.demo: Refreshing state... (ID: 69048513)
 cloudflare_record.demo: Refreshing state... (ID: c30fe74f5279d0def)
 cloudflare_record.demo: Destroying... (ID: c30fe74f5279d0def)
 cloudflare_record.demo: Destruction complete after 2s
 digitalocean_droplet.demo: Destroying... (ID: 69048513)
 digitalocean_droplet.demo: Destruction complete after 14s
 
 Destroy complete! Resources: 2 destroyed. Terminal

Slide 43

Slide 43 text

resource "digitalocean_droplet" "demo" {
 image = "ubuntu-17-10-x64"
 name = "phpCE"
 region = "fra1"
 - size = "512mb"
 + size = "1gb"
 }
 
 resource "cloudflare_record" "demo" {
 domain = "grodzicki.pl"
 name = "phpce"
 type = "A"
 value = "${digitalocean_droplet.demo.ipv4_address}"
 }
 main.tf

Slide 44

Slide 44 text

$ terraform plan
 
 Resource actions are indicated with the following symbols:
 ~ update in-place
 
 Terraform will perform the following actions:
 
 ~ digitalocean_droplet.demo
 size: "512mb" => "1gb"
 
 Plan: 0 to add, 1 to change, 0 to destroy. Terminal

Slide 45

Slide 45 text

$ terraform apply
 
 digitalocean_droplet.demo: Modifying... (ID: 69048968)
 size: "512mb" => "1gb"
 digitalocean_droplet.demo: Modifications complete after 53s (ID: 69048968)
 
 Apply complete! Resources: 0 added, 1 changed, 0 destroyed. Terminal

Slide 46

Slide 46 text

resource "digitalocean_droplet" "demo" {
 - image = "ubuntu-17-10-x64"
 + image = "debian-9-x64"
 name = "phpCE"
 region = "fra1"
 size = "1gb"
 }
 
 resource "cloudflare_record" "demo" {
 domain = "grodzicki.pl"
 name = "phpce"
 type = "A"
 value = "${digitalocean_droplet.demo.ipv4_address}"
 }
 main.tf

Slide 47

Slide 47 text

$ terraform plan
 
 Resource actions are indicated with the following symbols:
 ~ update in-place
 -/+ destroy and then create replacement
 
 Terraform will perform the following actions:
 ~ cloudflare_record.demo
 value: "46.101.143.229" => "${digitalocean_droplet.demo.ipv4_address}"
 
 -/+ digitalocean_droplet.demo (new resource required)
 id: "69048968" => (forces new resource)
 disk: "30" => 
 image: "ubuntu-17-10-x64" => "debian-9-x64" (forces new resource)
 ipv4_address: "46.101.143.229" => 
 ipv4_address_private: "" => 
 ipv6_address: "" => 
 ipv6_address_private: "" => 
 locked: "false" => 
 name: "phpCE" => "phpCE"
 price_hourly: "0.01488" => 
 price_monthly: "10" => 
 region: "fra1" => "fra1"
 resize_disk: "true" => "true"
 size: "1gb" => "1gb"
 status: "active" => 
 vcpus: "1" => 
 
 Plan: 1 to add, 1 to change, 1 to destroy. Terminal

Slide 48

Slide 48 text

$ terraform apply
 
 digitalocean_droplet.demo: Destroying... (ID: 69056095)
 digitalocean_droplet.demo: Destruction complete after 12s
 digitalocean_droplet.demo: Creating...
 disk: "" => ""
 image: "" => "debian-9-x64"
 ipv4_address: "" => ""
 ipv4_address_private: "" => ""
 ipv6_address: "" => ""
 ipv6_address_private: "" => ""
 locked: "" => ""
 name: "" => "phpCE"
 price_hourly: "" => ""
 price_monthly: "" => ""
 region: "" => "fra1"
 resize_disk: "" => "true"
 size: "" => "1gb"
 status: "" => ""
 vcpus: "" => ""
 digitalocean_droplet.demo: Creation complete after 47s (ID: 69056200)
 
 cloudflare_record.demo: Modifying... (ID: 7a5ad9e5a510eb3a87606bbacf2ccbec)
 value: "207.154.230.75" => "165.227.146.145"
 cloudflare_record.demo: Modifications complete after 3s (ID: 7a5ad9e5a510eb3a87606bbacf2ccbec)
 
 Apply complete! Resources: 1 added, 1 changed, 1 destroyed. Terminal

Slide 49

Slide 49 text

Human-friendly configuration JSON-compatible for non-humans

Slide 50

Slide 50 text

VCS-friendly format

Slide 51

Slide 51 text

Entire infrastructure as code

Slide 52

Slide 52 text

70+ providers AWS Bitbucket Chef Cloudflare Consul Datadog DigitalOcean DNSimple Docker Dyn Fastly GitHub Google Cloud Grafana Heroku Kubernetes Logentries MySQL New Relic Nomad NS1 OpenStack OVH Rancher Scaleway SoftLayer VMware

Slide 53

Slide 53 text

resource "github_team" "backend" {
 name = "backend"
 }
 
 resource "github_team_membership" "sebastian" {
 team_id = "${github_team.backend.id}"
 username = "sgrodzicki"
 } main.tf

Slide 54

Slide 54 text

$ terraform plan
 
 Resource actions are indicated with the following symbols:
 + create
 
 Terraform will perform the following actions:
 
 + github_team.backend
 id: 
 name: "backend"
 privacy: "secret"
 
 + github_team_membership.sebastian
 id: 
 role: "member"
 team_id: "${github_team.backend.id}"
 username: "sgrodzicki"
 
 Plan: 2 to add, 0 to change, 0 to destroy. Terminal

Slide 55

Slide 55 text

$ terraform apply
 
 github_team.backend: Creating...
 name: "" => "backend"
 privacy: "" => "secret"
 github_team.backend: Creation complete after 1s (ID: 2541906)
 
 github_team_membership.sebastian: Creating...
 role: "" => "member"
 team_id: "" => "2541906"
 username: "" => "sgrodzicki"
 github_team_membership.sebastian: Creation complete after 1s (ID: 2541906:sgrodzicki)
 
 Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Terminal

Slide 56

Slide 56 text

resource "github_repository" "phpce" {
 name = "phpce"
 description = "phpCE 2017"
 } main.tf

Slide 57

Slide 57 text

$ terraform plan
 
 Resource actions are indicated with the following symbols:
 + create
 
 Terraform will perform the following actions:
 
 + github_repository.phpce
 id: 
 allow_merge_commit: "true"
 allow_rebase_merge: "true"
 allow_squash_merge: "true"
 default_branch: 
 description: "phpCE 2017"
 full_name: 
 git_clone_url: 
 http_clone_url: 
 name: "phpce"
 ssh_clone_url: 
 svn_url: 
 
 Plan: 1 to add, 0 to change, 0 to destroy. Terminal

Slide 58

Slide 58 text

$ terraform apply
 
 github_repository.phpce: Creating...
 allow_merge_commit: "" => "true"
 allow_rebase_merge: "" => "true"
 allow_squash_merge: "" => "true"
 default_branch: "" => ""
 description: "" => "phpCE 2017"
 full_name: "" => ""
 git_clone_url: "" => ""
 http_clone_url: "" => ""
 name: "" => "phpce"
 ssh_clone_url: "" => ""
 svn_url: "" => ""
 
 github_repository.phpce: Creation complete after 1s (ID: phpce)
 
 Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Terminal

Slide 59

Slide 59 text

Demo

Slide 60

Slide 60 text

$ terraform console Interactive console
 for Terraform interpolations

Slide 61

Slide 61 text

$ terraform fmt Rewrites config files
 to canonical format

Slide 62

Slide 62 text

$ terraform graph Create a visual graph
 of Terraform resources

Slide 63

Slide 63 text

$ terraform graph cloudflare_record.demo digitalocean_droplet.demo provider.cloudflare provider.digitalocean [root] meta.count-boundary (count boundary fixup) [root] provider.cloudflare (close) [root] provider.digitalocean (close) [root] root

Slide 64

Slide 64 text

$ terraform import Import existing infrastructure
 into Terraform

Slide 65

Slide 65 text

$ terraform output Read an output from a state file

Slide 66

Slide 66 text

$ terraform state list (List resources in the state) mv (Move an item in the state) pull (Pull current state and output to stdout) push (Update remote state from a local state file) rm (Remove an item from the state) show (Show a resource in the state)

Slide 67

Slide 67 text

module "stack" {
 source = "github.com/segmentio/stack"
 environment = "demo"
 key_name = "sgrodzicki"
 name = "phpCE"
 } main.tf

Slide 68

Slide 68 text

Terraform Website

Slide 69

Slide 69 text

Terraform Documentation

Slide 70

Slide 70 text

Terraform Module Registry

Slide 71

Slide 71 text

Questions? joind.in/talk/49431

Slide 72

Slide 72 text

THANK YOU! joind.in/talk/49431