Skip to content

Сабмодули

TerraCi поддерживает вложенные сабмодули для организации связанной инфраструктуры внутри родительского модуля.

Что такое сабмодули?

Сабмодули — это Terraform-модули, вложенные глубже уровня стандартного паттерна:

infrastructure/
└── platform/
    └── production/
        └── us-east-1/
            └── ec2/                    # Родительский модуль (глубина 4)
                ├── main.tf             # Файлы родительского модуля
                ├── rabbitmq/           # Сабмодуль (глубина 5)
                │   └── main.tf
                └── redis/              # Сабмодуль (глубина 5)
                    └── main.tf

Идентификация модулей

ПутьТипID
platform/production/us-east-1/ec2Родительplatform/production/us-east-1/ec2
platform/production/us-east-1/ec2/rabbitmqСабмодульplatform/production/us-east-1/ec2/rabbitmq

Конфигурация

Сабмодули обнаруживаются автоматически. Любая директория с .tf файлами, вложенная глубже уровня паттерна, считается сабмодулем:

yaml
structure:
  pattern: "{service}/{environment}/{region}/{module}"

Примеры использования

Группировка EC2 инстансов

ec2/
├── main.tf           # Общие security groups, IAM roles
├── rabbitmq/
│   └── main.tf       # EC2 для RabbitMQ
└── elasticsearch/
    └── main.tf       # EC2 для Elasticsearch

Кластеры баз данных

databases/
├── main.tf           # Общие VPC, подсети
├── postgresql/
│   └── main.tf       # PostgreSQL RDS
├── redis/
│   └── main.tf       # ElastiCache Redis
└── mongodb/
    └── main.tf       # DocumentDB

Микросервисы

Группировка микросервисов по доменам:

services/
├── auth/
│   └── main.tf
├── payments/
│   └── main.tf
└── notifications/
    └── main.tf

Зависимости сабмодулей

Сабмодули могут зависеть от:

  • Родительского модуля
  • Других сабмодулей того же родителя
  • Модулей вне родителя

Зависимость от родителя

hcl
# В ec2/rabbitmq/main.tf
data "terraform_remote_state" "ec2_parent" {
  backend = "s3"
  config = {
    key = "platform/production/us-east-1/ec2/terraform.tfstate"
  }
}

Зависимости между сабмодулями

hcl
# В ec2/app/main.tf
data "terraform_remote_state" "rabbitmq" {
  backend = "s3"
  config = {
    key = "platform/production/us-east-1/ec2/rabbitmq/terraform.tfstate"
  }
}

Сопоставление имён

TerraCi использует умное сопоставление имён для сабмодулей:

Имя remote stateСоответствует
ec2_rabbitmqec2/rabbitmq
ec2-rabbitmqec2/rabbitmq
rabbitmqec2/rabbitmq (в том же контексте)

Сгенерированный пайплайн

Сабмодули отображаются как обычные джобы:

yaml
plan-platform-prod-us-east-1-ec2:
  stage: deploy-plan-0
  # ...

plan-platform-prod-us-east-1-ec2-rabbitmq:
  stage: deploy-plan-1
  needs:
    - apply-platform-prod-us-east-1-ec2
  # ...

Индекс родительских модулей

TerraCi поддерживает индекс связей родитель-потомок:

go
type Module struct {
    components map[string]string // именованные сегменты из паттерна
    segments   []string          // упорядоченные имена сегментов

    Path         string
    RelativePath string
    Parent       *Module   // Ссылка на родителя (для сабмодулей)
    Children     []*Module // Ссылки на потомков (для родителей)
}

Это позволяет:

  • Запрашивать все сабмодули родителя
  • Находить родителя сабмодуля (через m.Parent)
  • Проверять, является ли модуль сабмодулем (через m.IsSubmodule())
  • Строить точные цепочки зависимостей

Лучшие практики

1. Группируйте связанные ресурсы

Объединяйте ресурсы, которые деплоятся вместе:

app/
├── main.tf           # ECS-кластер, балансировщик нагрузки
├── api/
│   └── main.tf       # API-сервис
└── worker/
    └── main.tf       # Фоновый воркер

2. Выносите общую конфигурацию в родитель

Размещайте общие ресурсы в родительском модуле:

hcl
# В ec2/main.tf
resource "aws_security_group" "shared" {
  name = "ec2-shared-sg"
}

output "shared_security_group_id" {
  value = aws_security_group.shared.id
}
hcl
# В ec2/rabbitmq/main.tf
data "terraform_remote_state" "parent" {
  # ...
}

resource "aws_instance" "rabbitmq" {
  vpc_security_group_ids = [
    data.terraform_remote_state.parent.outputs.shared_security_group_id
  ]
}

3. Единообразное именование

Используйте единообразные имена для сабмодулей:

✓ ec2/rabbitmq
✓ ec2/redis
✓ ec2/elasticsearch

✗ ec2/rabbit-mq
✗ ec2/Redis
✗ ec2/es

4. Ограничивайте глубину вложенности

Хотя TerraCi поддерживает неограниченную вложенность сабмодулей, глубокие иерархии сложны в управлении. Рекомендуется реструктуризация при слишком глубокой вложенности:

# Вместо глубокой вложенности:
platform/prod/us-east-1/services/backend/api/v2/main.tf

# Используйте плоскую структуру:
platform/prod/us-east-1/backend-api/main.tf

Фильтрация сабмодулей

bash
# Только сабмодули
terraci generate --include "*/*//*/*/**"

# Исключить конкретный сабмодуль
terraci generate --exclude "*/*/us-east-1/ec2/rabbitmq"

# Только родительские модули
terraci generate --exclude "*/*/*/*/*"

Устранение неполадок

Сабмодули не обнаруживаются

  1. Убедитесь, что директория сабмодуля содержит .tf файлы
  2. Убедитесь, что сабмодуль вложен глубже уровня паттерна

Родитель не привязан

Если родитель сабмодуля не определяется:

  1. Убедитесь, что родитель существует на глубине паттерна
  2. Проверьте, что родитель содержит .tf файлы
  3. Запустите terraci validate -v для просмотра деталей обнаружения

Следующие шаги

Released under the MIT License.