Наличие файла состояния Terraform azure под другой подпиской

У меня две подписки в Azure. Назовем их sub-dev и sub-prod. Под sub-dev у меня есть ресурсы для разработки (в группе ресурсов rg-dev) и под sub-prod ресурсы для производства (в группе ресурсов rg-prod).

Теперь я хотел бы иметь только один файл состояния для dev и prod. Я могу это сделать, поскольку использую рабочие области Terraform (dev и prod). В sub-dev (rg-dev) есть учетная запись хранения с именем tfsate. У него есть контейнер и т. Д. Серверная часть Azure настроена следующим образом:

terraform {
  backend "azurerm" {
    resource_group_name  = "rg-dev"
    storage_account_name = "tfstate"
    container_name       = "tfcontainer"
    key                  = "terraform.tfstate" 
  }
}

Если я хочу применить к среде разработки, мне нужно переключить Az Cli на sub-dev. Точно так же для производства мне пришлось бы использовать sub-prod. Я переключаю подписку по умолчанию с помощью az cli:

az account set -s sub-prod

Проблема в том, что государственная учетная запись хранения находится в подчиненном, а не в подчиненном продукте. Я получаю ошибки доступа при попытке terraform init (или применения), когда подписка по умолчанию установлена ​​на sub-prod.

Error: Failed to get existing workspaces: Error retrieving keys for Storage Account "tfstate": storage.AccountsClient#ListKeys: Failure responding to request: StatusCode=403 -- Original Error: autorest/azure: Service returned an error. Status=403 Code="AuthorizationFailed" Message="The client '[email protected]' with object id '<redacted>' does not have authorization to perform action 'Microsoft.Storage/storageAccounts/listKeys/action' over scope '/subscriptions/sub-prod/resourceGroups/rg-dev/providers/Microsoft.Storage/storageAccounts/tfstate' or the scope is invalid. If access was recently granted, please refresh your credentials."

Я пробовал несколько вещей:

  • Я добавил subscription_id = "sub-dev"
  • Я создал токен SAS для учетной записи хранения tfstate и добавил значение конфигурации sas_token (удалено resource_group_name)

но зря и получаю ту же ошибку.

Я пытался az logout, но terraform требует, чтобы я сначала авторизовался. Должен ли я каким-то образом настраивать разрешения в конце Azure (это сложно, поскольку среда Azure настраивается сторонней организацией) или Terraform вообще поддерживает такой тип размещения вашего файла состояния при другой настройке подписки?


person Juho Rutila    schedule 31.07.2019    source источник
comment
Вам не нужен только один файл состояния для dev и prod. Если вы примените их по-разному (например, terraform apply dev и terraform apply production или какой-либо эквивалент), вам абсолютно необходимы два разных файла состояния, иначе развертывание второго файла перезапишет первый, уничтожив все в первом. И вы также не хотите одновременно применять и разработку, и продакшн.   -  person ydaetskcoR    schedule 31.07.2019
comment
Я использую рабочие области (dev и prod), поэтому могу использовать файл с одним состоянием. Должен ли я тогда, чтобы использовать разные файлы состояний, в определение серверной части некоторые условные значения?   -  person Juho Rutila    schedule 01.08.2019
comment
Я не рекомендую рабочие пространства для статических сред. Они усложняют вещи и затрудняют понимание того, что вы развернули, с первого взгляда на структуру кода / файла, поэтому вы упускаете одно из больших преимуществ IaC.   -  person ydaetskcoR    schedule 01.08.2019
comment
Итак, вы предлагаете иметь два разных каталога (dev и prod) с одинаковыми tf-файлами (параметризованное имя группы ресурсов) и разными конфигурациями бэкэнда?   -  person Juho Rutila    schedule 01.08.2019
comment
Ага. Я бы использовал модули или символические ссылки, чтобы сохранить СУХИЕ вещи, и изменять только то, что вам нужно, с помощью разных файлов tfvars и файлов конфигурации провайдера. Есть ряд других вопросов и ответов о том, как это структурировать уже на SO.   -  person ydaetskcoR    schedule 01.08.2019
comment
Я закончил делать это так, как вы предлагали @ydaetskcoR. Я оставляю вопрос открытым, если кто-то все же хочет на него ответить. Я не нашел способа сделать это сам.   -  person Juho Rutila    schedule 02.08.2019


Ответы (2)


Как бы то ни было (я не особо экспериментировал с другими методами организации терраформирования), мы используем терраформ точно так, как вы описываете. Файл состояния на удаленном сервере, в другой подписке на мои ресурсы. Рабочие области создаются для обработки сред для развертывания.

Наши файлы состояний определены так:

terraform {
  required_version = ">= 0.12.6"
  
  backend "azurerm" {
    subscription_id      = "<subscription GUID storage account is in>"
    resource_group_name  = "terraform-rg"
    storage_account_name = "myterraform"
    container_name       = "tfstate"
    key                  = "root.terraform.tfstate"
  }
}

Мы храним нашу учетную запись хранения terraform в совершенно другой подписке, чем наши развертывания, но в этом нет необходимости.

При такой настройке файла состояния он аутентифицируется на удаленном сервере через z CLI, используя контекст человека, взаимодействующего с CLI. Этот человек должен иметь роль читателя и доступа к данным для учетной записи хранения, чтобы динамически получать ключи учетной записи хранения во время выполнения.

С настроенным вышеупомянутым файлом состояния выполнение Terraform будет

az login
az account set -s "<name of subscription where you want to create resources>"
terraform init
terraform plan
terraform apply
person haodeon    schedule 06.08.2019
comment
Можете ли вы обновить свой ответ, чтобы узнать, какую подписку вы используете (подписка на учетную запись хранения terraform / подписка на ресурсы) при входе в систему? - person Juho Rutila; 06.08.2019
comment
Вместо этого я должен сделать az account set --subscription "<<sub>>" - person severin.julien; 18.06.2020
comment
Привет @haodeon. Здесь тот же сценарий. Однако я запускаю сценарии terraform, используя субъект-службу, который имеет разрешение только на подписку, в которой я хочу создать ресурсы. terraform init получает StatusCode 403, хотя я правильно добавил access_key для учетной записи хранения. - person Renato Silva; 04.02.2021
comment
Похоже, у меня это не работает. Я добавил свойство subscription_id в серверный блок azurerm, но оно по-прежнему вызывает ту же ошибку. Это похоже на игнорирование свойства subscription_id. Я использую terraform 0.13 с версией провайдера azurerm 2.44.0 - person Anthony Klotz; 10.02.2021
comment
@RenatoSilva Для использования субъекта-службы, у которого нет разрешений RBAC для учетной записи хранения, требуется ключ доступа к хранилищу. Я не уверен, почему в вашем случае это не работает. Сам тестировал, работает нормально, использую через переменные окружения. - person haodeon; 17.02.2021

Есть другой способ сделать это. Вы можете использовать ключ доступа, связанный с учетной записью хранения в другой подписке, и экспортировать его как переменную среды. Баш:

export ARM_ACCESS_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query '[0].value' -o tsv)

Powershell:

$env:ARM_ACCESS_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query '[0].value' -o tsv)
person ehsan khodadadi    schedule 14.01.2021