资源栈配置说明
当同一套基础设施需要部署到多个环境时,逐环境维护独立配置容易产生差异。资源栈通过两份 YAML 配置文件统一定义组件结构、环境参数和执行规则,并结合 Terraform 模块完成基础设施交付。
资源栈包含以下内容:
tfcomponent.yaml:定义基础设施组件、组件依赖、Provider和输入输出变量。tfdeploy.yaml:定义部署实例、环境参数、自动执行规则和跨资源栈数据传递。Terraform模块:实现具体云资源,由
tfcomponent.yaml中的component.source引用。
在自动化服务台创建资源栈前,先创建模板。模板中应包含tfcomponent.yaml和tfdeploy.yaml。如果component.source字段引用模板中的本地Terraform模块,模板中还需包含对应的模块目录。也可以通过脚手架项目初始化标准目录和配置。
核心设计
配置文件 | 职责 | 变更频率 |
| 定义系统架构,包括组件、组件依赖、Provider、输入变量和输出值 | 较低,通常在架构调整时修改 |
| 定义部署实例、不同环境的参数、自动执行规则和跨资源栈数据传递 | 较高,通常在新增环境或调整参数时修改 |
文件组织
以下目录以引用本地Terraform模块为例。modules/是示例目录,可以根据项目结构自定义;每个子目录对应一个Terraform模块。如果只引用Terraform Registry中的模块,则不需要modules/目录。
推荐使用以下目录结构:
my-project/
├── modules/ # 本地Terraform模块目录(名称可自定义)
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── vswitch/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── stacks/ # 资源栈工作目录
├── tfcomponent.yaml # Component配置
└── tfdeploy.yaml # Deployment配置创建资源栈时,需要指定资源栈工作目录。系统会在该目录下查找tfcomponent.yaml和tfdeploy.yaml。
以上述目录为例,工作目录填写:
stacks/如果两个配置文件位于模板根目录,工作目录填写:
/如果component.source字段引用模板中的本地Terraform模块,填写模块目录相对于资源栈工作目录的路径。以上述目录为例,资源栈工作目录为stacks/,模块位于modules/vpc/。从stacks/目录访问该模块需要返回上一级目录,因此配置如下:
source: "../modules/vpc"Stack Component 配置
tfcomponent.yaml用于定义资源栈的组件结构、Provider、输入变量和输出值。
配置项 | 必填 | 用途 |
| 是 | 声明配置文件格式版本 |
| 否 | 描述配置用途 |
| 否 | 声明输入变量 |
| 否 | 声明依赖的Provider及版本约束 |
| 否 | 配置Provider实例 |
| 是 | 定义基础设施组件 |
| 否 | 声明资源栈输出值 |
如果组件需要使用Provider,还需要配置required_providers、provider和组件的providers。
基础信息
format_version
format_version字段指定配置文件格式版本,格式为:
<POP Code>/<POP Version>当前使用以下版本:
format_version: IaCService/2021-08-06description
description字段用于描述当前Component配置的用途。
description: 创建VPC和VSwitch输入变量
variable
variable字段声明Component使用的输入变量。变量值可以通过以下方式提供:
在
variable.default中配置默认值。在
tfdeploy.yaml的deployment.inputs中配置。在
deployment.inputs中引用局部变量、参数集或上游资源栈输出。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 变量唯一标识,通过 |
| string | 是 | Terraform变量类型,例如 |
| string | 否 | 变量用途说明 |
| any | 否 | 默认值,Deployment未传入时使用 |
| bool | 否 | 是否按敏感变量处理,默认为 |
示例:
variable:
- name: region
type: string
description: 资源所属地域
- name: tags
type: map(string)
description: 资源标签
default:
managed_by: terraform
- name: token
type: string
description: 外部服务访问Token
sensitive: true将变量配置为sensitive: true,可以减少敏感值在控制台和执行日志中的暴露,但敏感值仍可能保存在Terraform状态文件中。限制状态文件的访问权限,不要将状态文件提交到公开代码仓库。
Provider 依赖
required_providers
required_providers字段声明资源栈依赖的Provider及其版本约束。
字段 | 类型 | 必填 | 说明 |
| string | 是 | Provider标识,例如 |
| string | 是 | Provider来源,例如 |
| string | 否 | Provider版本约束,例如 |
示例:
required_providers:
- name: alicloud
source: hashicorp/alicloud
version: "~> 1.251.0"provider
provider字段定义组件使用的Provider实例。
字段 | 类型 | 必填 | 说明 |
| string | 是 | Provider类型,对应 |
| string | 是 | Provider实例名称 |
| map | 否 | Provider配置,支持引用 |
通过以下格式引用Provider实例:
provider.<type>.<name>示例:
provider:
- type: alicloud
name: this
config:
region: var.region对应引用为:
provider.alicloud.this访问阿里云资源时,配置资源栈RAM Role,不要在配置文件或参数集中长期保存AccessKey。如果在provider.config字段中显式配置access_key和secret_key字段,Terraform Provider会优先使用该AK/SK,不会使用资源栈RAM Role注入的临时凭证。要统一执行身份,删除Provider中的AK/SK。
基础设施组件
component
component字段声明资源栈中的基础设施组件。每个组件引用一个Terraform模块。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 组件唯一标识,通过 |
| string | 是 | Terraform模块的相对路径或Registry地址 |
| string | 否 | Registry模块版本 |
| map | 否 | 传入模块的参数 |
| map | 是 | 组件使用的Provider实例 |
| string | 否 | 根据集合循环创建组件实例 |
| list(string) | 否 | 显式声明组件依赖关系 |
组件输出通过以下格式引用:
component.<组件名称>.<输出名称>示例:
component:
- name: vpc
source: "../modules/vpc"
inputs:
vpc_name: var.vpc_name
cidr_block: var.vpc_cidr
providers:
alicloud: provider.alicloud.thisinputs字段支持普通值、复杂数据结构和Terraform表达式:
普通字符串必须使用双引号,例如
"created by terraform"。var.*、component.*、each.value和Terraform函数等表达式不添加引号。包含Terraform字符串插值的值使用双引号,例如
"${var.name}-suffix"。
引用 Registry 模块
引用Registry模块时,可以同时指定source和version:
component:
- name: vpc
source: "alibaba/vpc/alicloud"
version: "1.11.0"
inputs:
cidr_block: var.vpc_cidr
providers:
alicloud: provider.alicloud.this显式声明组件依赖
当组件输入中已经引用其他组件的输出时,系统会根据引用关系建立依赖。对于无法通过输入引用表达的依赖,使用depends_on字段:
component:
- name: application
source: "../modules/application"
depends_on:
- component.vpc
providers:
alicloud: provider.alicloud.this如果inputs已引用另一个组件的输出,例如:
vpc_id: component.vpc.vpc_idTerraform会自动建立依赖,通常不需要再配置depends_on。
使用 for_each 创建多个组件实例
通过for_each字段,可以根据集合循环创建组件实例。
variable:
- name: bucket_names
type: set(string)
component:
- name: bucket
source: "../modules/oss_bucket"
for_each: var.bucket_names
inputs:
bucket_name: each.value
providers:
alicloud: provider.alicloud.this当bucket_names包含以下值时:
bucket_names:
- data-bucket
- log-bucket系统会创建两个组件实例。
使用for_each字段后,组件输出通常为按实例键组织的集合。引用输出时,根据Terraform模块实际生成的数据结构选择实例或遍历结果。
输出参数
output
output字段声明Component对外提供的输出值。tfdeploy.yaml可以通过publish_output字段发布这些值,供其他资源栈使用。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 输出唯一标识 |
| string | 否 | 输出值类型 |
| string | 否 | 输出用途说明 |
| string | 是 | 输出值,通常引用组件输出 |
示例:
output:
- name: vpc_id
type: string
description: VPC ID
value: component.vpc.vpc_id被引用的输出必须在对应Terraform模块的outputs.tf中真实存在。例如,使用component.vpc.vpc_id前,需要确保VPC模块已经声明名为vpc_id的Terraform Output。
Component 完整示例
format_version: IaCService/2021-08-06
description: 创建VPC和VSwitch
variable:
- name: region
type: string
- name: vpc_name
type: string
- name: vpc_cidr
type: string
- name: tags
type: map(string)
- name: zone_ids
type: list(string)
- name: vswitch_cidrs
type: list(string)
required_providers:
- name: alicloud
source: hashicorp/alicloud
version: "~> 1.251.0"
provider:
- type: alicloud
name: this
config:
region: var.region
component:
- name: vpc
source: "../modules/vpc"
inputs:
vpc_name: var.vpc_name
vpc_cidr: var.vpc_cidr
vpc_description: "created by terraform"
tags: merge(var.tags, { created_by = "tf" })
providers:
alicloud: provider.alicloud.this
- name: vswitch
source: "../modules/vswitch"
inputs:
vswitch_name: "${var.vpc_name}-vswitch"
vpc_id: component.vpc.vpc_id
vswitch_cidrs: var.vswitch_cidrs
zone_ids: var.zone_ids
providers:
alicloud: provider.alicloud.this
output:
- name: vpc_id
type: string
description: VPC ID
value: component.vpc.vpc_idStack Deployment 配置
tfdeploy.yaml定义部署实例、各环境的参数、自动执行规则、参数集引用和跨资源栈协作关系。
配置项 | 必填 | 用途 |
| 是 | 声明配置文件格式版本 |
| 否 | 描述配置用途 |
| 否 | 关联参数集,并在Deployment中引用参数 |
| 执行时必填 | 声明部署实例及环境参数 |
| 否 | 配置Terraform Plan后的自动执行规则 |
| 否 | 定义局部变量 |
| 否 | 向下游资源栈发布输出 |
| 否 | 引用上游资源栈发布的输出 |
执行资源栈时,必须在tfdeploy.yaml中通过deployment字段至少定义一个Deployment。
基础信息
format_version
与Component配置相同,当前使用:
format_version: IaCService/2021-08-06description
description字段用于描述当前Deployment配置的用途:
description: 创建开发和生产环境关联参数集
store
store字段用于引用自动化服务台中的参数集。配置后,可以在deployment.inputs字段中引用参数集中的参数,避免将密码、Token等敏感值直接写入配置文件或代码仓库。
使用store字段前,先在自动化服务台创建参数集,并将参数集关联到当前资源栈。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 存储类型,当前仅支持 |
| string | 是 | 参数集在当前配置文件中的引用名称 |
| string | 否 | 参数集名称,与 |
| string | 否 | 参数集ID,与 |
| string | 否 | 参数集类别,当前仅支持 |
如果同时配置id和name,系统优先使用id查找参数集。
参数集引用格式为:
store.<type>.<store_name>.<参数名>示例:
store:
- type: varset
store_name: tokens
id: pts-xxxx
category: terraform
deployment:
- name: production
inputs:
token: store.varset.tokens.example_token上述配置引用参数集pts-xxxx中名为example_token的参数,并将其传入Component变量token。
声明store字段只会建立参数集引用,不会将参数集中的全部参数自动传入Terraform。只有在deployment.inputs字段中显式引用的参数才会传入对应的Deployment。
如果引用参数集中的敏感参数,tfcomponent.yaml中接收该参数的变量必须配置sensitive: true:
variable:
- name: token
type: string
sensitive: true如果敏感参数对应的变量未配置sensitive: true,资源栈配置校验或执行将失败。
使用store字段时存在以下限制:
参数集必须已经关联到当前资源栈。
当前仅支持
varset类型。category当前仅支持terraform。name和id至少配置一项。参数集不存在、未关联或敏感属性配置不一致时,资源栈执行将失败。
部署实例
deployment
deployment字段声明部署实例。每条Deployment配置对应一组独立的部署参数,例如开发环境和生产环境。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 部署实例名称,例如 |
| map | 否 | 为 |
示例:
deployment:
- name: development
inputs:
region: "cn-hangzhou"
vpc_name: "vpc-dev"
- name: production
inputs:
region: "cn-beijing"
vpc_name: "vpc-prod"同一个资源栈中的不同Deployment会分别创建和维护Terraform任务及状态。根据实际隔离需求划分Deployment。
自动执行控制
orchestrate
orchestrate字段用于控制Terraform Plan完成后是否自动执行Apply。
未配置orchestrate时,资源栈只执行Terraform Plan,并在Plan完成后等待人工确认,不会自动执行Apply。
当前仅支持auto_approve类型。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 规则类型,当前仅支持 |
| string | 是 | 规则唯一标识 |
| list(object) | 是 | 自动执行条件列表 |
check对象包含以下字段:
字段 | 类型 | 必填 | 说明 |
| expression | 是 | 自动执行条件 |
| string | 否 | 条件不成立时的提示原因 |
系统会检查auto_approve下的全部条件:
所有条件均成立:Plan完成后自动执行Apply。
任一条件不成立:Plan完成后等待人工确认。
未配置
orchestrate:Plan完成后等待人工确认。
示例:当VPC组件没有变更时自动执行Apply;如果VPC组件存在变更,则等待人工确认。
orchestrate:
- type: auto_approve
name: safe_changes_only
check:
- condition: 'context.plan.component_changes["component.vpc"].total == 0'
reason: "VPC组件存在变更,需要人工确认。"自动执行规则不会绕过资源保护策略和其他安全检查。如果变更触发资源保护策略,即使条件成立,任务也可能被拒绝执行。
局部变量
locals
locals字段用于定义tfdeploy.yaml中重复使用的值。
locals:
common_region: "cn-hangzhou"
default_tags:
managed_by: "terraform"在deployment.inputs中通过local.<name>引用:
deployment:
- name: development
inputs:
region: local.common_region
tags: local.default_tags当前局部变量主要用于值传递。不要在locals字段中嵌套复杂引用或Terraform函数。
跨资源栈协作
资源栈可以通过publish_output字段发布输出,通过upstream_input字段引用其他资源栈发布的输出。
发布资源栈输出
publish_output字段声明当前资源栈向下游资源栈发布的输出。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 发布输出名称 |
| string | 否 | 输出用途说明 |
| any | 是 | 输出值,格式通常为 |
示例:
publish_output:
- name: vpc_id
description: 生产环境VPC ID
value: deployment.production.vpc_id其中:
production是deployment.name。vpc_id是tfcomponent.yaml中声明的output.name。
引用上游资源栈输出
upstream_input字段声明需要引用的上游资源栈。
字段 | 类型 | 必填 | 说明 |
| string | 是 | 当前配置中的引用名称 |
| string | 是 | 来源类型,当前仅支持 |
| string | 是 | 上游资源栈标识 |
source格式为:
{IaCEndpoint}/{AccountId}/{StackName}在deployment.inputs中通过以下格式引用输出:
upstream_input.<name>.<output>跨资源栈示例
上游网络资源栈发布生产环境VPC ID:
publish_output:
- name: vpc_id
description: 生产环境VPC ID
value: deployment.production.vpc_id下游应用资源栈声明并引用该输出:
upstream_input:
- name: network_stack
type: stack
source: "{IaCEndpoint}/{AccountId}/{NetworkStackName}"
deployment:
- name: production
inputs:
region: "cn-hangzhou"
vpc_id: upstream_input.network_stack.vpc_id执行下游资源栈时,系统会读取上游资源栈当前已经发布的输出值,无需在配置中硬编码资源ID。
使用跨资源栈输出时需注意:
上游资源栈必须存在,并且已经成功部署。
上游资源栈必须已经通过
publish_output发布对应名称的输出。跨账号引用前,上游资源栈所属账号必须在资源栈详情页的账户授权中,将下游阿里云账号 UID 添加为授权账号。具体操作请参见《创建和管理资源栈》中的“授权其他账号引用资源栈输出”。
upstream_input只有在deployment.inputs中被实际引用时,才会建立对应的消费关系。上游发布输出发生变化后,系统会触发存在消费关系的下游资源栈执行Plan。
自动触发下游Plan不代表一定自动执行Apply。是否自动Apply仍由下游资源栈的
orchestrate配置决定。当前自动触发以资源栈为粒度,可能执行下游资源栈中的全部Deployment,而不仅是引用该输出的单个Deployment。
Deployment 完整示例
format_version: IaCService/2021-08-06
description: 创建开发和生产环境
deployment:
- name: development
inputs:
region: "cn-hangzhou"
vpc_name: "vpc-dev"
vpc_cidr: "192.168.0.0/16"
tags:
environment: "development"
zone_ids:
- "cn-hangzhou-j"
- "cn-hangzhou-k"
vswitch_cidrs:
- "192.168.1.0/24"
- "192.168.2.0/24"
- name: production
inputs:
region: "cn-beijing"
vpc_name: "vpc-prod"
vpc_cidr: "172.16.0.0/16"
tags:
environment: "production"
zone_ids:
- "cn-beijing-l"
- "cn-beijing-k"
vswitch_cidrs:
- "172.16.1.0/24"
- "172.16.2.0/24"
orchestrate:
- type: auto_approve
name: no_vpc_changes
check:
- condition: 'context.plan.component_changes["component.vpc"].total == 0'
reason: "VPC组件存在变更,需要人工确认。"
publish_output:
- name: prod_vpc_id
description: 生产环境VPC ID
value: deployment.production.vpc_id表达式语法
不同表达式只能在对应的配置位置使用。
Component 表达式
以下表达式主要用于tfcomponent.yaml:
表达式 | 示例 | 说明 |
|
| 引用 |
|
| 引用其他组件的输出,并建立依赖 |
|
| 引用Provider实例 |
|
| 引用 |
Terraform函数 |
| 调用Terraform内置函数 |
字符串插值 |
| 在字符串中插入Terraform表达式 |
Terraform函数直接使用Terraform HCL表达式格式,不需要添加{{ }}。
正确示例:
tags: merge(var.tags, { created_by = "tf" })错误示例:
tags: '{{ merge(var.tags, { created_by = "tf" }) }}'Deployment 表达式
以下表达式主要用于tfdeploy.yaml:
表达式 | 使用位置 | 说明 |
|
| 引用 |
|
| 引用参数集中的参数 |
|
| 引用上游资源栈输出 |
|
| 发布指定Deployment的输出 |
|
| 当前Deployment名称 |
|
| Plan的整体变更统计 |
|
| 指定组件的变更统计 |
context.plan.changes和component_changes支持以下统计字段:
addchangeimportremovetotal
条件表达式支持以下比较运算符:
==
!=
>
<
>=
<=支持以下逻辑运算符:
&&
||示例:
orchestrate:
- type: auto_approve
name: development_safe_changes
check:
- condition: 'context.plan.deployment == "development" && context.plan.changes.remove == 0'
reason: "当前变更不满足开发环境自动执行条件。"上线前检查
将资源栈配置用于实际环境前,完成以下检查:
检查工作目录中是否同时存在
tfcomponent.yaml和tfdeploy.yaml。检查
component.source字段中的本地模块路径是否以资源栈工作目录为起点。检查Registry模块地址和版本是否正确。
检查Component引用的模块输入和输出是否真实存在。
检查每个Deployment是否为必填变量提供了值。
检查参数集是否已经关联到资源栈。
检查敏感参数对应的Component变量是否配置
sensitive: true。检查跨账号资源栈引用是否已经获得共享授权。
执行Terraform Plan,确认资源新增、修改和删除范围。
确认Plan结果符合预期后,再人工确认Apply或配置自动执行规则。
常见问题
以下问题按照配置和执行阶段分类。