Infrastructure as Code @ DevOpsDay Warsaw 2019

Infrastructure as Code @ DevOpsDay Warsaw 2019

Terraform enables you to safely and predictably create, change, and improve production infrastructure. It is an open source tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned. Terraform has emerged as a key player in the DevOps world for defining, launching, and managing infrastructure as code (IAC) across a variety of cloud and virtualization platforms, including AWS, Google Cloud, and Azure. In this talk I'll show you how to get up and running with Terraform using IaaS (e.g. AWS, DigitalOcean) or SaaS providers (e.g. CloudFlare, GitHub).

9a328142924c93e5e148c75356ba6d42?s=128

Sebastian Grodzicki

November 25, 2019
Tweet

Transcript

  1. Infrastructure as Code Sebastian Grodzicki @ DevOpsDay 2019 @sebgrodzicki

  2. $ whoami Sebastian Grodzicki
 • Engineering Manager at • ex-CTO

    at SHOWROOM & GoldenLine • #LifeAtElastic @sebgrodzicki
  3. module "stack" {
 source = "github.com/segmentio/stack"
 environment = "demo"
 key_name

    = "sgrodzicki"
 name = "WDI"
 }
 main.tf
  4. None
  5. None
  6. None
  7. None
  8. How did we get here?

  9. Data center evolution DC

  10. Data center evolution DC

  11. Data center evolution DC

  12. Data center evolution DC VM VM VM VM VM VM

    VM VM VM VM VM VM
  13. 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
  14. Data center evolution 
 DNS 
 CDN

  15. Data center evolution PaaS IaaS SaaS

  16. Data center evolution ACQUIRE
 
 
 
 
 
 


    
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 

  17. Data center evolution ACQUIRE
 
 
 
 
 
 


    
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR
  18. Data center evolution ACQUIRE
 
 
 
 
 
 


    
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS
  19. Data center evolution ACQUIRE
 
 
 
 
 
 


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


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


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


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


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


    
 
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 VENDOR DC OPS SYSADMIN DC OPS WEEKS DAYS DAYS DAYS
  25. Cloud computing

  26. Cloud computing ACQUIRE
 
 
 
 
 
 
 


    
 
 DESTROY
 
 
 
 
 
 
 
 
 
 PROVISION
 
 
 
 
 
 
 
 
 
 UPDATE
 
 
 
 
 
 
 
 
 
 SECONDS SECONDS SECONDS SECONDS
  27. How do I provision resources?

  28. How do I manage resource lifecycles?

  29. How do I balance service providers providing core technology for

    my datacenter?
  30. How do I enforce policy across all these resources?

  31. How do I automate and share those configurations?

  32. None
  33. TERRAFORM'S GOAL Provide a single workflow…

  34. TERRAFORM'S GOAL …with a unified view…

  35. TERRAFORM'S GOAL …using Infrastructure as Code…

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

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

  38. resource "digitalocean_droplet" "demo" {
 image = "ubuntu-18-10-x64"
 name = "WDI"


    region = "fra1"
 size = "s-1vcpu-1gb"
 }
 
 resource "cloudflare_record" "demo" {
 domain = "grodzicki.pl"
 name = "wdi"
 type = "A"
 value = "${digitalocean_droplet.demo.ipv4_address}"
 } main.tf
  39. $ terraform init
 
 Initializing provider plugins...
 - Checking for

    available provider plugins on https:// releases.hashicorp.com...
 - Downloading plugin for provider "cloudflare" (1.12.0)...
 - Downloading plugin for provider "digitalocean" (1.1.0)...
 
 Terraform has been successfully initialized! Terminal
  40. $ terraform plan
 
 Terraform will perform the following actions:


    
 + cloudflare_record.demo
 id: <computed>
 created_on: <computed>
 domain: "grodzicki.pl"
 hostname: <computed>
 metadata.%: <computed>
 modified_on: <computed>
 name: "wdi"
 proxiable: <computed>
 proxied: "false"
 ttl: <computed>
 type: "A"
 value: "${digitalocean_droplet.demo.ipv4_address}"
 zone_id: <computed>
 
 + digitalocean_droplet.demo
 id: <computed>
 backups: "false"
 disk: <computed>
 image: "ubuntu-18-10-x64"
 ipv4_address: <computed>
 ipv4_address_private: <computed>
 ipv6: "false"
 ipv6_address: <computed>
 ipv6_address_private: <computed>
 locked: <computed>
 memory: <computed>
 monitoring: "false"
 name: "WDI"
 price_hourly: <computed>
 price_monthly: <computed>
 private_networking: "false"
 region: "fra1"
 resize_disk: "true"
 size: "s-1vcpu-1gb"
 status: <computed>
 vcpus: <computed>
 volume_ids.#: <computed>
 
 Plan: 2 to add, 0 to change, 0 to destroy. Terminal
  41. $ terraform apply
 
 digitalocean_droplet.demo: Creating...
 backups: "" => "false"


    disk: "" => "<computed>"
 image: "" => "ubuntu-18-10-x64"
 ipv4_address: "" => "<computed>"
 ipv4_address_private: "" => "<computed>"
 ipv6: "" => "false"
 ipv6_address: "" => "<computed>"
 ipv6_address_private: "" => "<computed>"
 locked: "" => "<computed>"
 memory: "" => "<computed>"
 monitoring: "" => "false"
 name: "" => "WDI"
 price_hourly: "" => "<computed>"
 price_monthly: "" => "<computed>"
 private_networking: "" => "false"
 region: "" => "fra1"
 resize_disk: "" => "true"
 size: "" => "s-1vcpu-1gb"
 status: "" => "<computed>"
 vcpus: "" => "<computed>"
 volume_ids.#: "" => "<computed>"
 
 digitalocean_droplet.demo: Creation complete after 36s (ID: 137339900)
 
 cloudflare_record.demo: Creating...
 created_on: "" => "<computed>"
 domain: "" => "grodzicki.pl"
 hostname: "" => "<computed>"
 metadata.%: "" => "<computed>"
 modified_on: "" => "<computed>"
 name: "" => "wdi"
 proxiable: "" => "<computed>"
 proxied: "" => "false"
 ttl: "" => "<computed>"
 type: "" => "A"
 value: "" => "134.209.240.227"
 zone_id: "" => "<computed>"
 
 cloudflare_record.demo: Creation complete after 2s (ID: 02e2198170dba247e7177e7b59a3aa16)
 
 Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Terminal
  42. $ terraform destroy
 
 digitalocean_droplet.demo: Refreshing state... (ID: 137339900)
 cloudflare_record.demo:

    Refreshing state... (ID: 02e2198170dba247e7177e7b59a3aa16)
 
 cloudflare_record.demo: Destroying... (ID: 02e2198170dba247e7177e7b59a3aa16)
 cloudflare_record.demo: Destruction complete after 1s
 
 digitalocean_droplet.demo: Destroying... (ID: 137339900)
 digitalocean_droplet.demo: Still destroying... (ID: 137339900, 10s elapsed)
 digitalocean_droplet.demo: Destruction complete after 12s
 
 Destroy complete! Resources: 2 destroyed. Terminal
  43. resource "digitalocean_droplet" "demo" {
 image = "ubuntu-18-10-x64"
 name = "WDI"


    region = "fra1"
 - size = "s-1vcpu-1gb"
 + size = "s-1vcpu-2gb"
 }
 
 resource "cloudflare_record" "demo" {
 domain = "grodzicki.pl"
 name = "wdi"
 type = "A"
 value = "${digitalocean_droplet.demo.ipv4_address}"
 } main.tf
  44. $ terraform plan
 
 Resource actions are indicated with the

    following symbols:
 ~ update in-place
 
 Terraform will perform the following actions:
 
 ~ digitalocean_droplet.demo
 size: "s-1vcpu-1gb" => "s-1vcpu-2gb"
 
 Plan: 0 to add, 1 to change, 0 to destroy. Terminal
  45. $ terraform apply
 
 digitalocean_droplet.demo: Refreshing state... (ID: 137341062)
 cloudflare_record.demo:

    Refreshing state... (ID: d1ad18b09494e7c865620379ba84fb11)
 
 digitalocean_droplet.demo: Modifying... (ID: 137341062)
 size: "s-1vcpu-1gb" => "s-1vcpu-2gb"
 digitalocean_droplet.demo: Modifications complete after 1m9s (ID: 137341062)
 
 Apply complete! Resources: 0 added, 1 changed, 0 destroyed. Terminal
  46. resource "digitalocean_droplet" "demo" {
 - image = "ubuntu-18-10-x64"
 + image

    = "debian-9-x64"
 name = "WDI"
 region = "fra1"
 size = "s-1vcpu-2gb"
 }
 
 resource "cloudflare_record" "demo" {
 domain = "grodzicki.pl"
 name = "wdi"
 type = "A"
 value = "${digitalocean_droplet.demo.ipv4_address}"
 } main.tf
  47. $ 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: "134.209.226.251" => "${digitalocean_droplet.demo.ipv4_address}"
 
 -/+ digitalocean_droplet.demo (new resource required)
 id: "137341968" => <computed> (forces new resource)
 backups: "false" => "false"
 disk: "50" => <computed>
 image: "ubuntu-18-10-x64" => "debian-9-x64" (forces new resource)
 ipv4_address: "134.209.226.251" => <computed>
 ipv4_address_private: "" => <computed>
 ipv6: "false" => "false"
 ipv6_address: "" => <computed>
 ipv6_address_private: "" => <computed>
 locked: "false" => <computed>
 memory: "2048" => <computed>
 monitoring: "false" => "false"
 name: "WDI" => "WDI"
 price_hourly: "0.01488" => <computed>
 price_monthly: "10" => <computed>
 private_networking: "false" => "false"
 region: "fra1" => "fra1"
 resize_disk: "true" => "true"
 size: "s-1vcpu-2gb" => "s-1vcpu-2gb"
 status: "active" => <computed>
 vcpus: "1" => <computed>
 volume_ids.#: "0" => <computed>
 
 Plan: 1 to add, 1 to change, 1 to destroy. Terminal
  48. $ terraform apply
 
 digitalocean_droplet.demo: Destroying... (ID: 137341968)
 digitalocean_droplet.demo: Destruction

    complete after 12s
 digitalocean_droplet.demo: Creating...
 backups: "" => "false"
 disk: "" => "<computed>"
 image: "" => "debian-9-x64"
 ipv4_address: "" => "<computed>"
 ipv4_address_private: "" => "<computed>"
 ipv6: "" => "false"
 ipv6_address: "" => "<computed>"
 ipv6_address_private: "" => "<computed>"
 locked: "" => "<computed>"
 memory: "" => "<computed>"
 monitoring: "" => "false"
 name: "" => "WDI"
 price_hourly: "" => "<computed>"
 price_monthly: "" => "<computed>"
 private_networking: "" => "false"
 region: "" => "fra1"
 resize_disk: "" => "true"
 size: "" => "s-1vcpu-2gb"
 status: "" => "<computed>"
 vcpus: "" => "<computed>"
 volume_ids.#: "" => "<computed>"
 digitalocean_droplet.demo: Creation complete after 35s (ID: 137342688)
 
 cloudflare_record.demo: Modifying... (ID: b99a42e66c68a8a5a0a19f1a27821a80)
 value: "134.209.226.251" => "46.101.143.241"
 cloudflare_record.demo: Modifications complete after 1s (ID: b99a42e66c68a8a5a0a19f1a27821a80)
 
 Apply complete! Resources: 1 added, 1 changed, 1 destroyed. Terminal
  49. Human-friendly configuration JSON-compatible for non-humans

  50. VCS-friendly format

  51. Entire infrastructure as code

  52. 100+ 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
  53. resource "github_team" "wdi" {
 name = "WDI"
 }
 
 resource

    "github_team_membership" "sebastian" {
 team_id = "${github_team.wdi.id}"
 username = "sgrodzicki"
 } main.tf
  54. $ terraform plan
 
 Resource actions are indicated with the

    following symbols:
 + create
 
 Terraform will perform the following actions:
 
 + github_team.wdi
 id: <computed>
 etag: <computed>
 name: "WDI"
 privacy: "secret"
 slug: <computed>
 
 + github_team_membership.sebastian
 id: <computed>
 etag: <computed>
 role: "member"
 team_id: "${github_team.wdi.id}"
 username: "sgrodzicki"
 
 Plan: 2 to add, 0 to change, 0 to destroy. Terminal
  55. $ terraform apply
 
 github_team.wdi: Creating...
 etag: "" => "<computed>"


    name: "" => "WDI"
 privacy: "" => "secret"
 slug: "" => "<computed>"
 github_team.wdi: Creation complete after 2s (ID: 3174820)
 
 github_team_membership.sebastian: Creating...
 etag: "" => "<computed>"
 role: "" => "member"
 team_id: "" => "3174820"
 username: "" => "sgrodzicki"
 github_team_membership.sebastian: Creation complete after 2s (ID: 3174820:sgrodzicki)
 
 Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Terminal
  56. resource "github_repository" "wdi" {
 name = "wdi"
 description = "WDI

    2019"
 } main.tf
  57. $ terraform plan
 
 Resource actions are indicated with the

    following symbols:
 + create
 
 Terraform will perform the following actions:
 
 + github_repository.wdi
 id: <computed>
 allow_merge_commit: "true"
 allow_rebase_merge: "true"
 allow_squash_merge: "true"
 archived: "false"
 default_branch: <computed>
 description: "WDI 2019"
 etag: <computed>
 full_name: <computed>
 git_clone_url: <computed>
 html_url: <computed>
 http_clone_url: <computed>
 name: "wdi"
 ssh_clone_url: <computed>
 svn_url: <computed>
 
 Plan: 1 to add, 0 to change, 0 to destroy. Terminal
  58. $ terraform apply
 
 github_repository.wdi: Creating...
 allow_merge_commit: "" => "true"


    allow_rebase_merge: "" => "true"
 allow_squash_merge: "" => "true"
 archived: "" => "false"
 default_branch: "" => "<computed>"
 description: "" => "WDI 2019"
 etag: "" => "<computed>"
 full_name: "" => "<computed>"
 git_clone_url: "" => "<computed>"
 html_url: "" => "<computed>"
 http_clone_url: "" => "<computed>"
 name: "" => "wdi"
 ssh_clone_url: "" => "<computed>"
 svn_url: "" => "<computed>"
 
 github_repository.wdi: Creation complete after 3s (ID: wdi)
 
 Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Terminal
  59. Demo

  60. None
  61. $ terraform console Interactive console
 for Terraform interpolations

  62. $ terraform fmt Rewrites config files
 to canonical format

  63. $ terraform graph Create a visual graph
 of Terraform resources

  64. $ 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
  65. $ terraform import Import existing infrastructure
 into Terraform

  66. $ terraform output Read an output from a state file

  67. $ 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)
  68. module "stack" {
 source = "github.com/segmentio/stack"
 environment = "demo"
 key_name

    = "sgrodzicki"
 name = "WDI"
 }
 main.tf
  69. Terraform Website

  70. Terraform Documentation

  71. Terraform Module Registry

  72. THANK YOU!