Úvod do Terraformu pro začátečníky – Kurz Terraform

Photo of author

By etechblogcz

Zajímá vás, co je to Terraform? Pojďme se na to podívat.

Koncept Infrastruktury jako kódu (IaC) je mezi odborníky na DevOps velmi populární. Jedná se o proces správy a zajišťování kompletní IT infrastruktury (včetně fyzických i virtuálních serverů) pomocí strojově čitelných konfiguračních souborů. Je to v podstatě softwarový inženýrský přístup k operacím. Pomáhá automatizovat celé datové centrum pomocí skriptů.

Přestože Infrastruktura jako kód nabízí mnoho výhod, přináší i několik výzev:

  • Je nutná znalost programování.
  • Je obtížné odhadnout dopad změn.
  • Někdy je potřeba změny vrátit zpět.
  • Sledování změn může být problematické.
  • Automatizace zdrojů může být složitá.
  • Správa více infrastrukturních prostředí je náročná.

Terraform byl vytvořen, aby tyto problémy vyřešil.

Co je Terraform?

Terraform je open-source nástroj pro infrastrukturu jako kód, vyvinutý společností HashiCorp. Používá se k definování a poskytování celé infrastruktury pomocí snadno osvojitelného deklarativního jazyka.

Jedná se o nástroj pro správu infrastruktury, kde můžete nastavení cloudové infrastruktury uchovávat jako kód. Podobá se nástrojům, jako je například
CloudFormation, který se používá pro automatizaci infrastruktury AWS, ale je omezen pouze na AWS. Terraform však lze využít i na jiných cloudových platformách.

Níže uvádíme některé výhody používání Terraformu:

  • Zajišťuje orchestraci, nejen konfiguraci.
  • Podporuje mnoho poskytovatelů, jako jsou AWS, Azure, GCP, DigitalOcean a další.
  • Umožňuje vytvářet neměnnou infrastrukturu, kde se konfigurace plynule mění.
  • Využívá jednoduchý jazyk HCL (HashiCorp Configuration Language).
  • Je snadno přenositelný mezi různými poskytovateli.
  • Podporuje pouze klientskou architekturu, takže není nutná další správa konfigurace na serveru.

Základní koncepty Terraformu

Následují klíčové pojmy a terminologie používané v Terraformu:

  • Proměnné: Také známé jako vstupní proměnné, jsou to páry klíč-hodnota používané moduly Terraformu pro přizpůsobení.
  • Poskytovatel: Je to plugin, který umožňuje interakci s API dané služby a přístup k jejím zdrojům.
  • Modul: Jedná se o složku s šablonami Terraformu, která obsahuje veškerá nastavení.
  • Stav: Obsahuje uložené informace o infrastruktuře spravované Terraformem a jejích konfiguracích.
  • Zdroje: Představují blok jednoho nebo více objektů infrastruktury (např. výpočetní instance, virtuální sítě), které se používají pro konfiguraci a správu infrastruktury.
  • Zdroj dat: Implementovaný poskytovateli pro načtení informací o externích objektech do Terraformu.
  • Výstupní hodnoty: Jedná se o návratové hodnoty modulu Terraformu, které mohou být použity v jiných konfiguracích.
  • Plán: Je to fáze, ve které se určuje, co se má vytvořit, aktualizovat nebo zrušit, aby se infrastruktura dostala z aktuálního do požadovaného stavu.
  • Použít: Je to fáze, ve které se provádějí změny v infrastruktuře, aby se dosáhlo požadovaného stavu.

Životní cyklus Terraformu

Životní cyklus Terraformu se skládá z těchto fází: inicializace, plánování, použití a zrušení.

  • Terraform init inicializuje pracovní adresář, který obsahuje všechny konfigurační soubory.
  • Plán Terraform vytváří plán provádění pro dosažení požadovaného stavu infrastruktury. Změny v konfiguračních souborech se provádějí za účelem dosažení cílového stavu.
  • Terraform apply provede změny v infrastruktuře podle definovaného plánu, a infrastruktura se tak dostane do požadovaného stavu.
  • Terraform destroy se používá k odstranění všech zdrojů staré infrastruktury, které jsou po aplikaci označeny jako nepotřebné.

Jak funguje Terraform?

