Дизайн Terraform-модуля
Проектирование переиспользуемого модуля: что выносить, как описать inputs/outputs, версионирование и тесты на terratest.
Действуй как Staff Platform Engineer. Спроектируй переиспользуемый Terraform-модуль для: {{resource_scope}}. Ожидаемые потребители: {{consumers}}.
Что сделать
-
Определи границы модуля. Принцип: модуль — это законченная абстракция на уровне доменной задачи, а не обёртка вокруг одного ресурса.
- Если в модуле меньше 3 ресурсов и нет связной логики — это слишком тонко, оставь голый ресурс.
- Если модуль управляет несколькими независимыми системами — раздели на 2-3 узких модуля.
-
Спроектируй inputs. Каждой переменной —
description,type, валидация (validation { ... }). Группируй: required (без default), optional с разумным default, advanced (escape hatches). Не делай map/object для всего подряд — плоские переменные читаются лучше. -
Спроектируй outputs. Выводи всё, что может понадобиться вышестоящему коду: id, ARN, endpoint, security group. Outputs — это публичный API, breaking change в нём = мажорная версия.
-
Версионирование. Используй SemVer с тегами в Git.
v1.x— стабильный API,v0.x— экспериментальный (breaking возможны). Потребители пинятся черезsource = "git::...?ref=v1.4.2"илиversion = "~> 1.4"для registry. -
Тестирование. Минимум:
terraform validate+tflintв CI. Для серьёзных модулей — terratest с реальным apply в эфемерный аккаунт + destroy. Покрывай: дефолтный сценарий, edge-кейсы переменных, deprecation паттернов. -
Документация. README с обязательными секциями: Usage (минимальный пример), Requirements, Providers, Inputs, Outputs (генерируй terraform-docs). Один пример в
examples/каждой типовой конфигурации.
Anti-patterns
- ❌ Гигантский модуль "вся инфра одной командой" — невозможно тестировать, страшно менять.
- ❌ Leaky abstraction: модуль принимает 40 переменных, чтобы прокинуть любое поле в любой ресурс. Это не модуль, это обёртка.
- ❌
count = var.enabled ? 1 : 0на верхнем уровне — пользователь должен иметь возможность не вызывать модуль вообще, а не передавать флаг. - ❌ Hardcoded имена ресурсов без
name_prefix/тегов — конфликты при двух инстансах в одном аккаунте. - ❌ Использование
local-execдля логики, которую можно выразить декларативно.
Формат вывода
## Module: <name>
### Boundary justification
<почему именно этот scope, а не шире/уже>
### Inputs (table)
| name | type | required | description | validation |
### Outputs (table)
| name | description |
### Versioning strategy
<initial version, breaking change policy>
### Test plan
- Unit: ...
- Integration (terratest): ...
### Example usage
<минимальный + один продвинутый>
Принцип: хороший модуль исчезает из внимания после первого использования. Если потребители постоянно лезут внутрь — модуль спроектирован плохо.
Паттерн деплоя в Kubernetes
Выбор workload-типа, стратегии выката, probes, лимитов, anti-affinity и автомасштабирования под конкретный сервис.
Стратегия multi-region
Active-active vs active-passive, репликация данных, маршрутизация, автоматизация failover и предотвращение split-brain.
Аудит и оптимизация облачных затрат
Структурный разбор счёта: топ-spender'ы, idle-ресурсы, reserved/spot, оптимизация трафика и встраивание FinOps в процесс.