地形远程状态
terraform remote state
我们正在尝试将 Terraform 与存储在 S3 中的远程状态结合使用。
项目正在中断,例如“主要”VPC 项目,它仅创建网络基础设施(vpc、子网、IGW、NAT、路由等),以及子项目,创建特定资源在主要 vpc(子网)之上,即 ec2 节点。
项目 folders/files:
.
├── 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 节点部署到已配置的 public 个子网(上述步骤 1 中 VPC 项目的输出)。这是我们的脚本运行的 steps/commands(首先我们将所有文件复制到 /tmp/project/ 工作文件夹,然后在该文件夹中执行脚本):
$ 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.
如果我们在“测试”项目 (=main.tf) 的同一文件中声明了“data.terraform_remote_state”,那么一切都会成功执行。
选项 2.
如果我们将 data.terraform_remote_state.vpc_main 移动到一个单独的文件 (=”globals.tf”),我们会在执行 [terraform get $[=98 期间遇到此错误=]] 步骤:
$ 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
这是一个有效的错误,因为我们现在确实在两个地方定义了相同的资源。
但是为什么 Terraform 无法正确解析此资源,当我们尝试将其放入上述选项 2 下的单独文件中时?
根据 terraform 文档,所有 *.tf 文件都按字母顺序加载和附加,资源声明顺序无关紧要,因为 terraform 配置是声明性的:
https://www.terraform.io/docs/configuration/load.html
上面的情况好像不是这样。
我们可以在这里使用“硬编码”方法,但是 Terraform 中是否有“合法”的方法来实现这一点?
尝试使用该命令设置远程状态:
terraform_bucket_region='eu-west-1'
terraform_bucket_name='xxx'
terraform_file_name="terraform.tfstate"
export AWS_ACCESS_KEY_ID="xxx"
export AWS_SECRET_ACCESS_KEY="xxx"
[ -d .terraform ] && rm -rf .terraform
[ -f terraform.tfstate.backup ] && rm terraform.tfstate.backup
terraform remote config -backend=S3 -backend-config="region=${terraform_bucket_region}" -backend-config="bucket=${terraform_bucket_name}" -backend-config="key=${terraform_file_name}"
terraform get
我已将其设置为名为 set-remote-tf.sh
的 shell 脚本。
我使用 Terraform 远程状态有一段时间了。
我认为你的问题是关于地形状态依赖性的组织问题。
您应该 运行 每个文件夹的 terraform。每个也有一个 config.tf。
.
├── modules/
│ └── mod-vpc/
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── projects/
│ └── top-level-project-name-goes-here/
│ ├── env-dev/
│ │ ├── globals.tf
│ │ ├── test/
| | | |-- config.tf
│ │ │ ├── main.tf
│ │ │ └── variables.tf
| | | |-- terraform.tfvars
│ │ └── vpc/
| | |-- config.tf
│ │ ├── main.tf
│ │ └── variables.tf
| | |-- terraform.tfvars
│ └── env-prod/
# ../vpc/config.tf
terraform {
backend "s3" {
bucket = "my-infrastructure"
prefix = "vpc"
}
}
# ../test
terraform {
backend "s3" {
bucket = "my-infrastructure"
prefix = "test"
}
}
data "terraform_remote_state" "vpc_main" {
backend = "s3"
# workspace = "${terraform.workspace}" // optional
config {
bucket = "my-infrastructure"
prefix = "vpc"
}
}
data "terraform_remote_state" "other_terraform_state" {
backend = "s3"
workspace = "${terraform.workspace}"
config {
bucket = "my-infrastructure"
prefix = "other_terraform_state"
}
}
您可以在此处查看 GCP 示例 https://github.com/abgm/gcp-terraform-example/tree/first-example
我们正在尝试将 Terraform 与存储在 S3 中的远程状态结合使用。
项目正在中断,例如“主要”VPC 项目,它仅创建网络基础设施(vpc、子网、IGW、NAT、路由等),以及子项目,创建特定资源在主要 vpc(子网)之上,即 ec2 节点。
项目 folders/files:
.
├── 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 节点部署到已配置的 public 个子网(上述步骤 1 中 VPC 项目的输出)。这是我们的脚本运行的 steps/commands(首先我们将所有文件复制到 /tmp/project/ 工作文件夹,然后在该文件夹中执行脚本):
$ 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. 如果我们在“测试”项目 (=main.tf) 的同一文件中声明了“data.terraform_remote_state”,那么一切都会成功执行。
选项 2. 如果我们将 data.terraform_remote_state.vpc_main 移动到一个单独的文件 (=”globals.tf”),我们会在执行 [terraform get $[=98 期间遇到此错误=]] 步骤:
$ 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
这是一个有效的错误,因为我们现在确实在两个地方定义了相同的资源。
但是为什么 Terraform 无法正确解析此资源,当我们尝试将其放入上述选项 2 下的单独文件中时?
根据 terraform 文档,所有 *.tf 文件都按字母顺序加载和附加,资源声明顺序无关紧要,因为 terraform 配置是声明性的:
https://www.terraform.io/docs/configuration/load.html
上面的情况好像不是这样。
我们可以在这里使用“硬编码”方法,但是 Terraform 中是否有“合法”的方法来实现这一点?
尝试使用该命令设置远程状态:
terraform_bucket_region='eu-west-1'
terraform_bucket_name='xxx'
terraform_file_name="terraform.tfstate"
export AWS_ACCESS_KEY_ID="xxx"
export AWS_SECRET_ACCESS_KEY="xxx"
[ -d .terraform ] && rm -rf .terraform
[ -f terraform.tfstate.backup ] && rm terraform.tfstate.backup
terraform remote config -backend=S3 -backend-config="region=${terraform_bucket_region}" -backend-config="bucket=${terraform_bucket_name}" -backend-config="key=${terraform_file_name}"
terraform get
我已将其设置为名为 set-remote-tf.sh
的 shell 脚本。
我使用 Terraform 远程状态有一段时间了。 我认为你的问题是关于地形状态依赖性的组织问题。
您应该 运行 每个文件夹的 terraform。每个也有一个 config.tf。
.
├── modules/
│ └── mod-vpc/
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── projects/
│ └── top-level-project-name-goes-here/
│ ├── env-dev/
│ │ ├── globals.tf
│ │ ├── test/
| | | |-- config.tf
│ │ │ ├── main.tf
│ │ │ └── variables.tf
| | | |-- terraform.tfvars
│ │ └── vpc/
| | |-- config.tf
│ │ ├── main.tf
│ │ └── variables.tf
| | |-- terraform.tfvars
│ └── env-prod/
# ../vpc/config.tf
terraform {
backend "s3" {
bucket = "my-infrastructure"
prefix = "vpc"
}
}
# ../test
terraform {
backend "s3" {
bucket = "my-infrastructure"
prefix = "test"
}
}
data "terraform_remote_state" "vpc_main" {
backend = "s3"
# workspace = "${terraform.workspace}" // optional
config {
bucket = "my-infrastructure"
prefix = "vpc"
}
}
data "terraform_remote_state" "other_terraform_state" {
backend = "s3"
workspace = "${terraform.workspace}"
config {
bucket = "my-infrastructure"
prefix = "other_terraform_state"
}
}
您可以在此处查看 GCP 示例 https://github.com/abgm/gcp-terraform-example/tree/first-example