Architektura Terraformu se skládá ze dvou hlavních komponent:

Jádro Terraformu

Jádro Terraformu využívá dva vstupní zdroje:

Prvním zdrojem je konfigurace Terraformu, kterou definujete. Zde specifikujete, co má být vytvořeno nebo zajištěno. Druhým zdrojem je stav, který Terraform udržuje a který odráží aktuální nastavení infrastruktury.

Jádro Terraformu tedy na základě těchto vstupů určí, co je třeba udělat. Porovnává aktuální stav a požadovanou konfiguraci a zjišťuje, jaké změny jsou nutné. Určí, co je třeba vytvořit, aktualizovat nebo smazat, aby se infrastruktura dostala do požadovaného stavu.

Poskytovatelé

Druhou součástí architektury jsou poskytovatelé pro konkrétní technologie. Mohou to být poskytovatelé cloudu jako AWS, Azure, GCP, nebo i jiné platformy a služby. Může to být také poskytovatel komponent na vyšší úrovni, jako je Kubernetes, nebo i jiný software.

To vám dává možnost vytvářet infrastrukturu na různých úrovních.

Například – vytvoříte infrastrukturu AWS, nasadíte na ni Kubernetes, a pak uvnitř tohoto clusteru vytvoříte služby/komponenty.

Terraform má přes sto poskytovatelů pro různé technologie a každý z nich umožňuje uživateli Terraformu přístup k jeho zdrojům. Například prostřednictvím poskytovatele AWS máte přístup ke stovkám zdrojů AWS, jako jsou instance EC2, uživatelé AWS atd. S poskytovatelem Kubernetes máte přístup ke zdrojům, jako jsou služby, nasazení, jmenné prostory atd.

Terraform tedy funguje tak, že se snaží pokrýt kompletní nastavení aplikace od infrastruktury až po samotnou aplikaci.

Pojďme si vyzkoušet pár praktických příkladů. 👨‍💻

Nainstalujeme Terraform na Ubuntu a vytvoříme základní infrastrukturu.

Instalace Terraformu

Stáhněte si nejnovější balíček Terraformu.

Na oficiální stránce ke stažení najdete nejnovější verzi pro váš operační systém.

    [email protected]:~$ wget https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip
    --2020-08-14 16:55:38--
    https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip
    Resolving releases.hashicorp.com (releases.hashicorp.com)... 151.101.153.183, 2a04:4e42:24::439
    Connecting to releases.hashicorp.com (releases.hashicorp.com)|151.101.153.183|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 34851622 (33M) [application/zip]
    Saving to: ‘terraform_0.13.0_linux_amd64.zip’

    terraform_0.13.0_linux_amd64.zip
    100%[=================================================================>] 33.24M  90.3KB/s    in 5m 28s

    2020-08-14 17:01:06 (104 KB/s) - ‘terraform_0.13.0_linux_amd64.zip’ saved [34851622/34851622]
  

Rozbalte stažený balíček.

    [email protected]:~$ unzip terraform_0.13.0_linux_amd64.zip
    Archive:  terraform_0.13.0_linux_amd64.zip
    inflating: terraform
  

Přesuňte spustitelný soubor terraform do cesty uvedené níže. Zkontrolujte verzi Terraformu.

    [email protected]:~$ sudo mv terraform /usr/local/bin/
    [sudo] password for etechblog.cz:
    [email protected]:~$ terraform -v
    Terraform v0.13.0
  

Můžete vidět, že tyto příkazy jsou dostupné v Terraformu:

    [email protected]:~$ 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
        login      Obtain and save credentials for a remote host
        logout     Remove locally-stored credentials for a remote host
        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
        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:
        0.12upgrade  Rewrites pre-0.12 module source code for v0.12
        0.13upgrade  Rewrites pre-0.13 module source code for v0.13
        debug        Debug output management (experimental)
        force-unlock Manually unlock the terraform state
        push         Obsolete command for Terraform Enterprise legacy (v1)
        state        Advanced state management
  

Zajištění instance AWS EC2 pomocí Terraformu

V tomto ukázkovém příkladu spustíme novou instanci AWS EC2 pomocí Terraformu.

Vytvořte pracovní adresář pro tento demo projekt Terraformu.

    [email protected]:~$ mkdir terraform_demo
  

Přejděte do tohoto adresáře a vytvořte konfigurační soubor Terraformu, kde definujete poskytovatele a prostředky pro spuštění instance AWS EC2.

    [email protected]:~$ cd terraform_demo/
    [email protected]:~/terraform_demo$ gedit awsec2.tf

    provider "aws" {
    access_key = "B5KG6Fe5GUKIATUF5UD"
    secret_key = "R4gb65y56GBF6765ejYSJA4YtaZ+T6GY7H"
    region = "us-west-2"
    }

    resource "aws_instance" "terraform_demo" {
    ami = "ami-0a634ae95e11c6f91"
    instance_type = "t2.micro"
    }
  

Poznámka: Přístupové a tajné klíče jsem změnil 😛, musíte použít své vlastní.

Z výše uvedené konfigurace je patrné, že používáme poskytovatele AWS. Uvnitř poskytovatele se zadávají přihlašovací údaje uživatele AWS a oblast, kde má být instance spuštěna.

V sekci zdrojů uvádím podrobnosti o AMI pro Ubuntu (ami-0a634ae95e11c6f91) a typ instance t2.micro.

Vidíte, jak jednoduchý a čitelný je konfigurační soubor, i když nejste zkušený programátor.

terraform init

Nyní je prvním krokem inicializace Terraformu.

    [email protected]:~/terraform_demo$ terraform init

    Initializing the backend...

    Initializing provider plugins...
    - Using previously-installed hashicorp/aws v3.2.0

    The following providers do not have any version constraints in configuration,
    so the latest version was installed.

    To prevent automatic upgrades to new major versions that may contain breaking
    changes, we recommend adding version constraints in a required_providers block
    in your configuration, with the constraint strings suggested below.

    * hashicorp/aws: version = "~> 3.2.0"

    Terraform has been successfully initialized!

    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.

    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
  

terraform plan

Další fází je plánování. Vytvoří graf provádění pro vytvoření a zřízení infrastruktury.

    [email protected]:~/terraform_demo$ terraform plan
    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but will not be
    persisted to local or remote state storage.

    ------------------------------------------------------------------------

    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      + create

    Terraform will perform the following actions:

      # aws_instance.terraform_demo will be created
      + resource "aws_instance" "terraform_demo" {
          + ami                                  = "ami-0a634ae95e11c6f91"
          + arn                                  = (known after apply)
          + associate_public_ip_address          = (known after apply)
          + availability_zone                    = (known after apply)
          + cpu_core_count                       = (known after apply)
          + cpu_threads_per_core                 = (known after apply)
          + get_password_data                    = false
          + host_id                              = (known after apply)
          + id                                   = (known after apply)
          + instance_state                       = (known after apply)
          + instance_type                        = "t2.micro"
          + ipv6_address_count                   = (known after apply)
          + ipv6_addresses                       = (known after apply)
          + key_name                             = (known after apply)
          + outpost_arn                          = (known after apply)
          + password_data                        = (known after apply)
          + placement_group                      = (known after apply)
          + primary_network_interface_id         = (known after apply)
          + private_dns                          = (known after apply)
          + private_ip                           = (known after apply)
          + public_dns                           = (known after apply)
          + public_ip                            = (known after apply)
          + secondary_private_ips                = (known after apply)
          + security_groups                      = (known after apply)
          + source_dest_check                    = true
          + subnet_id                            = (known after apply)
          + tenancy                              = (known after apply)
          + volume_tags                          = (known after apply)
          + vpc_security_group_ids               = (known after apply)

          + ebs_block_device {
              + delete_on_termination            = (known after apply)
              + device_name                      = (known after apply)
              + encrypted                        = (known after apply)
              + iops                             = (known after apply)
              + kms_key_id                       = (known after apply)
              + snapshot_id                      = (known after apply)
              + volume_id                        = (known after apply)
              + volume_size                      = (known after apply)
              + volume_type                      = (known after apply)
            }

          + ephemeral_block_device {
              + device_name                      = (known after apply)
              + no_device                        = (known after apply)
              + virtual_name                     = (known after apply)
            }

          + metadata_options {
              + http_endpoint                    = (known after apply)
              + http_put_response_hop_limit        = (known after apply)
              + http_tokens                      = (known after apply)
            }

          + network_interface {
              + delete_on_termination            = (known after apply)
              + device_index                     = (known after apply)
              + network_interface_id             = (known after apply)
            }

          + root_block_device {
              + delete_on_termination            = (known after apply)
              + device_name                      = (known after apply)
              + encrypted                        = (known after apply)
              + iops                             = (known after apply)
              + kms_key_id                       = (known after apply)
              + volume_id                        = (known after apply)
              + volume_size                      = (known after apply)
              + volume_type                      = (known after apply)
            }
        }

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

    ------------------------------------------------------------------------

    Note: You didn't specify an "-out" parameter to save this plan, so Terraform
    can't guarantee that exactly these actions will be performed if
    "terraform apply" is subsequently run.
  

