В данном примере мы создадим Terraform модуль для провайдера AWS, который будет запускаться для 3-х разных окружений при помощи Terragrunt'a.
Требования:
- Установленный AWS CLI
- Установленный Terraform (версия выше 12.0)
- Установленный Terragrunt
Создадим обязательные файлы для Terragrunt'а:
terragrunt.hcl
terraform { extra_arguments "custom_vars" { commands = get_terraform_commands_that_need_vars() arguments = [ "-var-file=${get_terragrunt_dir()}/common.tfvars", ] } } remote_state { backend = "s3" config = { bucket = "tfstate.eu-west-2.artem" key = "${path_relative_to_include()}/terraform.tfstate" region = "eu-west-2" encrypt = true dynamodb_table = "my-lock-table" } }
Зададим имя S3 корзины, которая будет хранить состояние Terragrunt'а, создавать ее предварительно не нужно, Terragrunt создаст ее сам. Так же зададим регион.
Создадим файл для хранения переменных Terraform'а и Terragrunt'а:
touch common.tfvars variables.tf
Напишем первый модуль, который будет создавать VPC и Internet Gateway для него.
Создаем директорию для модулей и для VPC в частности:
mkdir -p modules/vpc
Модули работают по принципу функции, при обращении к ним мы передаем ряд переменных.
Для создания VPC нам нужно знать следующее:
- Имя VPC
- CIDR
Создадим отдельный файл для переменных "modules/vpc/variables.tf" и добавим туда следующее:
variable "vpc_name" {} variable "vpc_cidr" {}
Создаем сам модуль, для этого создаем файл "modules/vpc/main.tf" со следующим содержимым:
#################### CREATE VPC #################### resource "aws_vpc" "vpc" { cidr_block = var.vpc_cidr enable_dns_hostnames = "true" enable_dns_support = "true" tags = { Name = var.vpc_name } } ############# CREATE INTERNET GATEWAY ############## resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.vpc.id tags = { Name = "${var.vpc_name}-IGW" } }
Мы будем создавать шаблон для трех разных окружений:
- development
- staging
- production
Заполним файл переменных для Terragrunt'а:
common.tfvars
### DEVELOPMENT ENVIRONMENT #### development_aws_region = "us-east-1" development_vpc_name = "ARTEM-DEVELOPMENT-USE1" development_vpc_cidr = "192.168.0.0/16" ######### END OF BLOCK ######### ##### STAGING ENVIRONMENT ###### staging_aws_region = "us-east-1" staging_vpc_name = "ARTEM-STAGING-USE1" staging_vpc_cidr = "192.168.0.0/16" ######### END OF BLOCK ######### #### PRODUCTION ENVIRONMENT #### production_aws_region = "eu-central-1" production_vpc_name = "ARTEM-PRODUCTION-EUC1" production_vpc_cidr = "192.168.0.0/16" ######### END OF BLOCK #########
Теперь заполним файл переменных Terraform'а:
variables.tf
### DEVELOPMENT ENVIRONMENT #### variable "development_aws_region" {} variable "development_vpc_name" {} variable "development_vpc_cidr" {} ######### END OF BLOCK ######### ##### STAGING ENVIRONMENT ###### variable "staging_aws_region" {} variable "staging_vpc_name" {} variable "staging_vpc_cidr" {} ######### END OF BLOCK ######### #### PRODUCTION ENVIRONMENT #### variable "production_aws_region" {} variable "production_vpc_name" {} variable "production_vpc_cidr" {} ######### END OF BLOCK #########
Мы готовы к созданию первой среды, начнем с development среды
Создаем структуру:
mkdir -p environments/development
Перейдем в созданную директорию:
cd environments/development
Создадим обязательный файл "terragrunt.hcl" и вставим в него следующее:
include { path = find_in_parent_folders() }
И создадим символические ссылки на файлы переменных, находящиеся в корне:
ln -s ../../variables.tf variables.tf ln -s ../../common.tfvars common.tfvars
Создадим файл "main.tf" со следующим содержимым:
terraform { backend "s3" {} } provider "aws" { region = var.development_aws_region }
Все, теперь можно создавать файл Terraform'а для вызова модуля для создания VPC.
vpc.tf
module "vpc" { source = "../../modules/vpc" vpc_name = var.development_vpc_name vpc_cidr = var.development_vpc_cidr }
Выполняем:
terragrunt init
При первом запуске Terragrunt скажет, что корзины для хранения состояний не существует, и предложит создать ее, соглашаемся.
После init'а, смотрим версию Terraform'а и AWS провайдера, лучше эти версии указать в файле "main.tf", если планируется запуск с другого компьютера (так как мы создаем корзину для хранения состояния, то мы и подразумеваем запуск с любого компьютера с сохранением текущего состояния)
terraform --version Terraform v0.12.9 + provider.aws v2.30.0
main.tf
terraform { backend "s3" {} required_version = "~> 0.12.9" } provider "aws" { region = var.development_aws_region version = "~> 2.30" }
Теперь по образу development среды, создадим staging и production. Возвращаемся в корень проекта, удаляем директорию ".terraform" в "envarinments/development" и копируем development среду:
rm -rf environments/development/.terraform/ cp -aR environments/development environments/staging cp -aR environments/development environments/production
Меняем переменные для staging'а:
sed -i 's/development/staging/g' environments/staging/{main.tf,vpc.tf}
Меняем переменные для production'а:
sed -i 's/development/production/g' environments/production/{main.tf,vpc.tf}
Теперь находясь в корне проекта можем запустить планировку для все окружений одной командой:
terragrunt plan-all
Применить данный теймплейт можно как для каждой среды в частности, находясь в директории необходимой среды выполнить:
terragrunt apply
Или же для всех сразу, находясь в корне проекта выполнить:
terragrunt apply-all
Финальная наша структура выглядит следующим образом:
. ├── common.tfvars ├── environments │ ├── development │ │ ├── common.tfvars -> ../../common.tfvars │ │ ├── main.tf │ │ ├── terragrunt.hcl │ │ ├── variables.tf -> ../../variables.tf │ │ └── vpc.tf │ ├── production │ │ ├── common.tfvars -> ../../common.tfvars │ │ ├── main.tf │ │ ├── terragrunt.hcl │ │ ├── variables.tf -> ../../variables.tf │ │ └── vpc.tf │ └── staging │ ├── common.tfvars -> ../../common.tfvars │ ├── main.tf │ ├── terragrunt.hcl │ ├── variables.tf -> ../../variables.tf │ └── vpc.tf ├── modules │ └── vpc │ ├── main.tf │ └── variables.tf ├── terragrunt.hcl └── variables.tf 6 directories, 20 files
Для того, чтобы хранить наш шаблон в репозитории, в файл ".gitignore" добавим следующее:
.terraform/ terraform.*
Данный пример можно скачать Git репозиторием:
https://bitbucket.org/artem-gatchenko/example-terraform-module-part1