Wprowadzenie
Podstawy Terraforma i konfiguracji środowiska mamy już za sobą, więc możemy przejść do bardziej rozbudowanego przykładu. W tym wpisie zobaczysz, w jaki sposób przygotować infrastrukturę pod prostą aplikację webową działającą w Azure. Z wykorzystaniem Terraforma utworzymy takie zasoby jak App Service Plan, czy bazę danych.
Zmienne Terraform
W poprzednim wpisie pokazałem, w jaki sposób zacząć przygodę z Terraform i Azure. Jeśli nie czytałeś/czytałaś to zachęcam do nadrobienia zaległości – Terraform i Azure. Przykład w tamtym wpisie był bardzo prosty i sprowadzał się do utworzenie grupy zasobów (Resource Group) w Azure.
Zanim przejdziemy do tworzenia bardziej rozbudowanego przykładu, chciałbym najpierw wprowadzić nowe pojęcie z Terraforma, które ułatwi nam późniejszą pracę. Zmienne, o których mowa, pozwolą nam tworzyć parametryzowane szablony infrastruktury. Przydaje się to szczególnie wtedy, gdy będziemy mieli kilka różnych środowisk tworzonych z tego samego kodu infrastruktury; na przykład środowisko testowe, UAT, czy produkcyjne.
Aby skorzystać ze zmiennych, musimy w pierwszej kolejności utworzyć definicje zmiennej. W przykładzie utworzę plik variables.tf, w którym będą znajdowały się definicje zmiennych. Zaczniemy od utworzenia pierwszej prostej zmiennej, w której określimy nazwę środowiska (dev, test, prod i tym podobne). Plik variables.tf będzie wyglądał tak:
variable "env" { | |
type = string | |
default = "__env__" | |
} |
Za pomocą bloku variable określamy nową zmienną, gdzie „env” to nazwa zmiennej, której później będziemy używać. W bloku określamy dwie wartości: typ zmiennej (type) oraz domyślną wartość (default). Jest to odpowiednio string oraz __env__. Domyślna wartość może wydawać się trochę dziwna, ale jest ona już przygotowana do automatycznego stawiania infrastruktury z wykorzystaniem Azure DevOps. Omówię to w kolejnym wpisie.
Użycie zmiennych
Mając już przygotowaną zmienną, możemy ją już użyć. Dostęp do zmiennych mamy za pomocą słowa kluczowego var, gdzie po kropce podajemy nazwę zmiennej. Na przykład „var.env”.
Poniżej znajduje się fragment kodu, który utworzy nam grupę zasobów, gdzie w nazwie właśnie użyłem zmienną określającą środowisko:
resource "azurerm_resource_group" "resource_group" { | |
name = "onlin-rg-${var.env}" | |
location = "westeurope" | |
} |
Zmienna została użyta do zbudowania nazwy grupy zasobów. Wartość „onlin” w nazwie określa nazwę wymyślonej aplikacji, „rg” to skrót od resource grup i ostatni człon to właśnie nazwa środowiska, która pochodzi ze zmiennej env. W przypadku środowisk test grupa zasobów będzie nazywać się onlin-rg-test, a środowiska produkcyjnego onlin-rg-prod.
Terraform umożliwia nam jeszcze utworzenie plików tfvars, w których będą znajdować się już konkretne wartości zmiennych. Plik ten możemy wykorzystać podczas wykonywania komend Terraforma i wartości zmiennych z niego nadpiszą wartości domyślne, które podaliśmy podczas definicji zmiennej.
Na przykład dla środowiska developerskiego moglibyśmy mieć plik dev.tfvars, w którym będą używane wartości zmiennych dla tego środowiska. Na przykład:
env = "dev" |
W pliku tfvars podajemy tylko wartości zmiennych w formie „nazwa = wartość”.
Aby wykorzystać tak utworzony plik musimy skorzystać z przełącznika -var-file podczas wykonywania komend Terraform. Na przykład:
terraform apply -var-file="dev.tfvars"
Powyżej omówione zmienne to tak zwane Input variables, które służą właśnie do parametryzowania szablonu infrastruktury. Terraform udostępnia jeszcze dwa dodatkowe rodzaje zmiennych: Output oraz Local. Ale to już temat na inny wpis.
Web Aplikacja w Azure
Po poznaniu zmiennych możemy przejść do utworzenia bardziej rozbudowanej infrastruktury w Azure. Jako przykład wykorzystamy prostą aplikację webową, którą będę chciał hostować w Azure. W ramach aplikacji utworzę takie elementy infrastruktury:
- App Service Plan
- App Service
- Application Insight – podpięty zostanie pod utworzony App Service
- Sql Server
- Sql Database
- Konfiguracja firewall dla Sql Servera
Do utworzenia powyższych zasobów wykorzystam kilka zmiennych, które umożliwią mi ich sparametryzowanie w taki sposób, by można było mieć trochę inną konfigurację poszczególnych środowisk. Plik ze zmiennymi wygląda tak:
variable "env" { | |
type = string | |
default = "__env__" | |
} | |
variable "resource_location" { | |
type = string | |
default = "__resource_location__" | |
} | |
variable "app_service_plan_size" { | |
type = string | |
default = "__app_service_plan_size__" | |
} | |
variable "app_service_plan_tier" { | |
type = string | |
default = "__app_service_plan_tier__" | |
} | |
variable "database_sku" { | |
type = string | |
default = "__database_sku__" | |
} | |
variable "sql_server_login" { | |
type = string | |
default = "__sql_server_login__" | |
} | |
variable "sql_server_password" { | |
type = string | |
default = "__sql_server_password__" | |
} |
Wykorzystane zmienne to:
- env – nazwa środowiska np. dev, test, prod
- resource_location – region w Azure np. westeurope
- app_service_plan_size – rozmiar App Service Plan – np. B1
- app_service_plan_tier – poziom cenowy App Service Plan – np. Basic
- database_sku – rozmiar bazy np. Basic
- sql_server_login – login administratora w SQL Server
- sql_server_password – hasło administratora w SQL Server
Dodatkowo przygotowałem jeszcze plik dev.tfvars z wartościami zmiennych dla środowiska developerskiego. Na ogół ten plik wykorzystuję lokalnie podczas testów skryptów Terraforma. W przykładzie wygląda on tak:
env = "dev" | |
resource_location = "westeurope" | |
app_service_plan_size = "B1" | |
app_service_plan_tier = "Basic" | |
database_sku = "Basic" | |
sql_server_login = "sql-admin" | |
sql_server_password = "KrLFJ3n7SLXQrmPApQLzcuohyUv5Nex5KHyt" |
Zasoby w Azure
Po przygotowaniu zmiennych możemy przejść teraz do tworzenia zasobów. Dla przypomnienia opis poszczególnych typów zasobów znajdziesz w dokumentacji azurerm – https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs. Zaczniemy od tego, co pokazałem w poprzednim wpisie Terraform i Azure, czyli konfiguracji samego Terraform i utworzenia grupy zasobów:
terraform { | |
required_providers { | |
azurerm = { | |
source = "hashicorp/azurerm" | |
version = "=2.46.0" | |
} | |
} | |
} | |
provider "azurerm" { | |
features {} | |
} | |
resource "azurerm_resource_group" "resource_group" { | |
name = "onlin-rg-${var.env}" | |
location = var.resource_location | |
} |
Różnica głównie polega na sparametrowaniu nazwy grupy zasobów i wykorzystaniu zmiennej env jako ostatni człon nazwy (linijka 15) oraz użyciu zmiennej określającej region, w którym ma zostać utworzona grupa zasobów (linijka 16).
Kolejny zasób, jaki utworzymy to Application Insight:
resource "azurerm_application_insights" "app_insight" { | |
name = "onlin-ai-${var.env}" | |
location = azurerm_resource_group.resource_group.location | |
resource_group_name = azurerm_resource_group.resource_group.name | |
application_type = "web" | |
} |
Konfiguracja jest tutaj dość standardowa, czyli określamy nazwę, grupę zasobów oraz lokalizację. Będzie to się przewijało przez większość tworzonych zasobów w Azure. Tutaj korzystam z kolejnej fajnej funkcjonalności Terraforma, którą jest możliwość odnoszenia się do wcześniej utworzonych zasobów. W tym przypadku używamy wcześniej utworzoną grupę zasobów. Odnosimy się poprzez podanie [typu zasobu].[jego nazwy].[właściwości zasobu]. Zobacz linijkę 3 oraz 4.
Możemy teraz przejść do utworzenia App Service Plan oraz App Service:
resource "azurerm_app_service_plan" "app_service_plan" { | |
name = "onlin-sp-${var.env}" | |
location = azurerm_resource_group.resource_group.location | |
resource_group_name = azurerm_resource_group.resource_group.name | |
kind = "app" | |
sku { | |
tier = var.app_service_plan_tier | |
size = var.app_service_plan_size | |
} | |
} | |
resource "azurerm_app_service" "app" { | |
name = "onlin-app-${var.env}" | |
location = azurerm_resource_group.resource_group.location | |
resource_group_name = azurerm_resource_group.resource_group.name | |
app_service_plan_id = azurerm_app_service_plan.app_service_plan.id | |
https_only = true | |
client_affinity_enabled = true | |
identity { | |
type = "SystemAssigned" | |
} | |
site_config { | |
dotnet_framework_version = "v5.0" | |
always_on = true | |
use_32_bit_worker_process = false | |
default_documents = [ | |
"index.html" | |
] | |
} | |
app_settings = { | |
WEBSITE_RUN_FROM_PACKAGE = "1" | |
APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.app_insight.instrumentation_key | |
APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.app_insight.connection_string | |
} | |
} |
Myślę, że większość właściwości jest dość jasna. Chciałbym tylko zaznaczyć tutaj sposób podpięcia Application Insight do App Service. Robimy to przez ustawienie app settings, gdzie odwołujemy się do właściwości wcześniej utworzonego Application Insight – linijki 36 oraz 37.
Ostatnią częścią jest utworzenie SQL Servera oraz bazy danych:
sql.tfPodobnie jak wcześniej, większość właściwości jest moim zdaniem dość jasna. W tym przypadku chciałbym tylko zaznaczyć utworzenie ostatniego zasobu, czyli reguły firewall w SQL Service. Ustawiamy w niej dość specyficzne wartości adresów IP, którymi są same zera. W tym przypadku oznaczają one utworzenie reguły, która umożliwia korzystanie z SQL Servera przez zasoby znajdujące się w Azure. Jest to więc odpowiednik ustawienia „Allow Azure services and resources to access this server” z konfiguracji SQL Servera w Azure.
Cały plik z przykładu znajdziesz w repozytorium przygotowanym do tego wpisu – main.tf.
Utworzenie infrastruktury
Możemy w tym momencie przejść do utworzenia infrastruktury dla środowiska dev. W tym celu wystarczy wykonać komendę (oczywiście po wcześniejszej konfiguracji lokalnego środowiska opisanego w wpisie Terraform i Azure):
terraform apply -var-file="dev.tfvars"
Po dłuższej chwili zasoby zostaną utworzone:
Dla przypomnienia, usunięcie wszystkich utworzonych zasobów możemy wykonać z wykorzystaniem komendy:
terraform destroy -var-file="dev.tfvars"
Przykład
Tradycyjnie na githubie znajdziesz przykład do tego wpisu, w którym znajdują się wszystkie wspomniane powyżej pliki Terraforma – https://github.com/danielplawgo/TerraformAzure
Podsumowanie
W kolejnym wpisie dotyczącym Terraform i Azure pokazałem Ci przede wszystkim, w jaki sposób parametryzować szablony infrastruktury z wykorzystaniem zmiennych (typu Input). Następnie utworzyłem większą ilość zasobów w Azure. Jako przykład posłużyła mi prosta aplikacja webowa.
W kolejnym wpisie pokażę Ci, w jaki sposób wykonywać skrypty Terraform w Azure DevOps.
1 thought on “Terraform i Azure – przykład”