Несколько копий одного провайдера: alias и мультизона

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

Несколько копий одного провайдера: alias и мультизона

Сообщение 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 и карьера
До этого момента у нас был один блок provider "yandex" и один набор настроек: один каталог, одно облако, одна зона по умолчанию. Это удобно ровно до того дня, когда тебе понадобится развернуть ресурсы сразу в нескольких зонах доступности, или раскидать инфраструктуру по двум каталогам (например prod и staging в одном конфиге), или вообще ходить в два разных облака из одного terraform apply. И тут новички упираются в стену: а как объявить provider yandex дважды? Если просто написать два блока с одинаковым именем - Terraform ругнётся на дубликат.

Решение называется alias-провайдеры. Это штатный механизм Terraform (и OpenTofu тоже, тут они идентичны), который позволяет держать несколько именованных конфигураций одного и того же провайдера и явно указывать ресурсу, через какую из них работать. Именно на этом строится мультизонное отказоустойчивое развёртывание в Yandex Cloud, и именно это мы сейчас разберём по косточкам.

Зачем вообще несколько копий провайдера

Инфраструктура как код (iac) хороша тем, что вся топология лежит в одном месте. Но реальная топология редко влезает в одну зону и один каталог. Типичные сценарии, где одного провайдера мало:
  • Мультизона. ru-central1-a, ru-central1-b, ru-central1-d - три физически разнесённые зоны доступности. Чтобы кластер пережил падение одной зоны, виртуалки и диски надо разложить по разным зонам. Зона задаётся в провайдере (атрибут zone) или в самом ресурсе, и иногда удобнее иметь по провайдеру на зону.
  • Несколько каталогов (folder_id). Сетевую инфраструктуру держишь в одном folder, приложения - в другом. Один terraform, два каталога.
  • Несколько облаков (cloud_id) или аккаунтов. Прод и тестовый контур в разных облаках, разные сервисные аккаунты - но описаны одним кодом.
Во всех этих случаях параметры подключения (folder_id, cloud_id, zone, token либо service_account_key_file) разные, а провайдер один и тот же - yandex. Вот для этого и придумали alias.

Изображение

Как объявить и передать alias-провайдер

Базовый блок остаётся как был - это провайдер по умолчанию. А дополнительные конфигурации получают атрибут alias:

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

# Провайдер по умолчанию - без alias
provider "yandex" {
  zone      = "ru-central1-a"
  folder_id = var.folder_id
}

# Копия для зоны B
provider "yandex" {
  alias     = "zone_b"
  zone      = "ru-central1-b"
  folder_id = var.folder_id
}

# Копия для зоны D
provider "yandex" {
  alias     = "zone_d"
  zone      = "ru-central1-d"
  folder_id = var.folder_id
}
Имя провайдера по-прежнему yandex, отличаются они по alias. Обращаются к ним через запись yandex.<alias>, например yandex.zone_b.

Дальше самое важное: ресурс не знает про alias сам по себе. Ресурс всегда привязывается к провайдеру по умолчанию, если ты явно не сказал иное. Чтобы отправить ресурс в другую конфигурацию, добавляешь в него мета-аргумент provider:

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

resource "yandex_compute_instance" "web_a" {
  name = "web-a"
  zone = "ru-central1-a"

  resources {
    cores  = 2
    memory = 2
  }
  boot_disk {
    initialize_params {
      image_id = var.image_id
    }
  }
  network_interface {
    subnet_id = yandex_vpc_subnet.subnet_a.id
    nat       = true
  }
}

resource "yandex_compute_instance" "web_b" {
  provider = yandex.zone_b
  name     = "web-b"
  zone     = "ru-central1-b"

  resources {
    cores  = 2
    memory = 2
  }
  boot_disk {
    initialize_params {
      image_id = var.image_id
    }
  }
  network_interface {
    subnet_id = yandex_vpc_subnet.subnet_b.id
    nat       = true
  }
}
web_a уезжает в зону A через провайдер по умолчанию, web_b - в зону B через yandex.zone_b. Обрати внимание: provider = yandex.zone_b пишется без кавычек, это ссылка, а не строка.

Полноценный мультизонный пример

Соберём отказоустойчивую раскладку: своя подсеть в каждой зоне и по виртуалке в каждой. Сеть одна, а подсети привязаны к зонам.

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

resource "yandex_vpc_network" "net" {
  name = "app-net"
}

resource "yandex_vpc_subnet" "subnet_a" {
  name           = "subnet-a"
  zone           = "ru-central1-a"
  network_id     = yandex_vpc_network.net.id
  v4_cidr_blocks = ["10.10.1.0/24"]
}

resource "yandex_vpc_subnet" "subnet_b" {
  provider       = yandex.zone_b
  name           = "subnet-b"
  zone           = "ru-central1-b"
  network_id     = yandex_vpc_network.net.id
  v4_cidr_blocks = ["10.10.2.0/24"]
}

resource "yandex_vpc_subnet" "subnet_d" {
  provider       = yandex.zone_d
  name           = "subnet-d"
  zone           = "ru-central1-d"
  network_id     = yandex_vpc_network.net.id
  v4_cidr_blocks = ["10.10.3.0/24"]
}
Сама yandex_vpc_network - ресурс зонально-независимый, её создаёт провайдер по умолчанию. А подсети раскиданы по трём провайдерам и трём зонам. Теперь, когда сделаешь terraform plan apply, ты увидишь сетку из трёх зон, готовую под распределённое приложение.

