Terraform управляет ресурсами в виде состояния.
Если ресурс уже существует в файле состояния, и Terraform не обнаруживает дрейфа между конфигурацией, состоянием и любыми различиями в поставщике (например, что-то былоизменено в консоли AWS или другим инструментом), то это покажет, что изменений нет.Если он обнаружит некоторую форму дрейфа, то plan
покажет вам, какие изменения необходимо внести, чтобы подтолкнуть существующее состояние в провайдере к тому, что определено в коде Terraform.
Разделение состояния междуразличные среды
Если вы хотите иметь несколько сред или даже другие ресурсы, которые отделены друг от друга и не управляются одним и тем же действием Terraform (например, plan
, apply
или destroy
), тогдаВы хотите разделить их на разные файлы состояний.
Один из способов сделать это - разделить ваш код Terraform по среде и использовать файл состояний, соответствующий структуре каталогов вашей кодовой базы.Простой пример может выглядеть примерно так:
terraform/
├── production
│ ├── main.tf -> ../stacks/main.tf
│ └── terraform.tfvars
├── stacks
│ └── main.tf
└── staging
├── main.tf -> ../stacks/main.tf
└── terraform.tfvars
stacks / main.tf
variable "environment" {}
resource "aws_lambda_function" "foo" {
function_name = "foo-${var.environment}"
# ...
}
production / terraform.tfvars
environment = "production"
staging / terraform.tfvars
environment = "staging"
При этом используются символические ссылки, так что подготовка и производство поддерживаются в строках в коде с единственными изменениями, вносимыми в файл terraform.tfvars
.В этом случае он меняет имя лямбда-функции, чтобы включить среду.
Это то, что я обычно рекомендую для статических сред, так как гораздо яснее смотреть на структуру кода / каталога, какие среды существуют.
Динамические среды
Однако, если у вас есть более динамические среды, например, для каждой ветви функций, то не будет сложно жестко закодировать имя среды непосредственно в файле terraform.tfvars
.
В этом случае я бы порекомендовал что-то вроде этого:
terraform/
├── production
│ ├── main.tf -> ../stacks/main.tf
│ └── terraform.tfvars
├── review
│ ├── main.tf -> ../stacks/main.tf
│ └── terraform.tfvars
├── stacks
│ └── main.tf
└── staging
├── main.tf -> ../stacks/main.tf
└── terraform.tfvars
Это работает так же, но я бы пропустил переменную environment
в структуре review
, чтобы она была установлена интерактивно или через переменные среды CI (например, export TF_VAR_environment=${TRAVIS_BRANCH}
при работе в Travis CI, адаптируйте его для поддержки любой используемой вами системы CI.
Сохранение состояния раздельным между средами обзора в разных ветвях
Это дает вам только половину пути, потому чтокогда другой человек попытается использовать это с другой ветвью, он увидит, что Terraform хочет уничтожить / обновить любые ресурсы, которые уже созданы, запустив Terraform, если вы просто используете рабочее пространство по умолчанию .
Рабочие пространства предоставляют возможность разделения состояния более динамичным способом, а такжепозволяет интерполировать имя рабочего пространства в код Terraform :
resource "aws_instance" "example" {
tags {
Name = "web - ${terraform.workspace}"
}
# ... other arguments
}
Вместо этого средам обзора потребуется создать или использовать динамическое рабочее пространство, которое ограничено только для этой ветви.Вы можете сделать это, выполнив следующую команду :
terraform workspace new [NAME]
Если рабочее пространство уже существует, вам следует вместо этого использовать следующую команду :
terraform workspace select [NAME]
В CI вы можете использовать те же переменные среды, что и раньше, чтобы автоматически использовать имя ветви в качестве имени вашего рабочего пространства.