Передача значений: tfvars и приоритеты
Объявить переменную — половина дела. Вторая половина — передать ей значение, и способов несколько: флаг -var, файлы .tfvars, переменные окружения TF_VAR_. У них строгий порядок приоритета.
Запомните порядок приоритета — иначе однажды будете полчаса гадать, почему prod взял значение из staging. Побеждает самый «поздний» и явный источник.
Один и тот же конфиг прогоняется для разных окружений именно за счёт разных наборов значений. Для каждого окружения держат свой файл переменных: dev.tfvars, prod.tfvars, и применяют его флагом -var-file.
Источники значений
# 1. флаг командной строки (высший приоритет среди явных)
terraform apply -var="instance_type=t3.large"
# 2. конкретный файл переменных
terraform apply -var-file="prod.tfvars"
# 3. переменная окружения (префикс TF_VAR_)
export TF_VAR_db_password="secret123"
terraform apply
# terraform.tfvars и *.auto.tfvars подхватываются автоматически
Порядок приоритета (от низшего к высшему): значения по умолчанию → переменные окружения TF_VAR_ → terraform.tfvars → *.auto.tfvars → -var-file → -var. Чем источник «правее» в этой цепочке, тем он сильнее.
ПРИОРИТЕТ (слабее -> сильнее): default -> TF_VAR_env -> terraform.tfvars -> *.auto.tfvars -> -var-file -> -var слабее сильнее побеждает самый правый источник, задавший значение
Как работает под капотом
Terraform проходит источники в порядке приоритета и каждый следующий перезаписывает предыдущий. Смоделируем это слияние слоёв:
# слои в порядке возрастания приоритета
layers = [
("default", {"region": "us-east-1", "size": "t2.micro", "env": "dev"}),
("TF_VAR_env", {"region": "eu-west-1"}),
("terraform.tfvars", {"size": "t3.small"}),
("prod.tfvars", {"env": "prod", "size": "t3.large"}),
("-var CLI", {"size": "t3.xlarge"}),
]
final, source = {}, {}
for name, layer in layers:
for k, v in layer.items():
final[k] = v
source[k] = name # кто задал последним
for k in final:
print(f" {k:8} = {final[k]:12} (из {source[k]})")
«Попробуй сам ▶» — size прошёл через четыре слоя и победил CLI (t3.xlarge); env взялся из prod.tfvars. Так Terraform разрешает конфликты.
Частые ошибки
- Секреты в
*.auto.tfvars. Этот файл подхватывается автоматически и часто случайно попадает в git. - Путаница с приоритетом. Значение из
-varперебивает файл — а инженер ждёт обратного. - Один
terraform.tfvarsна все окружения. Так легко применить dev-значения к prod. Держите отдельные файлы.
Best practices
- На окружение — свой файл:
terraform apply -var-file=prod.tfvars. Никаких «общих» значений. - Секреты — только через
TF_VAR_из менеджера секретов или CI, никогда в файлах git. - Добавьте
*.tfvarsв.gitignore, кроме явно безопасных примеров (example.tfvars).
Разбор глубже
Когда переменная объявлена без default и её значение не пришло ни из одного источника, поведение зависит от режима. В интерактивном запуске Terraform спросит значение в консоли, приостановив выполнение. В автоматическом режиме (CI с флагом -input=false) такой запрос превращается в ошибку — и это правильно: пайплайн не должен молча зависать в ожидании ввода. Поэтому в CI всегда передают -input=false, чтобы недостающая переменная честно роняла сборку, а не подвешивала её.
Полезная практика для команд — файл terraform.tfvars.example с безопасными примерами значений, который коммитится в git, тогда как реальные *.tfvars с секретами добавляют в .gitignore. Новый инженер копирует пример, подставляет свои значения локально — и не рискует случайно закоммитить чувствительные данные. Это тот же паттерн, что и .env.example в обычной разработке. А для окружений (dev/staging/prod) держат отдельные файлы переменных и применяют их явным флагом -var-file, что делает невозможной случайную подстановку dev-значений в прод.
Отдельно стоит держать в голове порядок диагностики, когда переменная «взяла не то значение». Сначала проверьте -var и -var-file в команде запуска — они сильнее всего. Затем загляните в автоматически подхватываемые *.auto.tfvars, про которые легко забыть. Потом — в переменные окружения TF_VAR_, особенно если запуск идёт в CI, где они задаются незаметно. И только в конце смотрите на default. Этот чеклист «сверху вниз по приоритету» экономит массу времени, потому что в девяти случаях из десяти неожиданное значение приходит из самого сильного, а не самого очевидного источника.
Итог: значения приходят из CLI, файлов и окружения с чётким приоритетом — побеждает самый явный источник. На окружение — свой tfvars, секреты — через окружение. Дальше — как вернуть данные наружу через outputs.