terraform apply

Fáze aplikace spustí konfigurační soubor a vytvoří instanci AWS EC2. Po spuštění příkazu Apply se vás zeptá: „Chcete provést tyto akce?“ Musíte zadat „yes“ a stisknout Enter.

    [email protected]:~/terraform_demo$ terraform apply

    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      + create

    Terraform will perform the following actions:

      # aws_instance.terraform_demo will be created
      + resource "aws_instance" "terraform_demo" {
          + ami                                  = "ami-0a634ae95e11c6f91"
          + arn                                  = (known after apply)
          + associate_public_ip_address          = (known after apply)
          + availability_zone                    = (known after apply)
          + cpu_core_count                       = (known after apply)
          + cpu_threads_per_core                 = (known after apply)
          + get_password_data                    = false
          + host_id                              = (known after apply)
          + id                                   = (known after apply)
          + instance_state                       = (known after apply)
          + instance_type                        = "t2.micro"
          + ipv6_address_count                   = (known after apply)
          + ipv6_addresses                       = (known after apply)
          + key_name                             = (known after apply)
          + outpost_arn                          = (known after apply)
          + password_data                        = (known after apply)
          + placement_group                      = (known after apply)
          + primary_network_interface_id         = (known after apply)
          + private_dns                          = (known after apply)
          + private_ip                           = (known after apply)
          + public_dns                           = (known after apply)
          + public_ip                            = (known after apply)
          + secondary_private_ips                = (known after apply)
          + security_groups                      = (known after apply)
          + source_dest_check                    = true
          + subnet_id                            = (known after apply)
          + tenancy                              = (known after apply)
          + volume_tags                          = (known after apply)
          + vpc_security_group_ids               = (known after apply)

          + ebs_block_device {
              + delete_on_termination            = (known after apply)
              + device_name                      = (known after apply)
              + encrypted                        = (known after apply)
              + iops                             = (known after apply)
              + kms_key_id                       = (known after apply)
              + snapshot_id                      = (known after apply)
              + volume_id                        = (known after apply)
              + volume_size                      = (known after apply)
              + volume_type                      = (known after apply)
            }

          + ephemeral_block_device {
              + device_name                      = (known after apply)
              + no_device                        = (known after apply)
              + virtual_name                     = (known after apply)
            }

          + metadata_options {
              + http_endpoint                    = (known after apply)
              + http_put_response_hop_limit        = (known after apply)
              + http_tokens                      = (known after apply)
            }

          + network_interface {
              + delete_on_termination            = (known after apply)
              + device_index                     = (known after apply)
              + network_interface_id             = (known after apply)
            }

          + root_block_device {
              + delete_on_termination            = (known after apply)
              + device_name                      = (known after apply)
              + encrypted                        = (known after apply)
              + iops                             = (known after apply)
              + kms_key_id                       = (known after apply)
              + volume_id                        = (known after apply)
              + volume_size                      = (known after apply)
              + volume_type                      = (known after apply)
            }
        }

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

    Do you want to perform these actions?
    Terraform will perform the actions described above.
    Only 'yes' will be accepted to approve.

      Enter a value: yes

    aws_instance.terraform_demo: Creating...
    aws_instance.terraform_demo: Still creating... [10s elapsed]
    aws_instance.terraform_demo: Still creating... [20s elapsed]
    aws_instance.terraform_demo: Still creating... [30s elapsed]
    aws_instance.terraform_demo: Still creating... [40s elapsed]
    aws_instance.terraform_demo: Creation complete after 44s [id=i-0eec33286ea4b0740]

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

