Провайдеры во вложенных модулях
В конфигурации с несколькими модулями есть некоторые особенности, которые следует учитывать при связывании ресурсов с конфигурациями провайдеров.
Каждый ресурс в конфигурации должен быть связан с одной конфигурацией провайдера. В отличие от большинства других понятий OpenTofu, конфигурации провайдеров являются глобальными для всей конфигурации OpenTofu и могут использоваться совместно разными модулями. Конфигурации провайдеров можно определять только в корневом модуле.
Провайдеры можно передавать во вложенные модули двумя способами: неявно, посредством наследования, или явно, с помощью аргумента providers в блоке module. Эти два способа подробнее рассматриваются в следующих разделах.
Модуль, предназначенный для вызова одним или несколькими другими модулями, не должен содержать блоки provider. Модуль, содержащий собственные конфигурации провайдеров, несовместим с метааргументами for_each, count и depends_on.
Конфигурации провайдеров используются для выполнения всех операций со связанными ресурсами, в том числе для удаления удалённых объектов и обновления состояния. В своём состоянии OpenTofu сохраняет ссылку на конфигурацию провайдера, которая последней применялась для внесения изменений в каждый ресурс. Когда блок resource удаляется из конфигурации или динамический экземпляр ресурса удаляется путём изменения значения, заданного для метааргумента count или for_each, эта запись в состоянии будет использоваться для поиска нужной конфигурации, поскольку аргумент provider экземпляра ресурса (если он есть) больше не будет присутствовать в конфигурации.
Поэтому перед удалением экземпляра провайдера из конфигурации необходимо убедиться, что удалены все ресурсы, относящиеся к этому экземпляру провайдера. Если OpenTofu обнаружит в состоянии экземпляр ресурса, отслеживаемый с помощью экземпляра провайдера, который больше не объявлен в конфигурации, то во время планирования будет возвращена ошибка с предложением повторно добавить этот экземпляр провайдера.
Ограничения версий провайдеров в модулях
Хотя конфигурации провайдеров используются совместно разными модулями, каждый модуль должен объявить собственные требования к провайдерам, чтобы OpenTofu мог убедиться, что существует одна версия провайдера, совместимая со всеми модулями конфигурации, и указать адрес источника, служащий глобальным идентификатором провайдера, не зависящим от модуля.
Чтобы объявить, что модулю требуются определённые версии конкретного провайдера, используйте блок required_providers внутри блока terraform:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
}
}
}Например, требование к провайдеру сообщает: «Для этого модуля требуется версия v2.7.0 провайдера hashicorp/aws, на который он будет ссылаться как на aws». Однако оно не указывает параметры конфигурации, определяющие, к каким удалённым конечным точкам будет обращаться провайдер, например регион AWS. Параметры конфигурации задаются в конфигурациях провайдера, и одна конфигурация OpenTofu может содержать несколько разных конфигураций одного и того же провайдера.
Псевдонимы провайдеров в модулях
Чтобы объявить в модуле несколько имён конфигураций провайдера, добавьте аргумент configuration_aliases:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
configuration_aliases = [ aws.alternate ]
}
}
}Приведённые выше требования совпадают с предыдущими, за исключением добавления имени конфигурации провайдера с псевдонимом aws.alternate, на которое можно ссылаться из ресурсов с помощью аргумента provider.
Если вы пишете общий модуль, задавайте только минимальную требуемую версию провайдера с помощью ограничения >=. Оно должно указывать минимальную версию, включающую функции, от которых зависит ваш модуль, и позволять пользователю модуля при необходимости выбрать более новую версию провайдера, если другие части его общей конфигурации требуют дополнительных функций.
В настоящее время нельзя передать дочернему модулю целиком конфигурацию провайдера с несколькими экземплярами (объявленную с помощью for_each), хотя родительский модуль может назначить одному динамическому экземпляру конфигурации провайдера каждый экземпляр модуля.
Неявное наследование провайдеров
Для удобства работы с простыми конфигурациями дочерний модуль автоматически наследует от родительского конфигурации провайдеров по умолчанию. Это значит, что явные блоки provider присутствуют только в корневом модуле, а нижестоящие модули могут просто объявлять ресурсы для этого провайдера, которые автоматически связываются с конфигурациями провайдера корневого модуля.
Например, корневой модуль может содержать только блок provider и блок module для создания экземпляра дочернего модуля:
provider "aws" {
region = "us-west-1"
}
module "child" {
source = "./child"
}После этого дочерний модуль сможет использовать любые ресурсы этого провайдера без дополнительной настройки конфигурации провайдера:
resource "aws_s3_bucket" "example" {
bucket = "provider-inherit-example"
}Мы рекомендуем использовать этот подход, если для всей конфигурации достаточно одной конфигурации каждого провайдера.
Дочерние модули наследуют только конфигурации провайдеров, но не источники и требования к версиям провайдеров. Каждый модуль должен объявлять собственные требования к провайдерам. Это особенно важно для провайдеров, не принадлежащих HashiCorp.
В более сложных случаях может потребоваться несколько конфигураций провайдера или дочернему модулю могут потребоваться параметры провайдера, отличающиеся от родительских. В таких случаях провайдеры необходимо передавать явно.
Явная передача провайдеров
Если для дочерних модулей нужны разные конфигурации конкретного провайдера или дочернему модулю требуется конфигурация провайдера, отличающаяся от конфигурации родительского модуля, можно использовать аргумент providers в блоке module, чтобы явно указать, какие конфигурации провайдеров доступны дочернему модулю. Например:
# The default "aws" configuration is used for AWS resources in the root
# module where no explicit provider instance is selected.
provider "aws" {
region = "us-west-1"
}
# An alternate configuration is also defined for a different
# region, using the alias "usw2".
provider "aws" {
alias = "usw2"
region = "us-west-2"
}
# An example child module is instantiated with the alternate configuration,
# so any AWS resources it defines will use the us-west-2 region.
module "example" {
source = "./example"
providers = {
aws = aws.usw2
}
}Аргумент providers в блоке module похож на аргумент provider в блоке resource, но представляет собой отображение, а не одну строку, поскольку модуль может содержать ресурсы от многих разных провайдеров.
Ключи отображения providers — это имена конфигураций провайдеров, ожидаемые дочерним модулем, а значения — имена соответствующих конфигураций в текущем модуле.
При использовании аргумента providers в блоке module он переопределяет всё поведение наследования по умолчанию, поэтому необходимо перечислить соответствия для всех требуемых провайдеров. Это помогает избежать путаницы и неожиданностей, которые могут возникнуть при одновременной неявной и явной передаче провайдеров.
Дополнительные конфигурации провайдера (с заданным аргументом alias) никогда не наследуются дочерними модулями автоматически, поэтому их всегда необходимо передавать явно с помощью отображения providers. Например, модулю, который настраивает соединение между сетями в двух регионах AWS, вероятно, понадобятся регионы источника и назначения. В этом случае корневой модуль может выглядеть примерно так:
provider "aws" {
alias = "usw1"
region = "us-west-1"
}
provider "aws" {
alias = "usw2"
region = "us-west-2"
}
module "tunnel" {
source = "./tunnel"
providers = {
aws.src = aws.usw1
aws.dst = aws.usw2
}
}Затем в подкаталоге ./tunnel необходимо объявить псевдонимы конфигураций провайдера, чтобы вызывающий модуль мог передавать конфигурации с этими именами в аргументе providers:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
configuration_aliases = [ aws.src, aws.dst ]
}
}
}Затем для каждого ресурса следует задать атрибут provider со значением aws.src или aws.dst, чтобы выбрать одну из двух конфигураций провайдера.
Copyright (c) The OpenTofu Authors
Copyright (c) 2014 HashiCorp, Inc.
Mozilla Public License, version 2.0
https://opentofu.org/docs/v1.11/language/modules/develop/providers/