На практике лучше не плодить руками ресурсы web_a, web_b, web_d, а использовать for_each по списку зон. Но for_each и meta-аргумент provider вместе не дружат напрямую: provider нельзя вычислить динамически из ключа итерации. Поэтому распространённый рабочий приём - один модуль на зону, в каждый прокидываешь нужный alias-провайдер. И тут мы подходим к главной грабле.

Грабли: alias-провайдер не наследуется в модуль неявно

Запомни как мантру: дочерний модуль не видит alias-провайдеры родителя автоматически. Провайдер по умолчанию (yandex без alias) пробрасывается в модули неявно - его можно не передавать. А вот yandex.zone_b сам в модуль не попадёт. Если ресурс внутри модуля напишет provider = yandex.zone_b, а ты этот alias не передал - Terraform либо возьмёт дефолтную конфигурацию, либо упадёт с ошибкой про неопределённый провайдер.

Передача делается явно, через блок providers в вызове модуля:

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

module "app_zone_b" {
  source = "./modules/app"

  providers = {
    yandex = yandex.zone_b
  }

  subnet_id = yandex_vpc_subnet.subnet_b.id
}
Здесь мы говорим: внутри модуля то, что называется просто yandex, физически будет конфигурацией yandex.zone_b. Внутри модуля код пишется как обычно, без alias - модуль про зону не знает, он переиспользуемый. А снаружи мы тремя вызовами с разными providers разложили его по трём зонам.

Ещё пара граблей, на которых легко споткнуться:
  • alias обязателен у всех дополнительных копий, но запрещён у основной. Один блок без alias - это и есть default.
  • Если в модуле объявлен required_providers с configuration_aliases, провайдер придётся передавать всегда, даже дефолтный. Это для модулей, которым нужно несколько копий внутри.
  • Удалять провайдер, через который созданы ресурсы, нельзя, пока живы эти ресурсы. Terraform должен иметь конфигурацию, чтобы их потом уничтожить. Сначала destroy ресурсов - потом убираешь alias-блок.
  • terraform state хранит привязку ресурса к провайдеру. Если переименуешь alias, придётся либо пересоздавать, либо аккуратно работать через state, иначе план покажет лишние изменения.
Мини-лаба

Руками, на своём аккаунте Yandex Cloud:
  • Объяви провайдер по умолчанию (zone ru-central1-a) и две копии с alias zone_b и zone_d на остальные зоны.
  • Создай одну yandex_vpc_network и три yandex_vpc_subnet - по подсети на зону, каждая через свой провайдер.
  • Прогони terraform plan apply и убедись, что подсети реально оказались в разных зонах (поле zone в выводе).
  • Вынеси создание подсети в модуль ./modules/subnet и вызови его трижды, прокидывая разные alias через блок providers. Сравни план - ресурсов должно быть столько же.
  • Бонус: попробуй убрать блок providers из одного вызова модуля и посмотри, что скажет Terraform.
Контрольные вопросы
  • Чем отличается объявление основного провайдера от alias-копии и можно ли задать alias основному?
  • Как заставить конкретный ресурс работать через провайдер yandex.zone_b?
  • Почему alias-провайдер не попадает в дочерний модуль сам по себе и как его туда передать?
  • Что произойдёт, если удалить alias-блок провайдера, через который ещё существуют ресурсы?
Итог

Один блок provider "yandex" - это конфигурация по умолчанию, и она тянется в модули неявно. Дополнительные конфигурации объявляются тем же провайдером с атрибутом alias и адресуются как yandex.<alias>. Ресурс цепляется к нужной копии через мета-аргумент provider, а в модуль alias надо отдавать руками через блок providers - это и есть та самая грабля, на которой все спотыкаются. Освоив alias, ты получаешь мультизонную отказоустойчивость в ru-central1-a/b/d, разведение по каталогам и облакам - и всё это в одном terraform yandex cloud конфиге. Модули terraform плюс alias - база любой серьёзной инфраструктуры как код.
👍4 ❤️3 🔥1 😄 🤔3
Аватара пользователя
ban400es
Сообщения: 1
Зарегистрирован: 11 май 2026, 16:09

Re: Несколько копий одного провайдера: alias и мультизона

Сообщение ban400es »

Блин, как раз вчера ловил ошибку про неопределённый провайдер в модуле, а оно вон что - alias руками прокидывать надо. Спасибо, теперь дошло.
👍 ❤️ 🔥 😄 🤔3
Аватара пользователя
proxmox3
Сообщения: 1
Зарегистрирован: 13 май 2026, 07:18

Re: Несколько копий одного провайдера: alias и мультизона

Сообщение proxmox3 »

А for_each по зонам прям совсем никак нельзя с провайдерами связать? Один модуль на зону копипастить как-то грустно выглядит.
👍3 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Провайдеры Terraform: установка, версии, required_providers
Следующая глава →
Несколько провайдеров и аккаунтов: configuration_aliases

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

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

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

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

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