Несколько провайдеров и аккаунтов: configuration_aliases

Рейтинг: 66.7% · 13 голосов
Подробный курс по Terraform и OpenTofu на примерах Yandex Cloud: ресурсы и провайдеры, состояние и бэкенды, модули, циклы и условия HCL, секреты и Lockbox, тестирование, CI/CD и командная работа. С актуализацией на 2026 (Terraform 1.3-1.10, OpenTofu).
Ответить
Аватара пользователя
Vlad_DevOps
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Несколько провайдеров и аккаунтов: configuration_aliases

Сообщение Vlad_DevOps »

Оглавление курса (47)
  1. Что такое инфраструктура как код и зачем она нужна
  2. Категории инструментов IaC: чем отличаются Ansible, Packer, Kubernetes и Terraform
  3. Чем Terraform отличается от Ansible, Pulumi и CloudFormation
  4. Как работает Terraform под капотом и кто такой OpenTofu
  5. Установка Terraform и OpenTofu, подготовка Yandex Cloud
  6. Первый ресурс: разворачиваем виртуальную машину в Yandex Cloud
  7. Веб-сервер на ВМ: метаданные, user-data и группы безопасности
  8. Переменные ввода и выходные значения в Terraform
  9. Кластер ВМ: группа экземпляров Yandex Compute Instance Group
  10. Балансировщик нагрузки: Application Load Balancer в Yandex Cloud
  11. Состояние Terraform: что такое tfstate и чем опасен локальный файл
  12. Удалённое хранилище состояния: бэкенд на Yandex Object Storage
  13. Изоляция состояния: рабочие области против раскладки по папкам
  14. Источники данных и terraform_remote_state: связываем компоненты
  15. Модули Terraform: переиспользуем инфраструктуру
  16. Входные, локальные и выходные переменные модуля
  17. Версионирование модулей и подводные камни
  18. Циклы в Terraform: параметр count
  19. Циклы в Terraform: for_each по множествам и картам
  20. Выражения for и строковые директивы
  21. Условная логика: count-трюк, for_each и директива if
  22. Встроенные функции, типы и выражения HCL
  23. Развёртывание без простоя: create_before_destroy
  24. Подводные камни Terraform и рефакторинг с блоком moved
  25. Управление секретами: основы и типы
  26. Инструменты управления секретами: Yandex Lockbox, Vault, SOPS
  27. Аутентификация провайдера и секреты: сервисные аккаунты и OIDC
  28. Секреты в ресурсах и состоянии, ephemeral-значения
  29. Провайдеры Terraform: установка, версии, required_providers
  30. Несколько копий одного провайдера: alias и мультизона
  31. Несколько провайдеров и аккаунтов: configuration_aliases (вы здесь)
  32. Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud
  33. Код Terraform промышленного уровня: почему это долго
  34. Мелкие компонуемые модули вместо монолита
  35. Тестируемые модули и проверки: validation, precondition, postcondition
  36. Версионирование, публикация модулей и Terragrunt
  37. Ручное тестирование Terraform и очистка ресурсов
  38. Автоматические тесты на Terratest: модульные тесты
  39. Интеграционные и сквозные тесты, пирамида тестирования
  40. Нативный terraform test и статический анализ
  41. Внедрение Terraform в команде: процессы и культура
  42. Конвейер развёртывания прикладного кода
  43. Конвейер инфраструктурного кода и золотое правило Terraform
  44. Стиль, ревью и CI/CD-инструменты: Atlantis, TACOS, policy as code
  45. Что нового в Terraform 1.3-1.10: моды, импорт, провайдер-функции, Stacks
  46. OpenTofu в 2026: чем живёт форк и как мигрировать
  47. Сертификация HashiCorp Terraform Associate и карьера
Представь: тебе нужно развернуть одинаковую инфраструктуру в двух зонах доступности Yandex Cloud, чтобы база пережила падение одного дата-центра. Или ты обслуживаешь два разных каталога - прод и стейджинг - живущих в соседних облаках с разными сервисными аккаунтами. А может, у тебя вообще два клиента, и каждый платит за свой folder. Во всех этих случаях один блок provider "yandex" уже не вытягивает: тебе нужны ДВЕ (или больше) копии одного и того же провайдера, настроенные по-разному. И самое интересное начинается, когда эти копии надо протащить внутрь модуля.

Вот ровно про это и урок. Разберём, как Terraform работает с несколькими экземплярами провайдера, что такое алиасы, зачем модулю нужен configuration_aliases и почему наивный подход "просто скопирую провайдер внутрь модуля" приведёт тебя в ад при первом же terraform destroy. Это глава из серии про инфраструктуру как код, и тема скорее продвинутая, но без неё мульти-региональные и мульти-аккаунтные сетапы не собрать.

Алиасы провайдера: две копии одного и того же

Базовая механика простая. Один и тот же провайдер можно объявить несколько раз, и чтобы Terraform их различал, второму и последующим экземплярам дают alias. Первый блок без алиаса считается провайдером по умолчанию (default), его получают все ресурсы, которые явно не попросили другой.

Код: Выделить всё

provider "yandex" {
  # default-конфигурация, зона A
  zone      = "ru-central1-a"
  folder_id = var.folder_id
}

provider "yandex" {
  alias     = "zone_b"
  zone      = "ru-central1-b"
  folder_id = var.folder_id
}
Теперь у тебя есть два провайдера: yandex (default) и yandex.zone_b. Ресурс выбирает нужный через мета-аргумент provider:

Код: Выделить всё

resource "yandex_compute_disk" "data_a" {
  # без provider - значит default, зона A
  name = "data-a"
  zone = "ru-central1-a"
  size = 20
}

resource "yandex_compute_disk" "data_b" {
  provider = yandex.zone_b
  name     = "data-b"
  zone     = "ru-central1-b"
  size     = 20
}
Обрати внимание: provider = yandex.zone_b пишется БЕЗ кавычек, это ссылка, а не строка. Частая ошибка новичков - засунуть его в кавычки и потом долго не понимать, почему Terraform ругается.

Алиасы для аккаунтов и облаков работают точно так же, меняются только аргументы. Из доки провайдера Yandex Cloud видно, что у второй копии можно задать совсем другой сервисный аккаунт и каталог:

Код: Выделить всё

provider "yandex" {
  alias                    = "client_two"
  service_account_key_file = "key-client-two.json"
  cloud_id                 = var.cloud_id_two
  folder_id                = var.folder_id_two
  zone                     = "ru-central1-d"
}
Так один terraform apply раскатывает ресурсы в двух разных каталогах, под двумя разными ключами. Удобно для агентств и мультитенантных проектов.

Изображение

configuration_aliases: как протащить алиас в модуль

Внутри корневого конфига всё просто. Боль начинается с модулями. По умолчанию модуль наследует только default-провайдеров родителя. Если модуль хочет работать с ДВУМЯ копиями yandex одновременно, он должен явно заявить: "мне нужны две конфигурации этого провайдера". Делается это через configuration_aliases в блоке required_providers (фича стабильна начиная с Terraform 0.15, в 2026 это давно норма и в Terraform, и в OpenTofu).

Вот объявление внутри модуля, файл modules/two-zones/versions.tf:

Код: Выделить всё

terraform {
  required_providers {
    yandex = {
      source                = "yandex-cloud/yandex"
      version               = ">= 0.100"
      configuration_aliases = [yandex.primary, yandex.secondary]
    }
  }
}
Этой строкой модуль говорит: "я не буду сам настраивать провайдер, но жду, что мне передадут две его конфигурации под именами yandex.primary и yandex.secondary". Сам модуль их НЕ конфигурирует - никаких token, folder_id внутри. Он только потребляет.

Внутри модуля ресурсы ссылаются на эти алиасы как на локальные имена:

Код: Выделить всё

resource "yandex_vpc_network" "net" {
  provider = yandex.primary
  name     = "${var.prefix}-net"
}

