Ce este Terraform și de ce ar trebui să te intereseze?
Te-ai întrebat vreodată ce este Terraform? Haide să explorăm împreună acest instrument esențial în lumea DevOps.
Infrastructura ca și cod (IaC) a devenit un concept fundamental pentru profesioniștii DevOps. Aceasta reprezintă modalitatea de a gestiona și de a aloca întreaga infrastructură IT, atât cea fizică, cât și virtuală, prin intermediul fișierelor de definiție lizibile de mașini. Practic, este o abordare a operațiunilor inspirată din ingineria software. IaC facilitează automatizarea completă a centrelor de date prin utilizarea scripturilor de programare.
Deși Infrastructura ca și Cod oferă numeroase beneficii, aceasta vine și cu anumite provocări:
- Necesitatea învățării limbajelor de codificare.
- Dificultatea de a anticipa impactul modificărilor.
- Complexitatea anulării schimbărilor.
- Probleme în monitorizarea modificărilor.
- Imposibilitatea automatizării anumitor resurse.
- Gestionarea diferitelor medii de infrastructură.
Terraform a fost creat tocmai pentru a soluționa aceste provocări.
Definiția Terraform
Terraform este un instrument open-source de Infrastructură ca și Cod, dezvoltat de HashiCorp. Este folosit pentru a defini și a aloca infrastructura completă utilizând un limbaj declarativ ușor de învățat.
Terraform permite stocarea configurației infrastructurii cloud sub formă de cod, având o funcționalitate similară cu instrumente precum CloudFormation, care este utilizat pentru automatizarea infrastructurii AWS. Însă, spre deosebire de CloudFormation, Terraform poate fi utilizat pe multiple platforme cloud.
Iată câteva dintre avantajele utilizării Terraform:
- Facilitează orchestrarea, nu doar gestionarea configurației.
- Suportă numeroși furnizori, precum AWS, Azure, GCP, DigitalOcean și mulți alții.
- Asigură o infrastructură imuabilă, unde configurația se schimbă fără probleme.
- Utilizează un limbaj ușor de înțeles, HCL (HashiCorp Configuration Language).
- Este ușor de portat între diferiți furnizori.
- Funcționează pe o arhitectură client, eliminând necesitatea gestionării adiționale a configurației pe un server.
Concepte fundamentale Terraform
Iată o listă a conceptelor și terminologiei de bază utilizate în Terraform:
- Variabile: Cunoscute și ca variabile de intrare, sunt perechi cheie-valoare folosite de modulele Terraform pentru a permite personalizarea.
- Furnizor: Este un plugin care permite interacțiunea cu API-urile de servicii și accesarea resurselor aferente.
- Modul: Un director care conține șabloane Terraform, unde sunt definite toate configurațiile.
- Stare: Informații stocate în cache despre infrastructura gestionată de Terraform și configurațiile asociate.
- Resurse: Blocuri de cod care descriu unul sau mai multe obiecte de infrastructură (instanțe de calcul, rețele virtuale etc.) utilizate în configurare și management.
- Sursa de date: Mecanism implementat de furnizori pentru a returna informații despre obiectele externe Terraform.
- Valori de ieșire: Valori returnate de un modul Terraform, utilizabile de alte configurații.
- Plan: Etapa în care se determină ce trebuie creat, actualizat sau distrus pentru a alinia starea actuală a infrastructurii cu cea dorită.
- Aplicare: Etapa în care se implementează modificările asupra stării actuale a infrastructurii pentru a atinge starea dorită.
Ciclul de viață Terraform
Ciclul de viață Terraform este format din etapele: inițializare, planificare, aplicare și distrugere.
- `terraform init`: Inițializează directorul de lucru, care conține fișierele de configurare.
- `terraform plan`: Generează un plan de execuție pentru a atinge starea dorită a infrastructurii, luând în considerare modificările din fișierele de configurare.
- `terraform apply`: Implementează modificările asupra infrastructurii conform planului, aducând infrastructura la starea dorită.
- `terraform destroy`: Șterge toate resursele de infrastructură, marcate ca fiind „contaminate” după faza de aplicare.
Cum funcționează Terraform?
Arhitectura Terraform este alcătuită din două componente majore:
Nucleul Terraform
Nucleul Terraform utilizează două surse de intrare pentru funcționarea sa:
Prima sursă este configurația Terraform, definită de utilizator, unde se specifică ce anume trebuie creat sau alocat. A doua sursă este „starea”, în care Terraform menține o evidență a configurației actuale a infrastructurii.
Nucleul Terraform analizează aceste intrări și stabilește un plan de acțiune. Acesta compară starea actuală cu configurația dorită și calculează ce trebuie creat, actualizat sau șters pentru a aduce infrastructura la starea dorită.
Furnizorii
A doua componentă a arhitecturii o reprezintă furnizorii de tehnologii specifice. Aceștia pot fi furnizori de servicii cloud, precum AWS, Azure, GCP, sau alte platforme de infrastructură. De asemenea, pot fi furnizori pentru componente de nivel înalt, cum ar fi Kubernetes sau alte instrumente platform-as-a-service, chiar și software ca instrument de autoservire.
Aceștia oferă posibilitatea de a crea infrastructură la diverse niveluri. De exemplu, se poate crea infrastructura AWS, apoi se poate implementa Kubernetes deasupra acesteia și, ulterior, se pot crea servicii și componente în cadrul clusterului Kubernetes.
Terraform dispune de peste o sută de furnizori pentru diverse tehnologii, fiecare oferind acces la resursele specifice. Prin intermediul furnizorului AWS, de exemplu, se pot accesa sute de resurse precum instanțe EC2 sau utilizatori AWS. Similar, furnizorul Kubernetes permite accesul la resurse precum servicii, implementări și spații de nume.
Astfel, Terraform ajută la alocarea și gestionarea completă a configurației aplicației, de la infrastructură până la nivelul aplicației.
Hai să trecem la partea practică. 👨💻
Vom instala Terraform pe Ubuntu și vom aloca o infrastructură de bază.
Instalarea Terraform
Începem prin a descărca cel mai recent pachet Terraform.
Accesați pagina oficială de descărcare pentru a obține cea mai recentă versiune adecvată sistemului dvs. de operare.
[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]
Extrageți pachetul descărcat.
[email protected]:~$ unzip terraform_0.13.0_linux_amd64.zip Archive: terraform_0.13.0_linux_amd64.zip inflating: terraform
Mutați executabilul Terraform în calea de mai jos. Apoi, verificați versiunea Terraform.
[email protected]:~$ sudo mv terraform /usr/local/bin/ [sudo] password for tipstrick.ro: [email protected]:~$ terraform -v Terraform v0.13.0
Mai jos puteți vedea lista comenzilor disponibile în Terraform pentru execuție.
[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
Alocarea unei instanțe AWS EC2 cu Terraform
În această demonstrație, vom lansa o nouă instanță AWS EC2 folosind Terraform.
Începem prin a crea un director de lucru pentru demonstrația noastră cu Terraform.
[email protected]:~$ mkdir terraform_demo
Navigăm în acest director și creăm un fișier de configurare Terraform, unde definim furnizorul și resursele necesare pentru lansarea instanței 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" }
Notă: Am înlocuit cheile de acces și secrete pentru a menține securitatea. Trebuie să le utilizați pe cele proprii.
În configurația de mai sus, specificăm furnizorul ca fiind AWS. În cadrul acestuia, furnizăm datele de autentificare ale utilizatorului AWS, precum și regiunea în care va fi lansată instanța.
În secțiunea resurselor, indicăm AMI-ul pentru Ubuntu (ami-0a634ae95e11c6f91) și definim tipul instanței ca fiind t2.micro.
După cum se poate observa, fișierul de configurare este ușor de citit și de înțeles, chiar și pentru cineva care nu este un programator expert.
`terraform init`
Primul pas este inițializarea Terraform.
[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`
Următoarea etapă este planificarea, în care se va genera planul de execuție pentru crearea și alocarea infrastructurii.
[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`
În etapa de aplicare, se va executa fișierul de configurare și se va lansa instanța AWS EC2. Când rulați comanda de aplicare, veți fi întrebat „Doriți să efectuați aceste acțiuni?”. Trebuie să scrieți `yes` și să apăsați 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.
Accesați tabloul de bord AWS EC2 și veți observa că s-a creat o nouă instanță, având ID-ul specificat la sfârșitul comenzii `apply`.
Felicitări! Ați lansat cu succes o instanță AWS EC2 folosind Terraform.
`terraform destroy`
În final, dacă doriți să ștergeți infrastructura, trebuie să executați comanda `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.
Verificând din nou tabloul de bord EC2, veți observa că instanța a fost terminată.
Concluzie
Sper că cele de mai sus v-au oferit o idee clară despre cum să începeți cu Terraform. Vă încurajez să încercați exemplul prezentat.
De asemenea, vă sugerez să explorați și alte instrumente de automatizare a infrastructurii.
Dacă sunteți interesat să aprofundați cunoștințele, vă recomand să consultați Cursul „Learn DevOps with Terraform”.