Шесть источников значений
Terraform читает значения переменных из нескольких мест. От высокого приоритета к низкому:
-varв CLI,terraform plan -var="env=prod". Перебивает всё.-var-fileв CLI,terraform plan -var-file=prod.tfvars. Если несколько-var-file, последний выигрывает.*.auto.tfvarsи*.auto.tfvars.json, все файлы с этим суффиксом в корне проекта, читаются автоматически. В алфавитном порядке, последний по алфавиту выигрывает при коллизии.terraform.tfvarsиterraform.tfvars.json, фиксированное имя, читается автоматически.- Env-переменные
TF_VAR_*,export TF_VAR_env=prodзатемterraform plan. defaultв блоке variable. Это самый низкий приоритет, fallback.
Если ничего из вышеперечисленного не задано и нет default. Terraform спросит интерактивно в терминале.
Пример приоритета
Допустим, переменная объявлена так:
variable "env" {type = string
default = "dev"
}
Что увидит Terraform в разных ситуациях:
| Источники | Значение var.env |
|---|---|
| Ничего | "dev" (из default) |
export TF_VAR_env=staging | "staging" |
TF_VAR_env=staging + terraform.tfvars содержит env = "prod" | "prod" (.tfvars перебил env) |
Всё вышеперечисленное + -var-file=temp.tfvars где env = "qa" | "qa" |
Всё + -var="env=hotfix" | "hotfix" |
Правило простое: что ближе к CLI, то выиграет.
Когда что использовать
default, для значений, которые редко меняются и подходят 90% случаев. Регион AWS, instance type small.terraform.tfvars, основные значения для проекта. Часто добавляют в.gitignore, потому что там бывают токены и секреты.*.auto.tfvars, конфигурация по окружениям если без-var-file. Например,dev.auto.tfvarsзагрузится автоматически в dev-папке.-var-file, для CI/CD: один HCL, разные tfvars для dev/staging/prod. Файл подбирается переменной окружения или флагом.-var, для разовых override'ов. «Запусти plan один раз с другим значением, не меняя файлы».TF_VAR_*, для CI: секреты, которые нельзя в git. CI-система кладёт их в env.
TF_VAR_*, особенности
Префикс TF_VAR_ + имя переменной:
export TF_VAR_env=prod
export TF_VAR_db_password="$(vault read -field=password kv/prod/db)"
terraform plan
Если переменная типа string или number или bool, значение env идёт как есть. Если переменная типа list или map, env-значение должно быть JSON:
export TF_VAR_tags='{"env": "prod", "team": "platform"}'export TF_VAR_azs='["us-east-1a", "us-east-1b"]'
Регистр имени важен: TF_VAR_my_var ≠ TF_VAR_MY_VAR.
auto.tfvars vs .tfvars, нюанс
Файл terraform.tfvars. Это единственное фиксированное имя.
Файлы *.auto.tfvars, любое имя с этим суффиксом.
Зачем разделение?
terraform.tfvars. Это основной набор; часто в .gitignore.dev.auto.tfvars,staging.auto.tfvars,prod.auto.tfvars, окружения; обычно коммитятся. Подгружаются все сразу, но в одной workspace должна быть только нужная.
Альтернативный подход, держать файлы окружений в отдельных папках, без auto-суффикса, передавать через -var-file=envs/prod.tfvars. Это проще для CI.
Подводные камни
-
*.auto.tfvarsподгружаются ВСЕ. Если у вас в корнеdev.auto.tfvarsиprod.auto.tfvarsодновременно, оба читаются, последний по алфавиту перебивает. Это часто не то, что хочет автор. -
terraform.tfvars в git, частая утечка секретов. Если кладёте туда токены, обязательно
.gitignore. Не полагайтесь на «никто не посмотрит». -
Не передавайте секреты через
-var. Это попадёт в shell history. ИспользуйтеTF_VAR_*черезread -sили вытащите через secrets-manager. -
JSON для сложных типов в env. Если объявили
type = list(string)и попробовалиTF_VAR_x=us-east-1. Terraform не парсит это как list, упадёт. НужноTF_VAR_x='["us-east-1"]'. -
Интерактивный ввод, не для CI. Если в CI забыли передать переменную, Terraform зависнет на вопросе и пайплайн встанет навсегда. Лечится
-input=false(упадёт с понятной ошибкой вместо ожидания).