Czy zastanawiałeś się kiedyś, czym tak naprawdę jest Terraform? Spróbujmy to wspólnie zgłębić.
Pojęcie „Infrastruktura jako Kod” (Infrastructure as Code, IaC) to powszechnie używany termin wśród ekspertów DevOps. Opisuje ono proces zarządzania i dostarczania całej infrastruktury IT, zarówno tej fizycznej, jak i wirtualnej, za pomocą plików konfiguracyjnych, które są czytelne dla komputerów. Jest to podejście do operacji inspirowane inżynierią oprogramowania, umożliwiające automatyzację całego centrum danych za pomocą skryptów programistycznych.
Mimo wielu zalet, podejście Infrastructure as Code niesie za sobą pewne wyzwania:
- Konieczność nauki kodowania.
- Trudność w przewidywaniu skutków zmian.
- Potrzeba wycofywania wprowadzonych zmian.
- Problemy ze śledzeniem historii zmian.
- Ograniczenia w automatyzacji zasobów.
- Złożoność wynikająca z wielu środowisk infrastrukturalnych.
Terraform powstał, aby zaradzić tym niedogodnościom.
Czym zatem jest Terraform?
Terraform to otwarte, bezpłatne narzędzie typu „Infrastruktura jako Kod”, stworzone przez firmę HashiCorp. Służy do definiowania i udostępniania infrastruktury za pomocą prostego, deklaratywnego języka konfiguracji.
Jest to narzędzie do zarządzania infrastrukturą, pozwalające na przechowywanie konfiguracji środowiska chmurowego w postaci kodu. Przypomina nieco narzędzia takie jak CloudFormation, służące do automatyzacji infrastruktury w chmurze AWS, ale z tą różnicą, że Terraform działa nie tylko w AWS, ale także na innych platformach chmurowych.
Oto niektóre z korzyści wynikających z używania Terraform:
- Umożliwia orkiestrację, a nie tylko zarządzanie konfiguracją.
- Współpracuje z wieloma dostawcami, takimi jak AWS, Azure, GCP, DigitalOcean i innymi.
- Gwarantuje niezmienną infrastrukturę, w której konfiguracja zmienia się płynnie.
- Wykorzystuje łatwy do zrozumienia język HCL (HashiCorp Configuration Language).
- Jest łatwo przenośny do różnych dostawców chmurowych.
- Opiera się na architekturze klienta, eliminując konieczność dodatkowej konfiguracji po stronie serwera.
Kluczowe Koncepcje Terraform
Poniżej znajdziesz podstawowe pojęcia i terminologię, z którą spotkasz się w Terraform:
- Zmienne: Nazywane również zmiennymi wejściowymi, to pary klucz-wartość używane przez moduły Terraform w celu umożliwienia ich dostosowania do konkretnych potrzeb.
- Dostawca: Jest to wtyczka, która umożliwia interakcję z API danej usługi i dostęp do jej zasobów.
- Moduł: To folder zawierający szablony Terraform, w których zdefiniowane są wszystkie konfiguracje.
- Stan: Zawiera zapisane informacje o infrastrukturze zarządzanej przez Terraform oraz jej powiązanych konfiguracjach.
- Zasoby: Odnoszą się do bloków składających się z jednego lub większej liczby obiektów infrastruktury (np. instancji obliczeniowych, sieci wirtualnych), które służą do konfigurowania i zarządzania infrastrukturą.
- Źródło danych: Jest implementowane przez dostawców i służy do pobierania informacji o obiektach zewnętrznych do Terraform.
- Wartości wyjściowe: To dane zwracane przez moduł Terraform, które mogą być użyte w innych konfiguracjach.
- Plan: Jest to etap, w którym Terraform określa, jakie zmiany (utworzenie, aktualizacja, usunięcie) należy wprowadzić, aby przejść z aktualnego stanu infrastruktury do stanu docelowego.
- Zastosuj: Jest to etap, w którym Terraform wprowadza zmiany w rzeczywistej infrastrukturze, zgodnie z planem, aby osiągnąć pożądany stan.
Cykl Życia Terraform
Cykl życia Terraform składa się z kilku etapów: inicjalizacja, planowanie, zastosowanie i zniszczenie.
- Terraform init: Inicjuje katalog roboczy, w którym znajdują się pliki konfiguracyjne.
- Terraform plan: Tworzy plan działań, które są niezbędne do osiągnięcia docelowego stanu infrastruktury. Zmiany w konfiguracji są analizowane, aby ustalić, jak osiągnąć pożądany rezultat.
- Terraform apply: Wprowadza zmiany w infrastrukturze zgodnie z wygenerowanym planem, co prowadzi do osiągnięcia docelowego stanu.
- Terraform destroy: Służy do usunięcia zasobów infrastruktury, które zostały oznaczone jako „skażone” po etapie apply.
Jak Działa Terraform?
Architektura Terraform składa się z dwóch kluczowych elementów:
Rdzeń Terraform
Rdzeń Terraform wykorzystuje dwa główne źródła danych wejściowych:
Pierwszym z nich jest konfiguracja Terraform, którą tworzy użytkownik. W niej określa się, jakie elementy infrastruktury mają zostać utworzone. Drugim źródłem danych jest stan, w którym Terraform przechowuje aktualne informacje o konfiguracji infrastruktury.
Rdzeń Terraform, na podstawie tych danych, tworzy plan działania. Porównuje obecny stan infrastruktury z pożądanym, zdefiniowanym w pliku konfiguracyjnym. Na tej podstawie określa, jakie zmiany należy wprowadzić – co utworzyć, zaktualizować, a co usunąć, aby dostarczyć infrastrukturę w docelowej konfiguracji.
Dostawcy
Drugim elementem architektury są dostawcy, czyli wtyczki do konkretnych technologii. Mogą to być dostawcy chmurowi, jak AWS, Azure czy GCP, lub inne platformy usługowe. Mogą to być także bardziej zaawansowane komponenty, jak Kubernetes, czy inne narzędzia platformy jako usługi, a nawet oprogramowanie jako usługa.
Dzięki temu można tworzyć infrastrukturę na różnych poziomach.
Przykładowo, można utworzyć infrastrukturę w AWS, następnie wdrożyć na niej Kubernetes, a potem tworzyć usługi wewnątrz tego klastra.
Terraform ma setki dostawców dla różnych technologii, a każdy z nich umożliwia Terraformowi dostęp do zasobów danego dostawcy. Za pomocą dostawcy AWS użytkownik ma dostęp do setek zasobów, takich jak instancje EC2, użytkownicy AWS itp. Za pomocą dostawcy Kubernetes można zarządzać usługami, wdrożeniami, przestrzeniami nazw i innymi zasobami klastra.
W ten sposób działa Terraform, wspierając proces konfiguracji i dostarczania aplikacji, od poziomu infrastruktury aż po aplikację.
Przejdźmy do praktyki. 👨💻
Zainstalujemy Terraform na Ubuntu i udostępnimy prostą infrastrukturę.
Instalacja Terraform
Pobierz najnowszy pakiet Terraform.
Odwiedź oficjalną stronę pobierania, aby znaleźć najnowszą wersję dla twojego systemu operacyjnego.
[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]
Rozpakuj pobrany pakiet.
[email protected]:~$ unzip terraform_0.13.0_linux_amd64.zip Archive: terraform_0.13.0_linux_amd64.zip inflating: terraform
Przenieś plik wykonywalny Terraform do ścieżki pokazanej poniżej. Sprawdź wersję Terraform.
[email protected]:~$ sudo mv terraform /usr/local/bin/ [sudo] password for newsblog.pl: [email protected]:~$ terraform -v Terraform v0.13.0
Możesz zobaczyć dostępne polecenia Terraform.
[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
Udostępnianie Instancji AWS EC2 za Pomocą Terraform
W tym przykładzie uruchomimy nową instancję AWS EC2 za pomocą Terraform.
Utwórz katalog roboczy dla tego demo Terraform.
[email protected]:~$ mkdir terraform_demo
Przejdź do katalogu i utwórz plik konfiguracyjny terraform, gdzie zdefiniujesz dostawcę i zasoby do uruchomienia instancji 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" }
Uwaga: Zmieniłem klucze dostępu i tajne 😛, musisz użyć własnych.
Powyższa konfiguracja określa dostawcę – AWS. W jego ramach podajemy dane uwierzytelniające użytkownika AWS oraz region, w którym instancja ma zostać uruchomiona.
W definicji zasobu podajemy szczegóły dotyczące AMI Ubuntu (ami-0a634ae95e11c6f91) oraz typ instancji, który powinien być t2.micro.
Możesz zauważyć, jak czytelny i prosty jest plik konfiguracyjny, nawet dla osób, które nie są doświadczonymi programistami.
terraform init
Pierwszym krokiem jest zainicjowanie 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
Następnie wykonaj plan; Terraform utworzy plan wykonania dla stworzenia i udostępnienia 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
Etap wprowadzania spowoduje uruchomienie pliku konfiguracyjnego i uruchomienie instancji AWS EC2. Po uruchomieniu polecenia Apply, zostaniesz zapytany: „Czy chcesz wykonać te czynności?”, musisz wpisać `yes` i nacisnąć 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.
Sprawdź panel AWS EC2, a zobaczysz, że została utworzona nowa instancja z identyfikatorem instancji wymienionym na końcu polecenia `Apply`.
Udało Ci się uruchomić instancję AWS EC2 za pomocą Terraform.
terraform destroy
Na koniec, jeśli chcesz usunąć infrastrukturę, musisz uruchomić polecenie `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.
Po ponownym sprawdzeniu panelu EC2, zobaczysz, że instancja została zamknięta.
Podsumowanie
Mam nadzieję, że ten artykuł dał ci ogólne pojęcie o tym, jak zacząć swoją przygodę z Terraform. Zachęcam do wypróbowania przedstawionego przykładu.
Warto również zapoznać się z innymi narzędziami do automatyzacji infrastruktury.
Jeśli chcesz poszerzyć swoją wiedzę, polecam zapoznanie się z kursem na temat DevOps i automatyzacji infrastruktury za pomocą Terraform.