Přejděte do svého řídicího panelu AWS EC2 a uvidíte, že byla vytvořena nová instance s ID instance uvedeným na konci příkazu Apply.

Úspěšně jste spustili instanci AWS EC2 pomocí Terraformu.

terraform destroy

Nakonec, pokud chcete odstranit celou infrastrukturu, musíte spustit příkaz destroy.

    [email protected]:~/terraform_demo$ terraform destroy
    aws_instance.terraform_demo: Refreshing state... [id=i-0eec33286ea4b0740]

    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      - destroy

    Terraform will perform the following actions:

      # aws_instance.terraform_demo will be destroyed
      - resource "aws_instance" "terraform_demo" {
          - ami                                  = "ami-0a634ae95e11c6f91" -> null
          - arn                                  = "arn:aws:ec2:us-west-2:259212389929:instance/i-0eec33286ea4b0740" -> null
          - associate_public_ip_address          = true -> null
          - availability_zone                    = "us-west-2c" -> null
          - cpu_core_count                       = 1 -> null
          - cpu_threads_per_core                 = 1 -> null
          - disable_api_termination              = false -> null
          - ebs_optimized                        = false -> null
          - get_password_data                    = false -> null
          - hibernation                          = false -> null
          - id                                   = "i-0eec33286ea4b0740" -> null
          - instance_state                       = "running" -> null
          - instance_type                        = "t2.micro" -> null
          - ipv6_address_count                   = 0 -> null
          - ipv6_addresses                       = [] -> null
          - monitoring                           = false -> null
          - primary_network_interface_id         = "eni-02a46f2802fd15634" -> null
          - private_dns                          = "ip-172-31-13-160.us-west-2.compute.internal" -> null
          - private_ip                           = "172.31.13.160" -> null
          - public_dns                           = "ec2-34-221-77-94.us-west-2.compute.amazonaws.com" -> null
          - public_ip                            = "34.221.77.94" -> null
          - secondary_private_ips                = [] -> null
          - security_groups                      = [
              - "default",
            ] -> null
          - source_dest_check                    = true -> null
          - subnet_id                            = "subnet-5551200c" -> null
          - tags                                 = {} -> null
          - tenancy                              = "default" -> null
          - volume_tags                          = {} -> null
          - vpc_security_group_ids               = [
              - "sg-b5b480d1",
            ] -> null

          - credit_specification {
              - cpu_credits                        = "standard" -> null
            }

          - metadata_options {
              - http_endpoint                    = "enabled" -> null
              - http_put_response_hop_limit        = 1 -> null
              - http_tokens                      = "optional" -> null
            }

          - root_block_device {
              - delete_on_termination            = true -> null
              - device_name                      = "/dev/sda1" -> null
              - encrypted                        = false -> null
              - iops                             = 100 -> null
              - volume_id                        = "vol-0be2673afff6b1a86" -> null
              - volume_size                      = 8 -> null
              - volume_type                      = "gp2" -> null
            }
        }

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

    Do you really want to destroy all resources?
    Terraform will destroy all your managed infrastructure, as shown above.
    There is no undo. Only 'yes' will be accepted to confirm.

      Enter a value: yes

    aws_instance.terraform_demo: Destroying... [id=i-0eec33286ea4b0740]
    aws_instance.terraform_demo: Still destroying... [id=i-0eec33286ea4b0740, 10s elapsed]
    aws_instance.terraform_demo: Still destroying... [id=i-0eec33286ea4b0740, 20s elapsed]
    aws_instance.terraform_demo: Still destroying... [id=i-0eec33286ea4b0740, 30s elapsed]
    aws_instance.terraform_demo: Destruction complete after 34s

    Destroy complete! Resources: 1 destroyed.
  

Pokud znovu zkontrolujete řídicí panel EC2, uvidíte, že instance byla ukončena.

Závěr

Doufám, že vám tento článek poskytl základní přehled o tom, jak začít s Terraformem. Neváhejte si vyzkoušet uvedený příklad.

Doporučuji vám, abyste se na tento software pro automatizaci infrastruktury podívali blíže.

Pokud máte zájem o další vzdělávání, doporučuji vám podívat se na Výuka DevOps s Terraformem.