linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • База знаний
  • Шпаргалка
  • Capstone
  • Собеседование
home/terraform/kb/Основы Terraform/tf-interpolation

kb/core ── Основы Terraform ── beginner

${...}: подстановка значений в строки

${expression} внутри строки: подстановка значения выражения. ${var.env}, ${aws_s3_bucket.demo.id}. Если выражение. Это единственное значение аргумента (без обёртки в строку), современный HCL разрешает писать без ${...}.

view as markdown

Что делает ${...}

Внутри строки ${...}, это шаблон. Внутри фигурных скобок может быть любое выражение HCL: переменная, ссылка на ресурс, функция, условие.

hcl
bucket = "myapp-${var.env}"
# = "myapp-dev" если var.env = "dev"
tags = {
  Name = "${local.prefix}-bucket-${count.index}"
  # = "myapp-dev-bucket-0", "myapp-dev-bucket-1", ...
}
user_data = <<EOF
#!/bin/bash
echo "Environment: ${var.env}"
echo "Region: ${data.aws_region.current.name}"
EOF

Если есть необычные требования к строке, внутри ${...} можно вызывать функции:

hcl
bucket = "${var.app}-${upper(var.env)}-${formatdate("YYYY", timestamp())}"

Когда ${...} обязательны, когда нет

В старом HCL (Terraform до 0.12) ${...} нужны были везде:

hcl
count = "${var.instance_count}"           # старый стиль
ami   = "${data.aws_ami.ubuntu.id}"        # старый стиль

В современном HCL, ${...} нужны только если значение, часть большей строки:

hcl
# часть строки → ${...} обязательны
bucket = "myapp-${var.env}-logs"
# вся строка = одно выражение → ${...} НЕ нужны и не рекомендуются
count  = var.instance_count
ami    = data.aws_ami.ubuntu.id
region = "us-east-1"   # литерал, кавычки нужны, ${...} нет

terraform fmt уберёт лишние ${...} автоматически. А terraform validate выдаст warning на устаревший стиль.

Heredoc для многострочных строк

Если нужна многострочная строка с подстановками:

hcl
user_data = <<EOT
#!/bin/bash
set -e
echo "Hello from ${var.env}!"
apt-get update
apt-get install -y nginx
EOT

<<EOT ... EOT (любой маркер вместо EOT) сохраняет всё между ними как строку. Внутри работают ${...}.

Heredoc с дефисом, обрезает лидирующие пробелы:

hcl
config = <<-EOT
    key = "value"
    another = "thing"
    EOT
# = "key = \"value\"\nanother = \"thing\"\n", без отступов

Без дефиса, отступы остаются как есть. С дефисом. Terraform убирает наименьший общий отступ.

Спецсимволы внутри ${...}

Если внутри ${...} нужны фигурные скобки или знак доллара буквально, экранируйте:

hcl
# ${{var}}. Terraform увидит ${{var}} как «начало interpolation, потом литерал {var}»
# Это ошибка. Правильно, экранирование:
literal = "$${not_interpolation}"

▸"$ {not_interpolation}", в выходной строке без подстановки

literal_dollar = "%%{also_not}"

▸"%{also_not}", % сам по себе не interpolation, но если был бы %{, он начинает шаблон-блок

Знаки $$ и %%, экранирование для interpolation и template-блока соответственно. В обычной работе они нужны редко.

Шаблон-блоки %{...}

Не путать с ${...} (значение): это %{...} (управляющие конструкции):

hcl
user_data = <<-EOT
#!/bin/bash
%{ if var.env == "prod" }
echo "Production setup"
systemctl enable monitoring
%{ else }
echo "Non-prod setup"
%{ endif }
hostnames:
%{ for name in var.hostnames }
- ${name}
%{ endfor }
EOT

Это нужно когда в строке нужна логика. Используется редко, но удобно для cloud-init и user_data скриптов.

Подводные камни

  • ${...} без кавычек, невалидно. ${var.x} без обвязки в строку, ошибка. Если хотите выражение без интерполяции, не оборачивайте в строку: count = var.x.

  • Старый стиль "${var.x}" для одного значения, устарел. Работает, но warning. Лучше count = var.x.

  • Внутри ${...} нельзя многострочно. Это однострочное выражение. Многострочные конструкции, через heredoc.

  • ${...} не делает интерполяцию в state. State хранит уже подставленные значения. Если вы поменяли var.env. Terraform увидит, что bucket теперь должен быть другим, и предложит изменение.

  • Переменная типа list/map в interpolation = ошибка. bucket = "myapp-${var.tags}" где tags, map, упадёт. Только примитивы внутри строк. Для других, отдельные присваивания.

  • Heredoc backtick'и работают по-разному в Windows vs Unix. Если HCL генерируется кросс-платформенно, будьте осторожны с line endings внутри heredoc.

§ команды

bash
terraform fmt -recursive

Уберёт устаревшие ${var.x} обёртки вокруг одиночных выражений автоматически.

bash
terraform console

Можно ввести строку с interpolation и увидеть результат. Удобно для отладки сложных шаблонов.

§ см. также

  • hcl-syntaxHCL: язык, на котором пишут TerraformHCL (HashiCorp Configuration Language): это язык, на котором описывают желаемое состояние инфраструктуры. Похож на JSON, но людям читать легче: можно писать комментарии, переменные, циклы.
  • tf-referencesСсылки в HCL: как читать aws_s3_bucket.demo.bucketЛюбое значение в HCL можно получить через адрес: var.x, local.x, aws_s3_bucket.demo.arn, module.net.vpc_id, data.aws_region.current.name. Понимание этого синтаксиса, половина продуктивности в Terraform.
  • tf-conditional-expressionУсловия и null-safety: ?:, try, can, coalesceТернарный оператор a ? b : c, простой if/else. try(expr, fallback) пытается вычислить или подставляет запасное. can(expr) возвращает true/false. coalesce(...): первый не-null. Все спасают от падений.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки