我们正在尝试使用存储在S3中的远程状态的terraform.
项目正在被打破,例如有"主"VPC项目,它只创建网络基础(vpc,子网,IGW,NAT,路由等)和子项目,在主要基础上创建特定资源vpc(子网),即ec2节点.
项目文件夹/文件:
. ??? modules/ ? ??? mod-vpc/ ? ??? main.tf ? ??? outputs.tf ? ??? variables.tf ??? projects/ ? ??? top-level-project-name-goes-here/ ? ??? env-dev/ ? ? ??? globals.tf ? ? ??? test/ ? ? ? ??? main.tf ? ? ? ??? variables.tf ? ? ??? vpc/ ? ? ??? main.tf ? ? ??? variables.tf ? ??? env-prod/ ??? terraform.tfvars
除了VPC项目之外,所有其他项目都使用来自远程VPC状态的vpc_id,CIDR等.以下是我们的流程定义方式:
第1步:创建VPC.
这里没有问题,VPC被创建,输出打印出来,并存储到S3存储桶:
$ terraform init -backend=s3 -backend-config="region= us-west-2" -backend-config="bucket=xxx" -backend-config="key=xxx" -backend-config="acl=bucket-owner-full-control" $project_path $ terraform remote pull $ terraform get $project_path $ terraform apply
...
Outputs: cidr_block = 10.198.0.0/16 private_subnet_ids = subnet-d3f5029a,subnet-fbeb369c,subnet-7ad88622 public_subnet_ids = subnet-54f5021d region = us-west-2 vpc_id = vpc-b31ca3d4 vpc_name = main_vpc
步骤2:创建其他资源组:使用VPC远程状态的输出值,尝试将ec2节点部署到已配置的公共子网(上面步骤1中的VPC项目输出).以下是我们的脚本运行的步骤/命令(首先我们将所有文件复制到/ tmp/project/working文件夹,脚本在此文件夹中执行):
$ terraform init -backend=s3 -backend-config="region= us-west-2" -backend-config="bucket=xxx" -backend-config="key=xxx" -backend-config="acl=bucket-owner-full-control" $project_path $ terraform remote pull $ terraform get $project_path $ terraform apply
/ tmp/project /文件夹内容:
以下是项目文件结构的样子(在/ tmp/project /文件夹中):
??? .terraform ? ??? modules ? ? ??? 7d29d4ce6c4f98d8bcaa8b3c0ca4f8f1 -> /pathto/modules/mod-cassandra ? ? ??? aa8ffe05b5d08913f821fdb23ccdfd95 ? ??? terraform.tfstate ??? globals.tf ??? main.tf ??? terraform.tfvars ??? variables.tf
以下是此项目的main.tf文件的外观:
resource "aws_instance" "test" { instance_type = "${var.instance_type}" ami = "${var.ami}" subnet_id = "${data.terraform_remote_state.vpc_main.public_subnet_ids}" vpc_security_group_ids = ["${aws_security_group.http_ext.id}"] }
以下是data.terraform_remote_state资源的定义:
data "terraform_remote_state" "vpc_main" { backend = "s3" config { region = "us-west-2" bucket = "xxx" key = "xxx/vpc.json" } }
根据我们声明"data.terraform_remote_state.vpc_main"资源的位置(哪个文件),我们得到的结果不同:
选项1. 如果我们在"test"项目(= main.tf)中的同一文件中声明了"data.terraform_remote_state",则所有内容都会成功执行.
选项2. 如果我们将data.terraform_remote_state.vpc_main移动到单独的文件(="globals.tf"),我们会在执行[ terraform get $ project_path ]步骤时遇到此错误:
$ terraform init -backend=s3 -backend-config="region= us-west-2" -backend-config="bucket=xxx" -backend-config="key=xxx" -backend-config="acl=bucket-owner-full-control" $project_path $ terraform remote pull $ terraform get $project_path Error loading Terraform: module root: 4 error(s) occurred: * module 'cassandra': unknown resource 'data.terraform_remote_state.vpc_main' referenced in variable data.terraform_remote_state.vpc_main.cidr_block * module 'cassandra': unknown resource 'data.terraform_remote_state.vpc_main' referenced in variable data.terraform_remote_state.vpc_main.region * module 'cassandra': unknown resource 'data.terraform_remote_state.vpc_main' referenced in variable data.terraform_remote_state.vpc_main.vpc_id * module 'cassandra': unknown resource 'data.terraform_remote_state.vpc_main' referenced in variable data.terraform_remote_state.vpc_main.public_subnet_ids
由于某种原因,Terraform无法解析此data.terraform_remote_state.vpc_main资源.
选项3. 但是出于测试目的,我们启用两个声明(在"globals.tf"和"main.tf"中),我们在执行[ terraform apply ]步骤时遇到此错误:
$ terraform init -backend=s3 -backend-config="region= us-west-2" -backend-config="bucket=xxx" -backend-config="key=xxx" -backend-config="acl=bucket-owner-full-control" $project_path $ terraform remote pull $ terraform get $project_path $ terraform apply module root: 1 error(s) occurred: 2017/01/14 14:02:50 [DEBUG] plugin: waiting for all plugin processes to complete... • data.terraform_remote_state.vpc_main: resource repeated multiple times
这是一个有效的错误,因为我们现在拥有在两个地方定义的相同资源.
但是,当我们尝试将其放入上面选项2下的单独文件时,为什么Terraform无法正确解析此资源?
每个terraform文档所有*.tf文件都按字母顺序加载和追加,资源声明顺序无关紧要,因为terraform配置是声明性的:
https://www.terraform.io/docs/configuration/load.html
这似乎不是上面的情况.
我们可以在这里使用"硬编码"方法,但Terraform中有一种"合法"方式可以使这项工作成功吗?