Различные среды для Terraform (Hashicorp)

Я использую Terraform для сборки своего стека AWS и наслаждаюсь им. Если он должен использоваться в коммерческих настройках, конфигурация должна быть повторно использована для разных сред (например, QA, STAGING, PROD).

Как я смогу добиться этого? Должен ли я создать оболочку script, которая вызывает вызовы terraform cli при передаче в разных файлах состояния для каждой среды, как показано ниже? Мне интересно, есть ли более естественное решение, предоставленное Terraform.

terraform apply -state=qa.tfstate

Ответы

Ответ 1

Я предлагаю вам взглянуть на репозиторий best-practices hashicorp, который имеет неплохую настройку для работы с разными средами (аналогично тому, что предложил Джеймс Вулфенден),

Мы используем аналогичную настройку, и она работает очень хорошо. Тем не менее, это передовой опыт репо предполагает, что вы используете Atlas, которого нет. Мы создали довольно сложный Rakefile, который в основном (перейдя на репозиторий лучших практик) получает все подпапки /terraform/providers/aws и предоставляет их как разные сборки с использованием пространств имен. Таким образом, наш вывод rake -T отображает следующие задачи:

us_east_1_prod:init
us_east_1_prod:plan
us_east_1_prod:apply

us_east_1_staging:init
us_east_1_staging:plan
us_east_1_staging:apply

Это разделение предотвращает изменения, которые могут быть исключительными для того, чтобы dev случайно повлиял (или, что еще хуже, уничтожил) что-то в prod, так как это другой файл состояния. Он также позволяет тестировать изменения в dev/staging, прежде чем применять его к prod.

Кроме того, я недавно наткнулся на эту небольшую запись, которая в основном показывает, что может произойти, если вы будете держать все вместе: https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/

Ответ 2

Решение Paul с модулями - правильная идея. Тем не менее, я настоятельно рекомендую не определять все ваши среды (например, QA, этап, производство) в том же файле Terraform. Если вы это сделаете, то всякий раз, когда вы делаете изменения в постановке, вы рискуете также случайным нарушением производства, что частично поражает точку, в которой эти среды изолированы в первую очередь! См. Terraform, VPC и почему вы хотите использовать файл tfstate для env для яркого обсуждения того, что может пойти не так.

Я всегда рекомендую хранить код Terraform для каждой среды в отдельной папке. Фактически, вы можете даже захотеть сохранить код Terraform для каждого "компонента" (например, базы данных, VPC, одного приложения) в отдельных папках. Опять же, причина заключается в изоляции: при внесении изменений в одно приложение (которое вы можете делать 10 раз в день), вы не хотите подвергать весь ваш VPC риску (который вы, вероятно, никогда не измените).

Поэтому мой типичный макет файла выглядит примерно так:

stage
  └ vpc
     └ main.tf
     └ vars.tf
     └ outputs.tf
  └ app
  └ db
prod
  └ vpc
  └ app
  └ db
global
  └ s3
  └ iam

Весь код Terraform для промежуточной среды входит в папку stage, весь код для среды prod входит в папку prod и весь код, который живет за пределами среды (например, пользователи IAM, S3 ведра) переходит в папку global.

Для получения дополнительной информации ознакомьтесь с Как управлять состоянием Terraform. Для более глубокого изучения лучших практик Terraform, посмотрите книгу Terraform: Up and Running.

Ответ 3

По мере расширения вашего использования terraform вам необходимо разделить состояние (между разработчиками, процессы сборки и различные проекты), поддерживать несколько сред и регионов. Для этого вам нужно использовать удаленное состояние. Перед тем, как выполнить свою терраформию, вам нужно настроить свое состояние. (Im using powershell)

$environment="devtestexample"
$region     ="eu-west-1"
$remote_state_bucket = "${environment}-terraform-state"
$bucket_key = "yoursharedobject.$region.tfstate"

aws s3 ls "s3://$remote_state_bucket"|out-null
if ($lastexitcode)
{
   aws s3 mb "s3://$remote_state_bucket"
}

terraform remote config -backend S3 -backend-config="bucket=$remote_state_bucket"  -backend-config="key=$bucket_key" -backend-config="region=$region"
#(see here: https://www.terraform.io/docs/commands/remote-config.html)

terraform apply -var='environment=$environment' -var='region=$region'

Ваше состояние теперь сохраняется в S3, по регионам, по среде, и вы можете получить доступ к этому состоянию в других проектах tf.

Ответ 4

Не нужно создавать обертку script. Что мы делаем, так это разделить наш env на модуль, а затем получить файл верхнего уровня, где мы просто импортируем этот модуль для каждой среды. Пока у вас есть настройка модуля, чтобы принимать достаточно переменных, как правило, env_name и несколько других, вы хороши. В качестве примера

# project/main.tf
module "dev" {
    source "./env"

    env = "dev"
    aws_ssh_keyname = "dev_ssh"
}

module "stage" {
    source "./env"

    env = "stage"
    aws_ssh_keyname = "stage_ssh"
}

# Then in project/env/main.tf
# All the resources would be defined in here
# along with variables for env and aws_ssh_keyname, etc.

Ответ 5

Обратите внимание, что начиная с версии 0.10.0 Terraform поддерживает концепцию Workspaces (среды в 0.9.x).

Рабочее пространство - это именованный контейнер для состояния Terraform. При использовании нескольких рабочих пространств единый каталог конфигурации Terraform может использоваться для управления несколькими различными наборами ресурсов инфраструктуры.

Подробнее см. здесь: https://www.terraform.io/docs/state/workspaces.html