Вопрос или проблема
Я искал способ использовать Terraform для одновременного развёртывания на нескольких аккаунтах AWS, но пока безуспешно. AWS предоставляет возможность делать это с использованием стэков, но не уверен, есть ли такой способ в Terraform? Если есть, то какие решения возможны?
Вы можете прочитать больше о решении AWS здесь, https://aws.amazon.com/blogs/mt/supercharge-multi-account-management-with-aws-cloudformation/
Есть две проблемы, которые необходимо решить, чтобы использовать одни и те же конфигурации terraform в нескольких аккаунтах AWS. Первая – необходимо использовать другой файл состояния для каждого аккаунта. Вторая – убедиться, что провайдер AWS использует правильный профиль/учетные данные для нужного аккаунта.
Использование разных файлов состояния для каждого аккаунта
В общих чертах, terraform работает, создавая граф зависимостей ресурсов из предоставленных конфигурационных файлов terraform (*.tf) и сравнивая их с файлом состояния. Файл состояния может быть локальным (terraform.tfstate
) или находиться в удалённом бекенде; распространённым удалённым бекендом AWS является s3.
Даже если вы укажете провайдеру AWS использовать отдельные аккаунты через переменные (подробнее об этом ниже), если оба аккаунта используют один и тот же бекенд, terraform будет постоянно давать сбои. Это произойдет потому, что при переключении с одного аккаунта на другой, идентификаторы ресурсов AWS не будут совпадать, и/или ресурсы будут указаны в файле состояния, но не будут существовать в аккаунте, который в данный момент просматривает terraform.
Простой способ обойти это – использовать рабочие пространства. Рабочие пространства позволяют использовать разные файлы состояния без указания различных ключей бекенда. Использовать рабочие пространства очень просто. Если у вас есть простой блок terraform, такой как:
terraform {
backend "s3" {
bucket = "aws_bucket"
key = "terraform.tfstate"
region = "us-east-1"
}
}
Вы можете создать новые рабочие пространства, используя terraform workspace new <workspace-name>
. Таким образом, вы можете создать рабочее пространство для обоих ваших аккаунтов с помощью следующей последовательности:
terraform workspace new account-1
terraform workspace new account-2
И вы можете переключиться на текущее рабочее пространство, используя terraform workspace select
:
terraform workspace select account-1
Настройка провайдера AWS для учета рабочих пространств
Помимо использования отдельных файлов состояния, вам также необходимо указать различные учетные данные AWS (например, ключи доступа) для каждого необходимого аккаунта. Учетные данные AWS указываются с использованием провайдеров. В данном случае мы очевидно используем провайдер AWS. Вы по сути хотите использовать интерполяцию в блоке ресурса провайдера AWS, чтобы при переключении рабочих пространств terraform использовал правильные учетные данные. Предполагая, что у вас настроен файл учетных данных aws с отдельным профилем на каждый аккаунт:
[account-1]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[account-2]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
Тогда вы можете просто написать блок провайдера aws так:
provider "aws" {
region = "us-east-1"
profile = "${terraform.workspace}"
}
Так что, пока вы называете свои рабочие пространства по таким же именам, как и ваши профили aws, при переключении рабочих пространств terraform будет использовать другой профиль учетных данных aws при обновлении состояния и построении графа зависимостей.
Альтернативные методы
Это далеко не единственный способ достичь этого. Вы могли бы создать модули и тогда иметь разные директории, вызывающие модуль с различными провайдерами AWS и указанными файлами состояния. У каждого метода есть свои плюсы и минусы.
Метод рабочих пространств – это способ, как вы бы сделали это с одной директорией, и вы бы использовали точно такие же конфигурационные файлы terraform, как написано.
Модули потребуют отдельные конфигурационные файлы, которые как минимум вызовут модули и укажут провайдеров и бекенды. Модули имели бы смысл, если бы вы собирались использовать несколько аккаунтов, несколько регионов и несколько окружений. Например, если вам нужно было бы запустить в двух регионах для каждого аккаунта и двух разных окружениях (стейджинг и производство). Модули имеют смысл в этом случае, так как они предоставляют гибкость с помощью таких аргументов, как count (возможно, стейджинг запустит меньше количество инстансов и т.д.).
В основном фокус заключается в том, чтобы поместить состояние в один общий бакет и указать разные учетные данные для провайдера при переключении аккаунтов. Рабочие пространства идеально для меня работают
provider "aws" {
version = "~> 2.18"
profile = "second_account"
}
terraform {
backend "s3" {
encrypt = true
bucket = "shared_bucket"
region = "us-east-1"
key = "state"
profile = "first_shared_account"
}
required_version = "~> 0.12.7"
}
Обратите внимание на различные профили, указанные как для провайдера, так и для конфигурации бекенда.
Вы можете иметь множество различных профилей, пока каждый из них изолирован через своё рабочее пространство
aws configure --profile third_account
terraform workspace new third_account
terraform workspace select third_account
.
Ответ или решение
Развертывание инфраструктуры в нескольких учетных записях AWS с использованием Terraform — это задача, которая требует тщательного подхода и хорошего понимания особенностей работы Terraform. В этом процессе необходимо решить две основные проблемы: использование разных файлов состояния для каждой учетной записи и обеспечение правильной работы AWS-провайдера с учетом конкретной учетной записи и соответствующих учетных данных. Давайте подробно рассмотрим, как можно добиться этого с помощью Terraform.
Теоретическая часть: Обзор проблемы
Terraform управляет инфраструктурой, создавая граф зависимостей из конфигурационных файлов (*.tf) и сравнивая его с файлом состояния. Этот файл состояния может быть локальным или размещаться в удаленном бакенде, таком как S3. Проблема при работе с несколькими учетными записями заключается в том, что, если использовать один и тот же файл состояния для разных учетных записей, Terraform столкнется с несоответствиями ID ресурсов и другими ошибками, что приведет к сбоям. Эти проблемы необходимо решить, чтобы корректно и надежно управлять инфраструктурой через множество учетных записей AWS.
Практическая часть: Использование рабочих пространств
Один из способов решения этой проблемы — использование рабочих пространств (workspaces) в Terraform. Рабочие пространства позволяют создавать и переключаться между разными файлами состояния без необходимости изменения ключей на бекенде. Это позволяет сохранять разные состояния для каждой учетной записи AWS.
Пример конфигурации рабочих пространств
-
Создание рабочих пространств:
terraform workspace new account-1 terraform workspace new account-2
-
Переключение между рабочими пространствами:
terraform workspace select account-1
-
Конфигурация бекенда с использованием S3:
terraform { backend "s3" { bucket = "aws_bucket" key = "terraform/state/${terraform.workspace}/terraform.tfstate" region = "us-east-1" } }
Применение: Настройка провайдеров AWS
Чтобы обеспечить корректную работу AWS-провайдера для каждой учетной записи, необходимо задать разные учетные данные для каждой из них. Это достигается использованием интерполяции в блоке провайдера:
provider "aws" {
region = "us-east-1"
profile = "${terraform.workspace}"
}
Пример конфигурации профилей AWS:
Файл конфигурации AWS (~/.aws/credentials
):
[account-1]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[account-2]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
Альтернативные методы
Наряду с использованием рабочих пространств, существует и другой подход — использование модулей Terraform. Вы можете создавать модули, которые будут вызываться из разных директорий, каждая из которых будет содержать свою конфигурацию провайдера и бэкенда. Этот метод особенно полезен, если вы планируете развертывание в нескольких учетных записях, регионах и средах, например, для различных этапов разработки (продакшн, тестирование и т.д.).
Преимущества модулей:
- Гибкость и многократное использование конфигураций.
- Возможность легко изменять параметры, такие как количество инстансов, для разных сред и условий.
Заключение
Управление инфраструктурой в нескольких учетных записях AWS с помощью Terraform требует разбивки на разные файлы состояния и управления учетными данными с помощью провайдера. Рабочие пространства предоставляют удобный способ управления состояниями, в то время как модули можно использовать для более сложных сценариев развертывания. Главное — обеспечить изоляцию состояния между учетными записями и корректно настроить провайдер для использования нужных учетных данных.