Увод у Терраформ за почетнике – Терраформ Туториал

Pitate se, šta je to Terraform? Hajde da zajedno istražimo.

Infrastruktura kao kod (IaC) je široko rasprostranjen termin među DevOps stručnjacima. To je proces upravljanja i obezbeđivanja kompletne IT infrastrukture, uključujući fizičke i virtuelne mašine, korišćenjem mašinski čitljivih fajlova sa definicijama. Ovaj pristup predstavlja primenu softverskog inženjeringa u operacijama, omogućavajući automatizaciju celokupnog data centra pomoću programskih skripti.

Iako Infrastruktura kao kod nudi mnoge prednosti, susreće se i sa izazovima:

  • Potrebno je savladati kodiranje.
  • Nejasno je kako će promene uticati na sistem.
  • Otežano je vraćanje promena.
  • Praćenje promena nije jednostavno.
  • Automatizacija resursa može biti komplikovana.
  • Infrastruktura se često prostire na više okruženja.

Terraform je osmišljen da odgovori na ove izazove.

Šta je zapravo Terraform?

Terraform je open-source alat za infrastrukturu kao kod, razvijen od strane HashiCorp-a. Koristi se za definisanje i postavljanje kompletne infrastrukture pomoću deklarativnog jezika koji je jednostavan za učenje.

Terraform je alat za obezbeđivanje infrastrukture koji vam omogućava da konfiguracije oblaka čuvate kao kod. Sličan je alatima poput CloudFormation, koji se koristi za automatizaciju AWS infrastrukture, ali je ograničen samo na AWS. Sa Terraform-om, možete upravljati infrastrukturom na raznim cloud platformama.

U nastavku su navedene neke od prednosti korišćenja Terraform-a:

  • Orkestrira, ne samo što upravlja konfiguracijom.
  • Podržava brojne provajdere, uključujući AWS, Azure, GCP, DigitalOcean i mnoge druge.
  • Obezbeđuje nepromenljivu infrastrukturu, gde se konfiguracije menjaju bez poteškoća.
  • Koristi lako razumljiv jezik, HCL (HashiCorp Configuration Language).
  • Omogućava jednostavan prenos između različitih provajdera.
  • Radi na klijentskoj arhitekturi, eliminisavši potrebu za dodatnom konfiguracijom na serveru.

Ključni Koncepti Terraform-a

Ovo su osnovni koncepti i termini koji se koriste u Terraform-u:

  • Promenljive: Služe kao ulazne promenljive, parovi ključ-vrednost koji omogućavaju prilagođavanje Terraform modula.
  • Provajder: Dodatak za interakciju sa API-jima usluga i pristup resursima.
  • Modul: Direktorijum sa Terraform šablonima koji sadrži sve definicije konfiguracija.
  • Stanje: Keširana informacija o infrastrukturi kojom upravlja Terraform i povezanim konfiguracijama.
  • Resursi: Blok jednog ili više infrastrukturnih objekata (računarske instance, virtuelne mreže, itd.) koji se koriste za konfigurisanje i upravljanje infrastrukturom.
  • Izvor podataka: Provajderi ga koriste za pribavljanje informacija o spoljnim objektima.
  • Izlazne vrednosti: Povratne vrednosti Terraform modula koje mogu koristiti druge konfiguracije.
  • Plan: Faza u kojoj se određuje šta treba kreirati, ažurirati ili uništiti da bi se prešlo iz trenutnog u željeno stanje infrastrukture.
  • Primena: Faza u kojoj se primenjuju promene za prelazak iz trenutnog u željeno stanje infrastrukture.

Životni Ciklus Terraform-a

Životni ciklus Terraform-a sastoji se od inicijalizacije, planiranja, primene i uništavanja.

  • `terraform init` inicijalizuje radni direktorijum koji sadrži konfiguracione fajlove.
  • `terraform plan` kreira plan izvršenja kako bi se postiglo željeno stanje infrastrukture, uzimajući u obzir promene u konfiguracionim fajlovima.
  • `terraform apply` primenjuje promene u infrastrukturi prema planu, dovodeći je u željeno stanje.
  • `terraform destroy` se koristi za uklanjanje svih resursa koji su označeni kao nepotrebni nakon primene.

Kako Funkcioniše Terraform?

Terraform arhitektura se sastoji od dve glavne komponente:

Jezgro Terraform-a

Jezgro Terraform-a koristi dva ulazna izvora za svoj rad.

Prvi ulazni izvor je Terraform konfiguracija koju korisnik definiše, specificirajući šta treba kreirati ili postaviti. Drugi izvor je stanje u kojem Terraform održava informacije o trenutnom stanju infrastrukture.

Jezgro Terraform-a analizira ove ulaze i kreira plan izvršenja. Upoređuje trenutno stanje sa željenom konfiguracijom i određuje koje akcije su potrebne da se postigne željeno stanje, uključujući kreiranje, ažuriranje i brisanje resursa.

Provajderi

Druga komponenta su provajderi za specifične tehnologije, kao što su cloud provajderi (AWS, Azure, GCP) ili platforme kao usluga. Provajderi mogu biti i alati višeg nivoa poput Kubernetes-a.

Ovo omogućava kreiranje infrastrukture na različitim nivoima. Možete, na primer, kreirati AWS infrastrukturu, zatim primeniti Kubernetes na njoj, pa kreirati servise unutar Kubernetes klastera.

Terraform podržava preko stotinu provajdera za različite tehnologije, dajući korisnicima pristup njihovim resursima. Na primer, AWS provajder omogućava pristup stotinama AWS resursa kao što su EC2 instance i AWS korisnici. Kubernetes provajder pruža pristup resursima poput servisa, deploymenata i namespace-ova.

Terraform na ovaj način pomaže u obezbeđivanju celokupne postavke aplikacije, od infrastrukture do same aplikacije.

Pređimo na praktične primere. 👨‍💻

Instaliraćemo Terraform na Ubuntu i postaviti osnovnu infrastrukturu.

Instalacija Terraform-a

Preuzmite najnoviji Terraform paket.

Posetite zvaničnu stranicu za preuzimanje kako biste pronašli najnoviju verziju za vaš operativni sistem.

[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]

Raspakujte preuzeti paket.

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

Premestite Terraform izvršnu datoteku na putanju prikazanu ispod i proverite verziju.

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

Možete videti koje komande su dostupne za izvršenje u Terraform-u.

[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

Postavljanje AWS EC2 Instance Korišćenjem Terraform-a

U ovoj demonstraciji, pokrenućemo novu AWS EC2 instancu koristeći Terraform.

Kreirajte radni direktorijum za ovu Terraform demonstraciju.

[email protected]:~$ mkdir terraform_demo

Uđite u direktorijum i kreirajte Terraform konfiguracioni fajl u kojem ćete definisati provajdera i resurse za pokretanje AWS EC2 instance.

[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"
}

Napomena: Promenio sam pristupne i tajne ključeve 😛, vi treba da koristite svoje.

Iz konfiguracije iznad, vidite da pominjemo AWS kao provajdera. U okviru provajdera, dajemo AWS korisničke akreditive i region u kojem instanca treba da se pokrene.

U resursima, dajemo AMI detalje za Ubuntu (ami-0a634ae95e11c6f91) i navodimo da tip instance treba da bude t2.micro.

Možete videti koliko je konfiguracioni fajl jednostavan i čitljiv, čak i ako niste iskusan programer.

`terraform init`

Prvi korak je inicijalizacija Terraform-a.

[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`

Sledeća faza je plan; kreira se graf izvršenja za kreiranje i obezbeđivanje infrastrukture.

[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`

Faza primene će izvršiti konfiguracioni fajl i pokrenuti AWS EC2 instancu. Kada pokrenete komandu apply, pitaće vas: „Da li želite da izvršite ove radnje?“, potrebno je da ukucate yes i pritisnete 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.

Idite na svoju AWS EC2 kontrolnu tablu i videćete da je kreirana nova instanca sa ID-om instance pomenutim na kraju komande primene.

Uspešno ste pokrenuli AWS EC2 instancu koristeći Terraform.

`terraform destroy`

Konačno, ako želite da obrišete infrastrukturu, potrebno je da pokrenete komandu `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.

Ako ponovo proverite EC2 kontrolnu tablu, videćete da je instanca prekinuta.

Zaključak

Verujem da vam je gore navedeno dalo ideju kako da počnete sa Terraform-om. Slobodno isprobajte primer koji smo upravo pokazali.

Takođe, trebalo bi da razmotrite ovaj softver za automatizaciju infrastrukture.

Ako ste zainteresovani da saznate više, predlažem da pogledate Kurs učenja DevOps-a uz Terraform.