resource "yandex_vpc_subnet" "primary" {
  provider       = yandex.primary
  name           = "${var.prefix}-subnet-primary"
  zone           = var.zone_primary
  network_id     = yandex_vpc_network.net.id
  v4_cidr_blocks = ["10.10.1.0/24"]
}

resource "yandex_vpc_subnet" "secondary" {
  provider       = yandex.secondary
  name           = "${var.prefix}-subnet-secondary"
  zone           = var.zone_secondary
  network_id     = yandex_vpc_network.net.id
  v4_cidr_blocks = ["10.10.2.0/24"]
}
А теперь самое главное - проброс. При вызове модуля родитель ОБЯЗАН передать блок providers, который связывает локальные имена модуля (слева) с реальными провайдерами родителя (справа):

Код: Выделить всё

module "two_zones" {
  source = "./modules/two-zones"

  prefix          = "app"
  zone_primary    = "ru-central1-a"
  zone_secondary  = "ru-central1-b"

  providers = {
    yandex.primary   = yandex
    yandex.secondary = yandex.zone_b
  }
}
Читается так: "то, что модуль внутри зовёт yandex.primary, на самом деле мой default yandex; а yandex.secondary - это мой yandex.zone_b". Слева - имена из configuration_aliases модуля, справа - реальные провайдеры из корня. Перепутаешь стороны - получишь ошибку про несуществующий провайдер.

Полный рабочий пример: ВМ в двух зонах

Соберём всё вместе. Модуль разворачивает по виртуалке в каждой зоне поверх общей сети. Файл modules/two-zones/main.tf (versions.tf с configuration_aliases у нас уже выше):

Код: Выделить всё

data "yandex_compute_image" "ubuntu" {
  provider = yandex.primary
  family   = "ubuntu-2404-lts"
}

resource "yandex_compute_instance" "primary" {
  provider    = yandex.primary
  name        = "${var.prefix}-vm-a"
  platform_id = "standard-v3"
  zone        = var.zone_primary

  resources {
    cores  = 2
    memory = 2
  }

  boot_disk {
    initialize_params {
      image_id = data.yandex_compute_image.ubuntu.id
      size     = 20
    }
  }

  network_interface {
    subnet_id = yandex_vpc_subnet.primary.id
    nat       = true
  }
}

resource "yandex_compute_instance" "secondary" {
  provider    = yandex.secondary
  name        = "${var.prefix}-vm-b"
  platform_id = "standard-v3"
  zone        = var.zone_secondary

  resources {
    cores  = 2
    memory = 2
  }

  boot_disk {
    initialize_params {
      image_id = data.yandex_compute_image.ubuntu.id
      size     = 20
    }
  }

  network_interface {
    subnet_id = yandex_vpc_subnet.secondary.id
    nat       = true
  }
}
Один terraform plan, один terraform apply - и две машины поднимаются в разных зонах доступности, в одной сети. Никакого дублирования кода модуля: логика описана один раз, а раскатывается дважды через два алиаса.

Типичные грабли
  • Кавычки вокруг алиаса. provider = "yandex.zone_b" - неправильно. Это ссылка, кавычек быть не должно.
  • Конфигурация провайдера внутри переиспользуемого модуля. Технически можно положить блок provider {} в модуль, но Terraform будет тебя ругать предупреждениями, а главное - такой модуль нельзя нормально удалить через terraform destroy, если провайдер настроен через выражения, которые при удалении уже недоступны. Правило: модули конфигурируют ресурсы, а провайдеры настраивает корень.
  • Забыл блок providers при вызове. Если модуль объявил configuration_aliases, но ты не передал providers = { ... }, Terraform упадёт ещё на init с жалобой на необъявленный провайдер. Алиасы (не default) НЕ наследуются автоматически.
  • Перепутал стороны в providers. Слева - имя внутри модуля, справа - провайдер родителя. yandex.secondary = yandex.zone_b, а не наоборот.
  • Один общий стейт там, где нужны разные. Главная стратегическая ошибка. Несколько провайдеров - это всё ещё ОДИН terraform state. Об этом ниже.
Когда мульти-провайдер оправдан, а когда нет

Несколько копий провайдера в одном конфиге - мощно, но не бесплатно. Всё это живёт в едином terraform state и катится одним apply. Это плюс, когда ресурсы действительно связаны: сеть в зоне A и сеть в зоне B, между которыми ходит трафик; реплики одной базы; балансировщик и его бэкенды в разных зонах. Тут атомарность и общий граф зависимостей - именно то, что нужно.

Но если ты пихаешь в один стейт прод и дев только потому, что "так меньше папок", - ты роешь себе яму. Любая ошибка в дев-части блокирует apply прода. Радиус поражения растёт, а terraform plan становится простынёй на сто ресурсов. Для слабо связанных окружений правильнее РАЗДЕЛЬНЫЕ стейты (разные backend-ключи или воркспейсы) и, по возможности, отдельные прогоны. Грубое правило: один state - один радиус отказа. Если падение одной части не должно ронять другую, разноси по стейтам, а не по алиасам.

Мини-лаба
  • Объяви в корне два провайдера yandex: default в зоне ru-central1-a и алиас zone_b в ru-central1-b.
  • Создай в корне два yandex_compute_disk - один в default, другой через provider = yandex.zone_b. Сделай terraform plan и убедись, что диски уезжают в разные зоны.
  • Вынеси логику в модуль с configuration_aliases = [yandex.primary, yandex.secondary]. Пробрось providers при вызове.
  • Запусти terraform validate, затем plan. Намеренно убери блок providers и посмотри текст ошибки - запомни его, ты его ещё встретишь.
Контрольные вопросы
  • Чем default-провайдер отличается от провайдера с alias и какой из них наследуется модулем автоматически?
  • Зачем модулю нужен configuration_aliases, если внутри он всё равно не настраивает провайдер?
  • Как в блоке providers = { ... } соотносятся левая и правая части? Что есть что?
  • По какому признаку решать: тащить два окружения в один стейт через алиасы или разнести по отдельным стейтам?
Что запомнить

Один провайдер можно объявить много раз через alias, а ресурс выбирает копию мета-аргументом provider (без кавычек). Чтобы модуль работал с несколькими копиями, он декларирует их через configuration_aliases в required_providers, сам провайдеры не настраивает, а получает их извне через providers = { ... } при вызове. Слева в этом блоке - имена модуля, справа - реальные провайдеры корня. И помни: несколько алиасов - это по-прежнему один terraform state, поэтому слабо связанные окружения лучше разносить по разным стейтам, а не сваливать в кучу ради экономии папок. Всё то же самое работает и в OpenTofu - синтаксис идентичен.
👍7 ❤️3 🔥 😄 🤔2
Аватара пользователя
ruppi1
Сообщения: 1
Зарегистрирован: 22 май 2026, 05:34

Re: Несколько провайдеров и аккаунтов: configuration_aliases

Сообщение ruppi1 »

Спасибо, наконец дошло зачем нужен блок providers при вызове модуля. Раньше тупо копировал его из примеров и не понимал что слева а что справа, а оказывается слева имя из самого модуля.
👍1 ❤️2 🔥 😄 🤔
Аватара пользователя
luiscito
Сообщения: 1
Зарегистрирован: 08 июн 2026, 16:25

Re: Несколько провайдеров и аккаунтов: configuration_aliases

Сообщение luiscito »

А если мне реально нужны прод и дев отдельно, но хочется один раз написать конфиг - получается лучше один модуль и два раза его вызвать с разными backend, а не пихать оба в один стейт через алиасы? Правильно понял?
👍1 ❤️3 🔥 😄 🤔
Ответить
← Предыдущая глава
Несколько копий одного провайдера: alias и мультизона
Следующая глава →
Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud

Все главы курса «Terraform: инфраструктура как код на Yandex Cloud»

Поделиться темой: ✈ Telegram VK

Вернуться в «Terraform: инфраструктура как код на Yandex Cloud»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость