Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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).

Sebastian Grodzicki

November 25, 2019
Tweet

More Decks by Sebastian Grodzicki

Other Decks in Technology

Transcript

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

    View full-size slide

  2. $ whoami
    Sebastian Grodzicki

    • Engineering Manager at
    • ex-CTO at SHOWROOM & GoldenLine
    • #LifeAtElastic
    @sebgrodzicki

    View full-size slide

  3. module "stack" {

    source = "github.com/segmentio/stack"

    environment = "demo"

    key_name = "sgrodzicki"

    name = "WDI"

    }

    main.tf

    View full-size slide

  4. How did we get here?

    View full-size slide

  5. Data center evolution
    DC

    View full-size slide

  6. Data center evolution
    DC

    View full-size slide

  7. Data center evolution
    DC

    View full-size slide

  8. Data center evolution
    DC
    VM VM
    VM
    VM
    VM VM
    VM
    VM
    VM VM
    VM
    VM

    View full-size slide

  9. 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

    View full-size slide

  10. Data center evolution

    DNS

    CDN

    View full-size slide

  11. Data center evolution
    PaaS
    IaaS SaaS

    View full-size slide

  12. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    View full-size slide

  13. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR

    View full-size slide

  14. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR DC OPS

    View full-size slide

  15. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR SYSADMIN
    DC OPS

    View full-size slide

  16. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR DC OPS
    SYSADMIN
    DC OPS

    View full-size slide

  17. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR DC OPS
    SYSADMIN
    DC OPS
    WEEKS

    View full-size slide

  18. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR DC OPS
    SYSADMIN
    DC OPS
    WEEKS DAYS

    View full-size slide

  19. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR DC OPS
    SYSADMIN
    DC OPS
    WEEKS DAYS DAYS

    View full-size slide

  20. Data center evolution
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    VENDOR DC OPS
    SYSADMIN
    DC OPS
    WEEKS DAYS DAYS DAYS

    View full-size slide

  21. Cloud computing

    View full-size slide

  22. Cloud computing
    ACQUIRE










    DESTROY










    PROVISION










    UPDATE










    SECONDS SECONDS SECONDS SECONDS

    View full-size slide

  23. How do I provision resources?

    View full-size slide

  24. How do I manage resource
    lifecycles?

    View full-size slide

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

    View full-size slide

  26. How do I enforce policy across all
    these resources?

    View full-size slide

  27. How do I automate and share
    those configurations?

    View full-size slide

  28. TERRAFORM'S GOAL
    Provide a single workflow…

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  31. TERRAFORM'S GOAL
    …that can be iterated

    and changed safely…

    View full-size slide

  32. TERRAFORM'S GOAL
    …capable of complex

    N-tier applications.

    View full-size slide

  33. 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

    View full-size slide

  34. $ 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

    View full-size slide

  35. $ terraform plan


    Terraform will perform the following actions:


    + cloudflare_record.demo

    id: 

    created_on: 

    domain: "grodzicki.pl"

    hostname: 

    metadata.%: 

    modified_on: 

    name: "wdi"

    proxiable: 

    proxied: "false"

    ttl: 

    type: "A"

    value: "${digitalocean_droplet.demo.ipv4_address}"

    zone_id: 


    + digitalocean_droplet.demo

    id: 

    backups: "false"

    disk: 

    image: "ubuntu-18-10-x64"

    ipv4_address: 

    ipv4_address_private: 

    ipv6: "false"

    ipv6_address: 

    ipv6_address_private: 

    locked: 

    memory: 

    monitoring: "false"

    name: "WDI"

    price_hourly: 

    price_monthly: 

    private_networking: "false"

    region: "fra1"

    resize_disk: "true"

    size: "s-1vcpu-1gb"

    status: 

    vcpus: 

    volume_ids.#: 


    Plan: 2 to add, 0 to change, 0 to destroy.
    Terminal

    View full-size slide

  36. $ terraform apply


    digitalocean_droplet.demo: Creating...

    backups: "" => "false"

    disk: "" => ""

    image: "" => "ubuntu-18-10-x64"

    ipv4_address: "" => ""

    ipv4_address_private: "" => ""

    ipv6: "" => "false"

    ipv6_address: "" => ""

    ipv6_address_private: "" => ""

    locked: "" => ""

    memory: "" => ""

    monitoring: "" => "false"

    name: "" => "WDI"

    price_hourly: "" => ""

    price_monthly: "" => ""

    private_networking: "" => "false"

    region: "" => "fra1"

    resize_disk: "" => "true"

    size: "" => "s-1vcpu-1gb"

    status: "" => ""

    vcpus: "" => ""

    volume_ids.#: "" => ""


    digitalocean_droplet.demo: Creation complete after 36s (ID: 137339900)


    cloudflare_record.demo: Creating...

    created_on: "" => ""

    domain: "" => "grodzicki.pl"

    hostname: "" => ""

    metadata.%: "" => ""

    modified_on: "" => ""

    name: "" => "wdi"

    proxiable: "" => ""

    proxied: "" => "false"

    ttl: "" => ""

    type: "" => "A"

    value: "" => "134.209.240.227"

    zone_id: "" => ""


    cloudflare_record.demo: Creation complete after 2s (ID: 02e2198170dba247e7177e7b59a3aa16)


    Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
    Terminal

    View full-size slide

  37. $ 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

    View full-size slide

  38. 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

    View full-size slide

  39. $ 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

    View full-size slide

  40. $ 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

    View full-size slide

  41. 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

    View full-size slide

  42. $ 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" => (forces new resource)

    backups: "false" => "false"

    disk: "50" => 

    image: "ubuntu-18-10-x64" => "debian-9-x64" (forces new resource)

    ipv4_address: "134.209.226.251" => 

    ipv4_address_private: "" => 

    ipv6: "false" => "false"

    ipv6_address: "" => 

    ipv6_address_private: "" => 

    locked: "false" => 

    memory: "2048" => 

    monitoring: "false" => "false"

    name: "WDI" => "WDI"

    price_hourly: "0.01488" => 

    price_monthly: "10" => 

    private_networking: "false" => "false"

    region: "fra1" => "fra1"

    resize_disk: "true" => "true"

    size: "s-1vcpu-2gb" => "s-1vcpu-2gb"

    status: "active" => 

    vcpus: "1" => 

    volume_ids.#: "0" => 


    Plan: 1 to add, 1 to change, 1 to destroy.
    Terminal

    View full-size slide

  43. $ terraform apply


    digitalocean_droplet.demo: Destroying... (ID: 137341968)

    digitalocean_droplet.demo: Destruction complete after 12s

    digitalocean_droplet.demo: Creating...

    backups: "" => "false"

    disk: "" => ""

    image: "" => "debian-9-x64"

    ipv4_address: "" => ""

    ipv4_address_private: "" => ""

    ipv6: "" => "false"

    ipv6_address: "" => ""

    ipv6_address_private: "" => ""

    locked: "" => ""

    memory: "" => ""

    monitoring: "" => "false"

    name: "" => "WDI"

    price_hourly: "" => ""

    price_monthly: "" => ""

    private_networking: "" => "false"

    region: "" => "fra1"

    resize_disk: "" => "true"

    size: "" => "s-1vcpu-2gb"

    status: "" => ""

    vcpus: "" => ""

    volume_ids.#: "" => ""

    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

    View full-size slide

  44. Human-friendly configuration
    JSON-compatible for non-humans

    View full-size slide

  45. VCS-friendly format

    View full-size slide

  46. Entire infrastructure as code

    View full-size slide

  47. 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

    View full-size slide

  48. resource "github_team" "wdi" {

    name = "WDI"

    }


    resource "github_team_membership" "sebastian" {

    team_id = "${github_team.wdi.id}"

    username = "sgrodzicki"

    }
    main.tf

    View full-size slide

  49. $ terraform plan


    Resource actions are indicated with the following symbols:

    + create


    Terraform will perform the following actions:


    + github_team.wdi

    id: 

    etag: 

    name: "WDI"

    privacy: "secret"

    slug: 


    + github_team_membership.sebastian

    id: 

    etag: 

    role: "member"

    team_id: "${github_team.wdi.id}"

    username: "sgrodzicki"


    Plan: 2 to add, 0 to change, 0 to destroy.
    Terminal

    View full-size slide

  50. $ terraform apply


    github_team.wdi: Creating...

    etag: "" => ""

    name: "" => "WDI"

    privacy: "" => "secret"

    slug: "" => ""

    github_team.wdi: Creation complete after 2s (ID: 3174820)


    github_team_membership.sebastian: Creating...

    etag: "" => ""

    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

    View full-size slide

  51. resource "github_repository" "wdi" {

    name = "wdi"

    description = "WDI 2019"

    }
    main.tf

    View full-size slide

  52. $ terraform plan


    Resource actions are indicated with the following symbols:

    + create


    Terraform will perform the following actions:


    + github_repository.wdi

    id: 

    allow_merge_commit: "true"

    allow_rebase_merge: "true"

    allow_squash_merge: "true"

    archived: "false"

    default_branch: 

    description: "WDI 2019"

    etag: 

    full_name: 

    git_clone_url: 

    html_url: 

    http_clone_url: 

    name: "wdi"

    ssh_clone_url: 

    svn_url: 


    Plan: 1 to add, 0 to change, 0 to destroy.
    Terminal

    View full-size slide

  53. $ terraform apply


    github_repository.wdi: Creating...

    allow_merge_commit: "" => "true"

    allow_rebase_merge: "" => "true"

    allow_squash_merge: "" => "true"

    archived: "" => "false"

    default_branch: "" => ""

    description: "" => "WDI 2019"

    etag: "" => ""

    full_name: "" => ""

    git_clone_url: "" => ""

    html_url: "" => ""

    http_clone_url: "" => ""

    name: "" => "wdi"

    ssh_clone_url: "" => ""

    svn_url: "" => ""


    github_repository.wdi: Creation complete after 3s (ID: wdi)


    Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
    Terminal

    View full-size slide

  54. $ terraform console
    Interactive console

    for Terraform interpolations

    View full-size slide

  55. $ terraform fmt
    Rewrites config files

    to canonical format

    View full-size slide

  56. $ terraform graph
    Create a visual graph

    of Terraform resources

    View full-size slide

  57. $ 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

    View full-size slide

  58. $ terraform import
    Import existing infrastructure

    into Terraform

    View full-size slide

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

    View full-size slide

  60. $ 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)

    View full-size slide

  61. module "stack" {

    source = "github.com/segmentio/stack"

    environment = "demo"

    key_name = "sgrodzicki"

    name = "WDI"

    }

    main.tf

    View full-size slide

  62. Terraform Website

    View full-size slide

  63. Terraform Documentation

    View full-size slide

  64. Terraform Module Registry

    View full-size slide