Краткое руководство. Создание Брандмауэр Azure с несколькими общедоступными IP-адресами — Terraform
В этом кратком руководстве вы используете Terraform для развертывания Брандмауэр Azure с несколькими общедоступными IP-адресами из префикса общедоступного IP-адреса. Развернутый брандмауэр содержит правила преобразования сетевых адресов (NAT), разрешающие подключения по протоколу удаленного рабочего стола к двум виртуальным машинам Windows Server 2019.
Terraform поддерживает определение, предварительный просмотр и развертывание облачной инфраструктуры. С помощью Terraform можно создавать файлы конфигурации с применением синтаксиса HCL. Синтаксис HCL позволяет указать поставщика облачных служб, например Azure, и элементы, составляющие облачную инфраструктуру. После создания файлов конфигурации создается план выполнения, который позволяет предварительно просматривать изменения инфраструктуры до их развертывания. После проверки изменений примените план выполнения для развертывания инфраструктуры.
Дополнительные сведения о Брандмауэре Azure с несколькими общедоступными IP-адресами см. в статье Развертывание Брандмауэра Azure с использованием нескольких общедоступных IP-адресов с помощью Azure PowerShell.
Вы узнаете, как выполнять следующие задачи:
- Создайте случайное значение (для использования в имени группы ресурсов) с помощью random_pet
- Создание случайного пароля для виртуальной машины Windows с помощью random_password
- Создание группы ресурсов Azure с помощью azurerm_resource_group
- Создание префикса общедоступного IP-адреса Azure с помощью azurerm_public_ip_prefix
- Создание общедоступного IP-адреса Azure с помощью azurerm_public_ip
- Создание виртуальная сеть Azure с помощью azurerm_virtual_network
- Создание подсети Azure с помощью azurerm_subnet
- Создание сетевого интерфейса с помощью azurerm_network_interface
- Создание группы безопасности сети (для хранения списка правил безопасности сети) с помощью azurerm_network_security_group
- Создание связи между сетевым интерфейсом и группой безопасности сети с помощью azurerm_network_interface_security_group_association
- Создание виртуальной машины Windows с помощью azurerm_windows_virtual_machine
- Создание политики Брандмауэр Azure с помощью azurerm_firewall_policy
- Создание группы коллекций правил политики Брандмауэр Azure с помощью azurerm_firewall_policy_rule_collection_group
- Создание Брандмауэр Azure с помощью azurerm_firewall
- Создание таблицы маршрутов с помощью azurerm_route_table
- Создание связи между таблицей маршрутов и подсетью с помощью azurerm_subnet_route_table_association
Необходимые компоненты
Реализация кода Terraform
Примечание.
Пример кода для этой статьи находится в репозитории Azure Terraform GitHub. Вы можете просмотреть файл журнала, содержащий результаты теста из текущих и предыдущих версий Terraform.
См. другие статьи и примеры кода, в которых показано, как использовать Terraform для управления ресурсами Azure.
Создайте каталог для тестирования примера кода Terraform и сделайте его текущим каталогом.
Создайте файл с именем
providers.tf
и вставьте следующий код:terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.0" } random = { source = "hashicorp/random" version = "~>3.0" } } } provider "azurerm" { features { virtual_machine { delete_os_disk_on_deletion = true skip_shutdown_and_force_delete = true } } }
Создайте файл с именем
main.tf
и вставьте следующий код:resource "random_pet" "rg_name" { prefix = var.resource_group_name_prefix } resource "random_password" "password" { count = 2 length = 20 min_lower = 1 min_upper = 1 min_numeric = 1 min_special = 1 special = true } resource "azurerm_resource_group" "rg" { name = random_pet.rg_name.id location = var.resource_group_location } resource "azurerm_public_ip_prefix" "pip_prefix" { name = "pip-prefix" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name sku = "Standard" prefix_length = 31 } resource "azurerm_public_ip" "pip_azfw" { name = "pip-azfw" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name sku = "Standard" allocation_method = "Static" public_ip_prefix_id = azurerm_public_ip_prefix.pip_prefix.id } resource "azurerm_public_ip" "pip_azfw_2" { name = "pip-azfw-1" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name sku = "Standard" allocation_method = "Static" public_ip_prefix_id = azurerm_public_ip_prefix.pip_prefix.id } resource "azurerm_virtual_network" "azfw_vnet" { name = "azfw-vnet" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name address_space = ["10.10.0.0/16"] } resource "azurerm_subnet" "azfw_subnet" { name = "AzureFirewallSubnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.azfw_vnet.name address_prefixes = ["10.10.0.0/26"] } resource "azurerm_subnet" "backend_subnet" { name = "subnet-backend" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.azfw_vnet.name address_prefixes = ["10.10.1.0/24"] } resource "azurerm_network_interface" "backend_nic" { count = 2 name = "nic-backend-${count.index + 1}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name ip_configuration { name = "ipconfig-backend-${count.index + 1}" subnet_id = azurerm_subnet.backend_subnet.id private_ip_address_allocation = "Dynamic" } } resource "azurerm_network_security_group" "backend_nsg" { name = "nsg-backend" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name security_rule { name = "RDP" priority = 300 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3389" source_address_prefix = "*" destination_address_prefix = "*" } } resource "azurerm_network_interface_security_group_association" "vm_backend_nsg_association" { count = 2 network_interface_id = azurerm_network_interface.backend_nic[count.index].id network_security_group_id = azurerm_network_security_group.backend_nsg.id } resource "azurerm_windows_virtual_machine" "vm_backend" { count = 2 name = "vm-backend-${count.index + 1}" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location size = var.virtual_machine_size admin_username = var.admin_username admin_password = random_password.password[count.index].result network_interface_ids = [azurerm_network_interface.backend_nic[count.index].id] os_disk { caching = "ReadWrite" storage_account_type = "Standard_LRS" } source_image_reference { publisher = "MicrosoftWindowsServer" offer = "WindowsServer" sku = "2019-Datacenter" version = "latest" } } resource "azurerm_firewall_policy" "azfw_policy" { name = "azfw-policy" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location sku = var.firewall_sku_tier threat_intelligence_mode = "Alert" } resource "azurerm_firewall_policy_rule_collection_group" "policy_rule_collection_group" { name = "RuleCollectionGroup" firewall_policy_id = azurerm_firewall_policy.azfw_policy.id priority = 300 application_rule_collection { name = "web" priority = 100 action = "Allow" rule { name = "wan-address" protocols { type = "Http" port = 80 } protocols { type = "Https" port = 443 } destination_fqdns = ["getmywanip.com"] source_addresses = ["*"] } rule { name = "google" protocols { type = "Http" port = 80 } protocols { type = "Https" port = 443 } destination_fqdns = ["www.google.com"] source_addresses = ["10.10.1.0/24"] } rule { name = "wupdate" protocols { type = "Http" port = 80 } protocols { type = "Https" port = 443 } destination_fqdn_tags = ["WindowsUpdate"] source_addresses = ["*"] } } nat_rule_collection { name = "Coll-01" action = "Dnat" priority = 200 rule { name = "rdp-01" protocols = ["TCP"] translated_address = "10.10.1.4" translated_port = "3389" source_addresses = ["*"] destination_address = azurerm_public_ip.pip_azfw.ip_address destination_ports = ["3389"] } rule { name = "rdp-02" protocols = ["TCP"] translated_address = "10.10.1.5" translated_port = "3389" source_addresses = ["*"] destination_address = azurerm_public_ip.pip_azfw.ip_address destination_ports = ["3389"] } } } resource "azurerm_firewall" "fw" { name = "azfw" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name sku_name = "AZFW_VNet" sku_tier = var.firewall_sku_tier ip_configuration { name = "azfw-ipconfig" subnet_id = azurerm_subnet.azfw_subnet.id public_ip_address_id = azurerm_public_ip.pip_azfw.id } ip_configuration { name = "azfw-ipconfig-2" public_ip_address_id = azurerm_public_ip.pip_azfw_2.id } firewall_policy_id = azurerm_firewall_policy.azfw_policy.id } resource "azurerm_route_table" "rt" { name = "rt-azfw-eus" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name disable_bgp_route_propagation = false route { name = "azfw" address_prefix = "0.0.0.0/0" next_hop_type = "VirtualAppliance" next_hop_in_ip_address = "10.10.0.4" } } resource "azurerm_subnet_route_table_association" "jump_subnet_rt_association" { subnet_id = azurerm_subnet.backend_subnet.id route_table_id = azurerm_route_table.rt.id }
Создайте файл с именем
variables.tf
и вставьте следующий код:variable "resource_group_location" { type = string description = "Location for all resources." default = "eastus" } variable "resource_group_name_prefix" { type = string description = "Prefix for the Resource Group Name that's combined with a random id so name is unique in your Azure subcription." default = "rg" } variable "firewall_sku_tier" { type = string description = "Firewall SKU." default = "Premium" # Valid values are Standard and Premium validation { condition = contains(["Standard", "Premium"], var.firewall_sku_tier) error_message = "The SKU must be one of the following: Standard, Premium" } } variable "virtual_machine_size" { type = string description = "Size of the virtual machine." default = "Standard_D2_v3" } variable "admin_username" { type = string description = "Value of the admin username." default = "azureuser" }
Создайте файл с именем
outputs.tf
и вставьте следующий код:output "resource_group_name" { value = azurerm_resource_group.rg.name } output "backend_admin_password" { sensitive = true value = azurerm_windows_virtual_machine.vm_backend[*].admin_password }
Инициализация Terraform
Запустите terraform init, чтобы инициализировать развертывание Terraform. Эта команда скачивает поставщик Azure, необходимый для управления ресурсами Azure.
terraform init -upgrade
Основные моменты:
- Параметр
-upgrade
обновляет необходимые подключаемые модули поставщика до последней версии, которая соответствует ограничениям версии конфигурации.
Создание плана выполнения Terraform
Чтобы создать план выполнения, выполните terraform plan.
terraform plan -out main.tfplan
Основные моменты:
- Команда
terraform plan
создает план выполнения, но не выполняет его. Вместо этого она определяет, какие действия необходимы для создания конфигурации, заданной в файлах конфигурации. Этот шаблон позволяет проверить, соответствует ли план выполнения вашим ожиданиям, прежде чем вы начнете вносить изменения в фактические ресурсы. - Необязательный параметр
-out
позволяет указать выходной файл для плана. Использование параметра-out
гарантирует, что проверяемый план полностью соответствует применяемому.
Применение плана выполнения Terraform
Выполните terraform apply, чтобы применить план выполнения к вашей облачной инфраструктуре.
terraform apply main.tfplan
Основные моменты:
- В примере
terraform apply
команды предполагается, что вы ранее выполнили.terraform plan -out main.tfplan
- Если для параметра
-out
указано другое имя файла, используйте то же имя в вызове кterraform apply
. - Если вы не использовали параметр
-out
, вызовитеterraform apply
без параметров.
Проверка результатов
Получите имя группы ресурсов Azure.
resource_group_name=$(terraform output -raw resource_group_name)
Выполните команду az network ip-group list , чтобы отобразить две новые группы IP-адресов.
az network ip-group list --resource-group $resource_group_name
Очистка ресурсов
Если вам больше не нужны ресурсы, созданные через Terraform, выполните следующие действия:
Выполните команду terraform plan и укажите флаг
destroy
.terraform plan -destroy -out main.destroy.tfplan
Основные моменты:
- Команда
terraform plan
создает план выполнения, но не выполняет его. Вместо этого она определяет, какие действия необходимы для создания конфигурации, заданной в файлах конфигурации. Этот шаблон позволяет проверить, соответствует ли план выполнения вашим ожиданиям, прежде чем вы начнете вносить изменения в фактические ресурсы. - Необязательный параметр
-out
позволяет указать выходной файл для плана. Использование параметра-out
гарантирует, что проверяемый план полностью соответствует применяемому.
- Команда
Выполните команду terraform apply, чтобы применить план выполнения.
terraform apply main.destroy.tfplan
Устранение неполадок с Terraform в Azure
Устранение распространенных проблем при использовании Terraform в Azure