Начало работы с террафом на Azure (9 части серии)
- Предварительные условия
- Шаг 1 — Функции
- Шаг 2 — Комплексные выражения
- Шаг 3 — петли
- Вывод
Когда мы начинаем строить инфраструктуру с террафом, логика, используемая для создания взаимосвязей модулей, становится все более сложной. Вот почему важно понимать варианты и возможности HCl (язык конфигурации Hashicorp). Это не только облегчит создание необходимого логического потока в нашем коде, но мы также можем оптимизировать наши конфигурации. Написание конфигурации террафора по-разному может потенциально может обеспечить повышение производительности в развертывании.
Понимание того, как создавать петли и расширенные выражения могут дать нашему коду очистительным взглядом и предоставлять нашим товарищам по команде более точным пониманием инфраструктуры при чтении конфигурации террафора. Помните, наш террафом не предназначен просто развернуть нашу инфраструктуру и выполнить работу. Цель HCl состоит в том, чтобы преодолеть разрыв между человеческими и удобными для машиностроенных интерфейсов, обеспечивая код, который легко читается, и хорошо работает с командной строкой одновременно.
В этом руководстве мы собираемся создать модуль и узнать, как использовать функции, выражения и петли в наших конфигурациях террафора.
Предварительные условия
Если вы хотите следовать вместе с концепциями в этом руководстве, вам нужно будет настроить следующее:
- Azure подписка Отказ
- Лазурная облачная оболочка. Обязательно проверьте предпосылки на «Начало работы с террафорами на Azure: развертывание ресурсов» Для руководства о том, как установить это.
Шаг 1 — Функции
HCl содержит встроенные функции, которые можно вызвать в выражении, чтобы логически создавать значения для наших аргументов. С террафом мы можем использовать интерактивную консоль для тестирования наших выражений террафора вместо того, чтобы каждый раз запустить нашу конфигурацию Terraform. Просто введите следующий синтаксис, где установлен террафом. Это работает в лазурной облачной оболочке, а также:
terraform console
Вы будете направлены на консоль террафора, которая отобразит >
Отказ Вы можете проверить некоторые из этих примеров функций в этом руководстве в вашей собственной консоли Terraform. Есть много Встроенные функции , но мы перейдем на наиболее часто используемые:
Нижнее Полезно для значений, которые необходимо всегда быть ниже, как имена учетных записей хранения:
> lower("TFStoragesta") tfstoragesta
Заменить Полезно для манипулирования схемами именования или цифровыми форматами определенных значений. Формат следующий:
replace(string, substring, replacement)
Простой корпус использования будет заменять строку в тексте:
> replace("Luke likes CloudSkills", "likes", "loves") Luke loves CloudSkills
Более практичное использование случая будет использовать заменить
Функция с запросом Regex, чтобы поменять любую подписку ID на строке идентификатора ресурса с определенной подпиской:
> replace("/subscriptions/f8c37571-4325-4a97-977b-7a216e64bae3/resourceGroups/rg-remotestatetfc", "/[0-9A-Fa-f]{8}-(?:[0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}/", "c1c37531-2355-4a57-947b-4e236e64bae3") /subscriptions/c1c37531-2355-4a57-947b-4e236e64bae3/resourceGroups/rg-remotestatetfc
Мин и Макс Используются для поиска самых высоких и самых низких значений в наборе номеров, которые могут быть полезны для определения наибольшего или наименьшего ресурса:
> max(32,64,99) 99
> min (32,128,1024) 32
Сплит Может использоваться для получения двух строковых значений из одного значения. Например, Standard_lrs
Строка типа хранения может быть разделена на Azurerm_Storage_account
Ресурс, который принимает следующие два аргумента для Account_teir
и Account_replication_type
:
resource "azurerm_storage_account" "example" { name = "storageaccountname" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location account_tier = "Standard" account_replication_type = "LRS" }
Мы могли бы взять переменную вход Standard_lrs
и использовать разделение, чтобы получить каждое значение, уменьшающее количество необходимых переменных:
> split("_","Standard_LRS") [ "Standard", "LRS", ]
Элемент Затем можно использовать для доступа к каждому индексу списка путем обертывания нашей функции разделения с помощью функции элемента и указание значения индекса:
> element(split("_","Standard_LRS"), 0) Standard
Затем мы могли бы написать наш блок ресурсов, как следующие, если мы создали входную переменную для Standard_lrs
нить:
resource "azurerm_storage_account" "example" { name = "storageaccountname" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location account_tier = element(split("_","var.storage_type"), 0) account_replication_type = element(split("_","var.storage_type"), 1) }
Coalesce возьму серию аргументов и вернуть первый, который не нуль или пустая строка ""
:
> coalesce("40", "50", "20") 40 > coalesce( "", "50", "20") 50
Это может быть полезно для создания набора дополнительных переменных и выбора того, который содержит значение:
Примечание: В этой статье есть несколько конфигураций, которая будет усечена ...
Чтобы уменьшить количество кода в этой статье.
resource "azurerm_virtual_machine" "main" { name = "${var.prefix}-vm" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name network_interface_ids = [azurerm_network_interface.main.id] vm_size = coalesce( var.small, var.medium, var.large) ...
Длина Возвращает численную длину строки, списка или карты:
> length(["32GB", "64GB"]) 2
Это очень полезно для получения числа предмета. Для приведенного выше примера мы можем определить, что у нас есть два размера диска, и мы будем требовать создания 2 дисков. Затем мы могли бы накормить эту ценность в петлю, которую мы будем демонстрация позже в этом руководстве.
Установленная продукция Понадобится все возможные комбинации данного набора:
> setproduct(["development", "staging", "production"], ["EastUS", "WestUS"]) [ [ "development", "EastUS", ], [ "development", "WestUS", ], [ "staging", "EastUS", ], [ "staging", "WestUS", ], [ "production", "EastUS", ], [ "production", "WestUS", ], ]
Файл прочитал содержимое файла и вернуть его как строку:
> file("${path.module}/test.ps1") #This is an empty PS1
Это очень полезно при использовании template_file
Тип источника данных, который позволяет вставлять переменные в ваши файлы, а затем передавать их в другой ресурс для использования. Ниже у нас есть test.ps1
Файл, который установит DNS-адреса сервера. У нас есть две переменные, вставленные в наш скрипт PowerShell, представленный $ {Dns_server1}
и $ {Dns_server2}
:
# test.ps1 Set-DnsClientServerAddress -InterfaceIndex 12 -ServerAddresses ("${DNS_Server1}","{DNS_Server2}")
Далее мы можем использовать template_file
Ресурс для указания test.ps1
Сценарий и замените $ {Dns_server1}
и $ {Dns_server2}
Переменные внутри скрипта со своими соответствующими значениями, объявленными в Варс
блокировать. Затем мы можем ссылаться в недавно преобразованные test.ps1
Файл, который включает в себя правильные значения для серверов DNS с помощью data.template_file.init.rended
в custom_data
Атрибут блока ресурсов виртуального машины:
data "template_file" "init" { template = "${file("./test.ps1")}" vars = { DNS_Server1 = "10.0.0.1" DNS_Server2 = "10.0.0.2" } resource "azurerm_virtual_machine" "main" { ... os_profile { computer_name = "myserver" admin_username = "adminuser" admin_password = "badpassword123" custom_data = data.template_file.init.rendered } ... }
Функции — отличный способ манипулировать данными в наших конфигурациях, однако иногда существует необходимость включить больше логики в наш код. Именно здесь выражения вступают в игру.
Шаг 2 — Комплексные выражения
Выражения используются для вычисления значений в наших конфигурациях HCL. Комплексные выражения позволяют нам предоставить дополнительную логику нашим ресурсам развернутым. Ниже приведены некоторые примеры популярных выражений, которые мы можем использовать в нашем коде:
Операторы
Операторы либо сочетают в себе результат двух значений и изготавливают третье или принимают одно значение и преобразуют его. Типичные операторы, используемые в конфигурациях, являются следующими:
- Равный
A == B
ЕслиА
равноb
Тогда результат правда. - Не равно
А
ЕслиА
не равенb
Тогда результат правда. - Либо или
А
BЕсли либо
Аили
b - верно, то результат правда. Оба правда
A && B
Если оба
Аи
B - верны, то результат правда. Не правда
! А
Условия
Условия Определите значение, основанное на результате двух выражений BoOL (True или False):
condition ? true : false
Это обычно используется для настройки значения по умолчанию в конфигурации террафора. Например, если у нас есть модуль виртуального машины и хотел бы предоставить возможность развертывать виртуальную машину к другому местоположению, чем группа ресурсов, мы могли бы создать переменную для vm_location
и установить по умолчанию для ""
как ниже:
variable "vm_location" { type = string description = "Azure location of terraform server environment" default = "" }
В нашем блоке ресурсов виртуальной машины мы могли бы использовать условное выражение для Расположение
аргумент Выражение условия обеспечивает логику использовать значение для var.vm_location
Если это не пустая строка. Если var.vm_location
По-прежнему является пустой строкой, потому что пользователь модуля никогда не указан ни один, то экспрессия условия обеспечивает логику по умолчанию на местоположение нашей группы ресурсов:
resource "azurerm_virtual_machine" "main" { name = "MyVMName" location = var.vm_location != "" ? var.vm_location : azurerm_resource_group.main.location ...
Для выражений
Для выражений позволяют нам принимать значение и изменить его. Мы можем использовать это, чтобы повторить список значений и изменять их. Например, мы можем получить список подсетей из Azurerm_virtual_network
Источник данных и использовать для
Выражение, чтобы повторить каждую подсеть и изменить выходное форматирование его строчным буквам:
data "azurerm_virtual_network" "example" { name = "LukeLab-NC-Prod-Vnet" resource_group_name = "NetworkingTest-RG" } output "subnets" { value = [for s in data.azurerm_virtual_network.example.subnets : lower(s)] }
При запуске этого конфигурации вывод следующий:
Outputs: subnets = [ "lukeapp-nc-prod-subnet", "lukeapp5-nc-prod-subnet", "lukeapp4-nc-prod-subnet", "lukeapp3-nc-prod-subnet", "lukeapp2-nc-prod-subnet", ]
Обратите внимание на выражение в []
. Это даст нам вывод кортежа. Мы также можем изменить тип вывода на объект, упаковывая наши для выражения в {}
вместо. Также мы должны включать два выражения результата, используя =>
Символ, чтобы отделить их:
data "azurerm_virtual_network" "example" { name = "LukeLab-NC-Prod-Vnet" resource_group_name = "NetworkingTest-RG" } output "subnets" { value = {for s in data.azurerm_virtual_network.example.subnets : s => lower(s)} }
Вывод затем изменяется на тип объекта без двух результатов:
Outputs: subnets = { "LukeApp-NC-Prod-Subnet" = "lukeapp-nc-prod-subnet" "LukeApp2-NC-Prod-Subnet" = "lukeapp2-nc-prod-subnet" "LukeApp3-NC-Prod-Subnet" = "lukeapp3-nc-prod-subnet" "LukeApp4-NC-Prod-Subnet" = "lukeapp4-nc-prod-subnet" "LukeApp5-NC-Prod-Subnet" = "lukeapp5-nc-prod-subnet" }
Мы также можем выполнить более продвинутую логику с нашими выражениями. Мы можем отфильтровать наши результаты, включая заявление о если после чего следует какая-то логика. В этом примере мы только лидирующие подсети, которые не являются пустой строкой:
[for s in data.azurerm_virtual_network.example.subnets : lower(s) if s != ""
Для более продвинутого примера этого мы можем использовать Regexall
Чтобы отфильтровать наши результаты, чтобы включить только подсети, которые соответствуют нашим требованиям Regeex. В этом примере мы выбираем только подсети с Lukeapp 2-4 во имя. Кроме того, обратите внимание, что мы обертываем наше Regexall
Функция с Длина
Функция, а затем проверка, чтобы убедиться, что она больше 0. Это рекомендуемый способ подтвердить строку, соответствующую требованиям Regeex. Если бы мы пропустили использование длина
Экспрессия IF ошибся, когда запрос REGEX не соответствует другим подсетам:
data "azurerm_virtual_network" "example" { name = "LukeLab-NC-Prod-Vnet" resource_group_name = "NetworkingTest-RG" } output "subnets" { value = [for s in data.azurerm_virtual_network.example.subnets : s if length(regexall("LukeApp[2-4]-NC-Prod-Subnet", s)) > 0] }
Когда мы запускаем это, мы получаем только подсети, которые соответствуют нашему утверждению Regex:
Outputs: subnets = [ "LukeApp4-NC-Prod-Subnet", "LukeApp3-NC-Prod-Subnet", "LukeApp2-NC-Prod-Subnet", ]
Выражения Splat.
Выражения SPLAT являются более чистым способом выполнения некоторых из тех же задач, которые мы можем сделать с для
выражение. В нашем предыдущем для
Пример выражения, мы перечислили подсети виртуальной сети, как следующее:
[for s in data.azurerm_virtual_network.example.subnets : s]
Вместо этого мы можем использовать выражение Splat, как так. Символ [*] направляет нас по поводу выполнения всех элементов в списке:
data.azurerm_virtual_network.example[*].subnets
Мы также можем ссылаться на индекс атрибута, чтобы выбрать первую подсеть в списке:
data.azurerm_virtual_network.example[*].subnets[0]
Комплексные выражения — отличный способ добавить логику на наших конфигураций Terraform и позволить нам создавать модули, которые могут быть универсальными. Например, если мы хотели, чтобы все VMS развернуты в среде разработки, чтобы использовать более медленные, менее дорогие типы дисков, мы могли бы кодировать логику с условным выражением. Использование переменной var.environment
Чтобы указать окружающую среду, которую мы хотим развернуть, мы могли бы ссылаться на то, что переменная для условно принять решение использовать либо Standard_lrs
или Premium_lrs
Тип диска:
resource "azurerm_virtual_machine" "main" { ... storage_os_disk { name = "myosdisk1" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = var.environment == "Development" ? "Standard_LRS" : "Premium_LRS" } ...
Функции и сложные выражения могут сделать много нашего тяжелого подъема, однако в нашем инструменте есть еще один инструмент, который может помочь упростить наш код. В следующем разделе мы будем покрывать петли.
Шаг 3 — петли
Петли в террафоре могут помочь нам во многих отношениях. Мы можем быстро перейти через коллекцию компонентов с петлей. Мы также можем эффективно масштабировать наши ресурсы с использованием петлей. Вот некоторые из способов петли через ресурсы в террафоре:
Считать
Счет — очень популярная техника в конфигурациях террафора. Это позволяет нам создавать несколько экземпляров блока ресурсов. Почти все блоки ресурсов могут использовать Считать
атрибут. Ниже приведен пример Azurerm_Resource_Group
Блок ресурсов, который имеет Считать
Атрибут установлен на 3
Отказ Это говорит террафору создать этот ресурс три раза. Также обратите внимание, мы изменяем имя группы ресурсов каждый раз; В противном случае наш код будет ошибся, потому что мы не можем иметь группы ресурсов с дублирующими именами. Мы используем Count.index
Переменная, которая доступна только тогда, когда Считать
аргумент используется. Count.index
Определяет индексное значение нашего ресурса, который является числом, присвоенным «точению этого ресурса в списке». Нумерация индекса начинается в 0. Так что, если мы развертываем ресурс с Считать
3
У нас будут три индекса 0,1 и 2:
provider "azurerm" { features {} } resource "azurerm_resource_group" "main" { count = 3 name = "rg-MyResourceGroup-${count.index}" location = "West US 2" }
Когда мы бежим План террафора
Против этой конфигурации мы можем видеть, что мы будем развернуть три группы ресурсов:
Terraform will perform the following actions: # azurerm_resource_group.main[0] will be created + resource "azurerm_resource_group" "main" { + id = (known after apply) + location = "westus2" + name = "rg-MyResourceGroup-0" } # azurerm_resource_group.main[1] will be created + resource "azurerm_resource_group" "main" { + id = (known after apply) + location = "westus2" + name = "rg-MyResourceGroup-1" } # azurerm_resource_group.main[2] will be created + resource "azurerm_resource_group" "main" { + id = (known after apply) + location = "westus2" + name = "rg-MyResourceGroup-2" } Plan: 3 to add, 0 to change, 0 to destroy.
Количество используется для условной логики. Если мы установим Считать
Значение ресурса в 0
Террафом будет развернуть 0 копий этого ресурса. Это удобно для создания логики для развертывания ресурсов только в определенных обстоятельствах. В приведенном ниже примере у нас есть переменная Bool для bootdiag_storage
Отказ У нас также есть блок ресурсов для хранения Azure для хранения нашей загрузочной диагностики. Обратите внимание на считать
Аргумент теперь имеет условное выражение для оценки, если bootdiag_storage
Переменная верна или нет. Если переменная установлена на true, установите Считать
аргумент для 1
Указывая на то, что мы разверним этот ресурс. Если переменная установлена на false, Считать
затем установлен на 0
указывая на то, что Azure_Storage_account
Ресурс не будет развернут:
provider "azurerm" { features {} } variable "bootdiag_storage" { type = bool description = "Enter the name of the boot diagnostic storage account if one is desired" default = false } resource "azurerm_resource_group" "rg" { name = "rg-MyResourceGroup" location = "West US 2" } resource "azurerm_storage_account" "bootdiag" { count = var.bootdiag_storage ? 1 : 0 name = "myterraformvmsadiag" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location account_tier = "Standard" account_replication_type = "GRS" }
Для каждого
For_each петли позволяют нам повторять список или карту. Это позволяет нам иметь более чистый код. Например, вместо создания azurerm_network_security_Rule
Ресурс для каждого правила мы хотим создавать для нашего NSG, мы можем просто создать переменную карты InBound_Rules
Отказ Затем мы можем использовать for_each
Чтобы зацикливаться через каждый элемент на нашей карте и создать правило для каждого. Кроме того, обратите внимание, что мы используем Каждый. Кей
и каждая Переменные в нашей конфигурации, чтобы указать ключ и ценные пары на нашей карте:
provider "azurerm" { features {} } variable "inbound_rules" { type = map description = "A map of allowed inbound ports and their priority value" default = { 101 = 3389 102 = 22 103 = 443 } } resource "azurerm_resource_group" "rg" { name = "rg-mytesourcegroup" location = "West US 2" } resource "azurerm_network_security_group" "nsg" { name = "nsg-mysecuritygroup" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name } resource "azurerm_network_security_rule" "nsg_rule" { for_each = var.inbound_rules name = "port_${each.value}" priority = each.key direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = each.value source_address_prefix = "*" destination_address_prefix = "*" resource_group_name = azurerm_resource_group.rg.name network_security_group_name = azurerm_network_security_group.nsg.name }
Когда мы бежим План террафора
Мы можем видеть, что все наши блоки ресурсов правила NSG будут созданы со значениями нашей карты:
Terraform will perform the following actions: # azurerm_network_security_group.nsg will be created + resource "azurerm_network_security_group" "nsg" { + id = (known after apply) + location = "westus2" + name = "nsg-mysecuritygroup" + resource_group_name = "rg-mytesourcegroup" + security_rule = (known after apply) } # azurerm_network_security_rule.nsg_rule["101"] will be created + resource "azurerm_network_security_rule" "nsg_rule" { + access = "Allow" + destination_address_prefix = "*" + destination_port_range = "3389" + direction = "Inbound" + id = (known after apply) + name = "port_3389" + network_security_group_name = "nsg-mysecuritygroup" + priority = 101 + protocol = "Tcp" + resource_group_name = "rg-mytesourcegroup" + source_address_prefix = "*" + source_port_range = "*" } # azurerm_network_security_rule.nsg_rule["102"] will be created + resource "azurerm_network_security_rule" "nsg_rule" { + access = "Allow" + destination_address_prefix = "*" + destination_port_range = "22" + direction = "Inbound" + id = (known after apply) + name = "port_22" + network_security_group_name = "nsg-mysecuritygroup" + priority = 102 + protocol = "Tcp" + resource_group_name = "rg-mytesourcegroup" + source_address_prefix = "*" + source_port_range = "*" } # azurerm_network_security_rule.nsg_rule["103"] will be created + resource "azurerm_network_security_rule" "nsg_rule" { + access = "Allow" + destination_address_prefix = "*" + destination_port_range = "443" + direction = "Inbound" + id = (known after apply) + name = "port_443" + network_security_group_name = "nsg-mysecuritygroup" + priority = 103 + protocol = "Tcp" + resource_group_name = "rg-mytesourcegroup" + source_address_prefix = "*" + source_port_range = "*" } # azurerm_resource_group.rg will be created + resource "azurerm_resource_group" "rg" { + id = (known after apply) + location = "westus2" + name = "rg-mytesourcegroup" } Plan: 5 to add, 0 to change, 0 to destroy.
Динамические блоки
Ресурсы, которые содержат повторяемые блоки конфигурации, могут использовать динамические блоки. Например, Azurerm_Virtual_Machine
Ресурс включает в себя Storage_data_disk
Блок для определения конфигурации наших дисков данных VM. Этот блок может использоваться несколько раз внутри Azurerm_Virtual_Machine
Чтобы указать несколько дисков данных. Вместо того, чтобы повторять одну и ту же блочную структуру снова и снова, мы можем использовать динамические блоки для упрощения нашего кода. Это делается путем префикса блока с динамический
и используя for_each
Итерации через нашу Storage_data_disk
блокировать.
В этом примере у нас есть переменная disk_size_gb.
Это может принять строку, разделенные запятыми чисел, чтобы указать размер дисков для добавления. Поэтому, если мы хотели, чтобы три диска, которые размечены как 32 ГБ, 64 ГБ и 128 ГБ, мы бы установили эту переменную к «32 64,128» в нашем Terraform.tfvars
файл.
В for_each
Аргумент под нашими Dynamic Storage_data_disk
блок, мы используем Сплит
Функция, чтобы отделить значения размера нашего диска и итерации через каждый. Мы используем Storage_data_disk.value
Чтобы ссылаться на значение каждого числа в disk_size_gb
для каждого размера диска. Кроме того, мы используем Storage_data_disk.key
Для ссылки на индекс номер нашего Storage_data_disk
блок и используя это значение в название
и Лунь
Аргументы для предоставления уникальных значений:
variable "disk_size_gb" { description = "Size of disks in GBs. Choose multiple disks by comma separating each size" type = string default = "64" } # Create virtual machine resource "azurerm_virtual_machine" "vm" { name = var.servername location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name network_interface_ids = [azurerm_network_interface.nic.id] vm_size = "Standard_D2s_v3" ... dynamic storage_data_disk { for_each = split(",", var.disk_size_gb) content { name = "${var.servername}_datadisk_${storage_data_disk.key}" create_option = "Empty" lun = storage_data_disk.key disk_size_gb = storage_data_disk.value managed_disk_type = "StandardSSD_LRS" } } ...
Когда мы бежим План террафора
Против этой конфигурации мы получаем следующий выход, указав Storage_data_disk
Блоки для наших трех дисков:
# azurerm_virtual_machine.vm will be created + resource "azurerm_virtual_machine" "vm" { + availability_set_id = (known after apply) + delete_data_disks_on_termination = false + delete_os_disk_on_termination = false + id = (known after apply) + license_type = (known after apply) + location = "westus2" + name = "vmterraform" + network_interface_ids = (known after apply) + resource_group_name = "rg-terraexample" + tags = (known after apply) + vm_size = "Standard_D2s_v3" + identity { + identity_ids = (known after apply) + principal_id = (known after apply) + type = (known after apply) } + os_profile { + admin_password = (sensitive value) + admin_username = "joeblow" + computer_name = "vmterraform" + custom_data = "c991e3a089d3ad26ec85af93f698c375db0933f2" } + os_profile_windows_config { + enable_automatic_upgrades = false + provision_vm_agent = true + additional_unattend_config { + component = "Microsoft-Windows-Shell-Setup" + content = (sensitive value) + pass = "oobeSystem" + setting_name = "FirstLogonCommands" } + additional_unattend_config { + component = "Microsoft-Windows-Shell-Setup" + content = (sensitive value) + pass = "oobeSystem" + setting_name = "AutoLogon" } } + storage_data_disk { + caching = (known after apply) + create_option = "empty" + disk_size_gb = 32 + lun = 0 + managed_disk_id = (known after apply) + managed_disk_type = "StandardSSD_LRS" + name = "vmterraform_datadisk_0" + write_accelerator_enabled = false } + storage_data_disk { + caching = (known after apply) + create_option = "empty" + disk_size_gb = 64 + lun = 1 + managed_disk_id = (known after apply) + managed_disk_type = "StandardSSD_LRS" + name = "vmterraform_datadisk_1" + write_accelerator_enabled = false } + storage_data_disk { + caching = (known after apply) + create_option = "empty" + disk_size_gb = 128 + lun = 2 + managed_disk_id = (known after apply) + managed_disk_type = "StandardSSD_LRS" + name = "vmterraform_datadisk_2" + write_accelerator_enabled = false } + storage_image_reference { + offer = "WindowsServer" + publisher = "MicrosoftWindowsServer" + sku = "2019-Datacenter" + version = "latest" } + storage_os_disk { + caching = "ReadWrite" + create_option = "FromImage" + disk_size_gb = (known after apply) + managed_disk_id = (known after apply) + managed_disk_type = "Premium_LRS" + name = "stvmvmterraformos" + os_type = (known after apply) + write_accelerator_enabled = false } }
Петли отлично подходят для уменьшения повторяющегося кода и создания масштабируемых ресурсов. Однако они также могут добавить дополнительную сложность для других, читая конфигурацию Terraform, поэтому выбирайте мудро при использовании петлей в Terraporm Code.
Вывод
В этой статье мы узнали о функциях, сложных выражениях и петлях. Мы рассмотрели примеры и обсудили свои преимущества и случаи использования в нашем террафоре. Язык HCl — это как читаемый человеком, так и достаточно удобный для машинно, чтобы выполнить сложную логику, описанную в этом руководстве. Тем не менее, существует баланс для написания инфраструктурного кода, который не только принесет работу, но также предоставляет документацию другому члену команды. Используйте их там, где это имеет смысл, но не до такой степени, что код трудно понять. Помните, что простота является важнейшим компонентом создания длительных автоматизированных решений.
Начало работы с террафом на Azure (9 части серии)
Оригинал: «https://dev.to/cloudskills/getting-started-with-terraform-on-azure-functions-expressions-and-loops-363g»