Пять типов source
| Тип | Пример | Когда |
|---|---|---|
| Local | ./modules/s3-bucket | Модуль живёт в этом же репо |
| Terraform Registry | terraform-aws-modules/vpc/aws | Публичный module, версионирование semver |
| Git | git::https://github.com/org/repo.git//modules/x?ref=v1.2.3 | Приватный модуль в git |
| HTTP archive | https://example.com/modules/x-v1.zip//x | CDN, артефакт-сторадж |
| S3 | s3::https://s3.amazonaws.com/bucket/x.zip | Внутренний S3 как реестр |
Type определяется по форме строки, не по отдельному полю. Terraform сам угадывает.
Local
module "logs" {source = "./modules/s3-bucket"
name = "..."
}
- Путь относительно
.tfфайла, в котором написанmoduleблок. terraform initсоздаст symlink в.terraform/modules/logs/.- Любые правки HCL модуля видны сразу, это просто файлы в репо.
- Нет версионирования. Это часть твоего репо, версия = текущий HEAD git.
Используй для модулей которые живут вместе с root'ом. Не пытайся через local-path ссылаться на «соседний» проект, будет ад с относительными путями.
Terraform Registry
module "vpc" {source = "terraform-aws-modules/vpc/aws"
version = "5.7.0"
name = "main"
cidr = "10.0.0.0/16"
# ...
}
Формат: <namespace>/<name>/<provider>. Три сегмента, без https://.
- Реестр, registry.terraform.io (публичный) или приватный (HCP Terraform, Spacelift, и т.п.).
version, semver constraint:"5.7.0","~> 5.7",">= 5.0, < 6.0". См. tf-module-versioning.- Не указал version → берётся максимум. В CI это бомба замедленного действия: завтра выйдет 6.0 с breaking changes, и сборка ломается без единого коммита. Всегда фиксируй version.
Публичные модули AWS (terraform-aws-modules/vpc/aws,
.../eks/aws, .../alb/aws): это де-факто стандарт. Они огромные,
параметризованы под все edge-case'ы. Подходят, когда твои требования
ничем не отличаются от стандарта. Если отличаются, модуль легче
написать свой, чем разбираться какой из 40 input'ов нужно нажать.
Git
# SSH
module "billing" {source = "git::ssh://git@github.com/myorg/terraform-modules.git//billing?ref=v1.2.3"
}
# HTTPS
module "billing" {source = "git::https://github.com/myorg/terraform-modules.git//billing?ref=v1.2.3"
}
Формат: git::<git-url>//<подпуть>?ref=<branch_tag_or_sha>.
//перед подпутём, это разделитель Terraform, не часть git-URL.ref, branch, tag или commit-SHA. Для воспроизводимости, только tag или SHA, не branch. Иначе сегодняinitскачает один commit, завтра , другой.- Аутентификация, стандартная git: SSH-ключ, HTTPS basic, токен через
GIT_TERMINAL_PROMPT/ credential helper. - В корпоративных репозиториях обычно делают один git-репо с
подкаталогами для модулей. Это удобно для версионирования: один tag
v1.2.3фиксирует всё.
HTTP archive
module "x" {source = "https://example.com/modules/x-v1.0.tar.gz//x"
}
Terraform скачивает архив, распаковывает, заходит в подпуть //x. Поддерживаются:
.zip, .tar.gz, .tar.bz2, .tar.xz.
Полезно когда модули публикуются в CDN или артефакт-сторадж (Artifactory, Nexus). Версионирование, через имя файла или header.
S3
module "x" {source = "s3::https://s3-eu-west-1.amazonaws.com/my-bucket/modules/x-v1.zip"
}
Префикс s3:: подсказывает terraform использовать AWS-credentials для
доступа (из той же credentials chain, что AWS-провайдер).
Это компромисс между «свой git» и «свой Registry»: дёшево, частный, не требует дополнительного сервиса. Минус, нет встроенного семвера, версионирование руками через имена файлов.
Кэширование и init
При terraform init Terraform скачивает все модули в .terraform/modules/:
.terraform/modules/
├── modules.json # mapping: имя в HCL → путь
├── vpc/ # скачанный код vpc-модуля
└── billing/ # скачанный код billing-модуля
Эта папка, кэш. Меняешь HCL модуля (для local): видно сразу. Меняешь
source = "git::...?ref=v2.0.0". Нужно terraform init -upgrade,
иначе используется старая закэшированная копия.
Подводные камни
-
Source интерполировать нельзя. Никаких
source = "git::...?ref=${var.v}". Source разрешается на этапе init, до переменных. Версия модуля, статическое значение. Если нужно «динамически переключать версии», держи их в separate root-модулях или используй Terragrunt. -
Branch вместо tag, мина.
?ref=mainозначает «текущий main». Завтра кто-то смержит в main breaking change → твойterraform initскачает его, plan покажет destroy+create. Всегда tag или SHA. -
Registry-модули могут тянуть Registry-модули. Большие AWS-модули внутри используют десятки subdependencies. Один
module "vpc"→.terraform/modules/пухнет на 30+ модулей. Это норма, не баг. -
source = "./modules/x"после миграции репо ломается. Перенёс модули в подпапку, relative path сломан. Лечится bulk-grep'ом по repo, но больно. Чем глубже структура, тем чаще будет. -
Не используй HTTP без HTTPS.
source = "http://..."отключает проверку TLS. Это путь для атаки «подменили модуль на машине билда». -
Авторизация для приватных git, через credential helper, не в URL. Не пиши
git::https://user:token@github.com/..., токен попадёт в лог и.terraform/modules/modules.json. Используйgit config --global credential.helper storeлокально и secrets-механизм в CI.