使用Terraform来管理针对环境的不同状态
我想做的事情
我想根据不同的环境(开发和生产)将Terraform划分并管理各自的资源。
做过的事情
创建每个环境的tfstate,并在目录中分隔环境。
大致而言,目录结构大致如此。
├── .terraform
│ ├── terraform.tfstate
│ └── terraform.tfstate.backup
├── development
│ ├── .terraform
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── config.tf
│ ├── ec2.tf
│ ├── elasticache.tf
│ ├── elb.tf
│ ├── iam.tf
│ ├── rds.tf
│ ├── route53.tf
│ ├── s3.tf
│ ├── security_group.tf
│ ├── variables.tf
│ └── vpc.tf
├── production
│ ├── .terraform
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── config.tf
│ ├── ec2.tf
│ ├── elasticache.tf
│ ├── elb.tf
│ ├── iam.tf
│ ├── rds.tf
│ ├── route53.tf
│ ├── s3.tf
│ ├── security_group.tf
│ ├── variables.tf
│ └── vpc.tf
├── route53.tf
├── s3.tf
├── config.tf
└── variables.tf
作为要点
-
- ルートディレクトリにそれぞれの環境で共通のリソースを作る
一部IAM Role、IAM User、Route53のZone、それぞれの環境で共通で使うS3バケット、共通のVPCなど
環境別にディレクトリを切る
それぞれの環境固有のリソースはそのディレクトリ内で作成。(環境ごとに固有のドメイン、環境固有のS3のオブジェクト、VPC、EC2インスタンスなど)
上位のリソースのIDやARNなどはoutputs経由で委譲してもらう
为什么会有这样的结构呢,因为我考虑过根据不同的环境准备Var文件(Terraform中的变量)并在应用执行时进行切换的方法。
-
- オプションの切り替えで事故りそう(-state, -varでの指定で毎回正確に指定出来る自信がない)
- 事故を防ぐため複数人で作業する場合でもオプション指定無しでも実行出来るようにしたい(terraform plan, terraform applyのみで実行出来るようにしたい)
虽然这种写法略显冗长,无法像变量文件切换那样实现重用性,但由于基础设施事故一个错误就可能导致灾难,所以更希望通过明确性来确保安全,而不是过于追求重用性。这就是为什么我们选择了这种结构。
建構方式
- ルートディレクトリでS3をremote stateに設定をする
terraform remote config \
-backend=S3 \
-backend-config="bucket=your.terraform.bucket" \
-backend-config="key=super.terraform.tfstate" \
-backend-config="region=ap-northeast-1"
- 共通のリソースを作る
route53.tf的意思是使用Terraform配置Amazon Route53服务。
resource "aws_route53_zone" "foobar" {
name = "foobar.com"
comment = "foo!"
tags {
name = "foobar"
}
}
outputを定義する
在这里定义的输出资源可以委托给各个环境并使用。
$ vim outputs.tf
输出.tf
output "zone_id" {
value = "${aws_route53_zone.foobar.id}"
}
使用计划进行确认,使用申请进行应用。
terraform plan
terraform apply
- リモートにtfstateファイルをpush
完成应用后,将状态文件推送到远程的S3。
terraform remote push
- 各環境別のリソースを作成
我們將從這裡開始創建各個環境所需的資源。
$ mkdir development
$ cd development
从命令行设置不同环境的远程状态。
terraform remote config \
-backend=S3 \
-backend-config="bucket=your.terraform.bucket" \
-backend-config="key=development.terraform.tfstate" \
-backend-config="region=ap-northeast-1"
为了从资源定义中使用远程状态,需要定义terraform_remote_state。
vim config.tf
config.tf的中文翻译为:配置.tf
resource "terraform_remote_state" "super_state" {
backend = "s3"
config {
bucket = "your.terraform.bucket"
region = "ap-northeast-1"
key = "super.terraform.tfstate"
}
}
resource "terraform_remote_state" "development_state" {
backend = "s3"
config {
bucket = "your.terraform.bucket"
region = "ap-northeast-1"
key = "development.terraform.tfstate"
}
}
假设您想要在Route53上设置用于开发环境的域名。
$ vim route53.tf
route53.tf的中文意思是什么?
resource "aws_route53_record" "dev_api" {
zone_id = "${terraform_remote_state.super_state.output.zone_id}"
name = "dev.api.foobar.com"
type = "A"
}
通过委托`${terraform_remote_state.super_state.output.zone_id}`在根目录输出,实现了这样的效果。
这样一来,在多人合作时,可以参考远程状态并定义资源,使团队的工作和资源组件化更加容易。
资源定义完成后,我们会在每个环境对应的目录中使用相同的 plan、apply 进行应用。
terraform plan
terraform apply
总结
通过将terraform的状态(state)按照环境分别存放在不同的目录下进行管理,
如果误操作或者仅使用手动方式在远程更改配置的话,tfstate很容易失去一致性,可能导致事故的发生,因此在操作方式上需要谨慎。