资源栈配置说明

更新时间:
复制 MD 格式

当同一套基础设施需要部署到多个环境时,逐环境维护独立配置容易产生差异。资源栈通过两份 YAML 配置文件统一定义组件结构、环境参数和执行规则,并结合 Terraform 模块完成基础设施交付。

资源栈包含以下内容:

  • tfcomponent.yaml:定义基础设施组件、组件依赖、Provider和输入输出变量。

  • tfdeploy.yaml:定义部署实例、环境参数、自动执行规则和跨资源栈数据传递。

  • Terraform模块:实现具体云资源,由tfcomponent.yaml中的component.source引用。

在自动化服务台创建资源栈前,先创建模板。模板中应包含tfcomponent.yamltfdeploy.yaml。如果component.source字段引用模板中的本地Terraform模块,模板中还需包含对应的模块目录。也可以通过脚手架项目初始化标准目录和配置。

核心设计

配置文件

职责

变更频率

tfcomponent.yaml

定义系统架构,包括组件、组件依赖、Provider、输入变量和输出值

较低,通常在架构调整时修改

tfdeploy.yaml

定义部署实例、不同环境的参数、自动执行规则和跨资源栈数据传递

较高,通常在新增环境或调整参数时修改

文件组织

以下目录以引用本地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.yamltfdeploy.yaml

以上述目录为例,工作目录填写:

stacks/

如果两个配置文件位于模板根目录,工作目录填写:

/

如果component.source字段引用模板中的本地Terraform模块,填写模块目录相对于资源栈工作目录的路径。以上述目录为例,资源栈工作目录为stacks/,模块位于modules/vpc/。从stacks/目录访问该模块需要返回上一级目录,因此配置如下:

source: "../modules/vpc"

Stack Component 配置

tfcomponent.yaml用于定义资源栈的组件结构、Provider、输入变量和输出值。

配置项

必填

用途

format_version

声明配置文件格式版本

description

描述配置用途

variable

声明输入变量

required_providers

声明依赖的Provider及版本约束

provider

配置Provider实例

component

定义基础设施组件

output

声明资源栈输出值

如果组件需要使用Provider,还需要配置required_providersprovider和组件的providers

基础信息

format_version

format_version字段指定配置文件格式版本,格式为:

<POP Code>/<POP Version>

当前使用以下版本:

format_version: IaCService/2021-08-06

description

description字段用于描述当前Component配置的用途。

description: 创建VPC和VSwitch

输入变量

variable

variable字段声明Component使用的输入变量。变量值可以通过以下方式提供:

  • variable.default中配置默认值。

  • tfdeploy.yamldeployment.inputs中配置。

  • deployment.inputs中引用局部变量、参数集或上游资源栈输出。

字段

类型

必填

说明

name

string

变量唯一标识,通过var.<name>引用

type

string

Terraform变量类型,例如stringlist(string)map(string)

description

string

变量用途说明

default

any

默认值,Deployment未传入时使用

sensitive

bool

是否按敏感变量处理,默认为false

示例:

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及其版本约束。

字段

类型

必填

说明

name

string

Provider标识,例如alicloud

source

string

Provider来源,例如hashicorp/alicloud

version

string

Provider版本约束,例如~> 1.251.0

示例:

required_providers:
  - name: alicloud
    source: hashicorp/alicloud
    version: "~> 1.251.0"

provider

provider字段定义组件使用的Provider实例。

字段

类型

必填

说明

type

string

Provider类型,对应required_providers.name

name

string

Provider实例名称

config

map

Provider配置,支持引用var.*

通过以下格式引用Provider实例:

provider.<type>.<name>

示例:

provider:
  - type: alicloud
    name: this
    config:
      region: var.region

对应引用为:

provider.alicloud.this
重要

访问阿里云资源时,配置资源栈RAM Role,不要在配置文件或参数集中长期保存AccessKey。如果在provider.config字段中显式配置access_keysecret_key字段,Terraform Provider会优先使用该AK/SK,不会使用资源栈RAM Role注入的临时凭证。要统一执行身份,删除Provider中的AK/SK。

基础设施组件

component

component字段声明资源栈中的基础设施组件。每个组件引用一个Terraform模块。

字段

类型

必填

说明

name

string

组件唯一标识,通过component.<name>.<output>引用输出

source

string

Terraform模块的相对路径或Registry地址

version

string

Registry模块版本

inputs

map

传入模块的参数

providers

map

组件使用的Provider实例

for_each

string

根据集合循环创建组件实例

depends_on

list(string)

显式声明组件依赖关系

组件输出通过以下格式引用:

component.<组件名称>.<输出名称>

示例:

component:
  - name: vpc
    source: "../modules/vpc"
    inputs:
      vpc_name: var.vpc_name
      cidr_block: var.vpc_cidr
    providers:
      alicloud: provider.alicloud.this

inputs字段支持普通值、复杂数据结构和Terraform表达式:

  • 普通字符串必须使用双引号,例如"created by terraform"

  • var.*component.*each.valueTerraform函数等表达式不添加引号。

  • 包含Terraform字符串插值的值使用双引号,例如"${var.name}-suffix"

引用 Registry 模块

引用Registry模块时,可以同时指定sourceversion

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_id

Terraform会自动建立依赖,通常不需要再配置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字段发布这些值,供其他资源栈使用。

字段

类型

必填

说明

name

string

输出唯一标识

type

string

输出值类型

description

string

输出用途说明

value

string

输出值,通常引用组件输出

示例:

output:
  - name: vpc_id
    type: string
    description: VPC ID
    value: component.vpc.vpc_id

被引用的输出必须在对应Terraform模块的outputs.tf中真实存在。例如,使用component.vpc.vpc_id前,需要确保VPC模块已经声明名为vpc_idTerraform 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_id

Stack Deployment 配置

tfdeploy.yaml定义部署实例、各环境的参数、自动执行规则、参数集引用和跨资源栈协作关系。

配置项

必填

用途

format_version

声明配置文件格式版本

description

描述配置用途

store

关联参数集,并在Deployment中引用参数

deployment

执行时必填

声明部署实例及环境参数

orchestrate

配置Terraform Plan后的自动执行规则

locals

定义局部变量

publish_output

向下游资源栈发布输出

upstream_input

引用上游资源栈发布的输出

执行资源栈时,必须在tfdeploy.yaml中通过deployment字段至少定义一个Deployment。

基础信息

format_version

Component配置相同,当前使用:

format_version: IaCService/2021-08-06

description

description字段用于描述当前Deployment配置的用途:

description: 创建开发和生产环境

关联参数集

store

store字段用于引用自动化服务台中的参数集。配置后,可以在deployment.inputs字段中引用参数集中的参数,避免将密码、Token等敏感值直接写入配置文件或代码仓库。

使用store字段前,先在自动化服务台创建参数集,并将参数集关联到当前资源栈。

字段

类型

必填

说明

type

string

存储类型,当前仅支持varset

store_name

string

参数集在当前配置文件中的引用名称

name

string

参数集名称,与id至少配置一项

id

string

参数集ID,与name至少配置一项

category

string

参数集类别,当前仅支持terraform

如果同时配置idname,系统优先使用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

  • nameid至少配置一项。

  • 参数集不存在、未关联或敏感属性配置不一致时,资源栈执行将失败。

部署实例

deployment

deployment字段声明部署实例。每条Deployment配置对应一组独立的部署参数,例如开发环境和生产环境。

字段

类型

必填

说明

name

string

部署实例名称,例如developmentproduction

inputs

map

tfcomponent.yaml中声明的变量赋值

示例:

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类型。

字段

类型

必填

说明

type

string

规则类型,当前仅支持auto_approve

name

string

规则唯一标识

check

list(object)

自动执行条件列表

check对象包含以下字段:

字段

类型

必填

说明

condition

expression

自动执行条件

reason

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字段声明当前资源栈向下游资源栈发布的输出。

字段

类型

必填

说明

name

string

发布输出名称

description

string

输出用途说明

value

any

输出值,格式通常为deployment.<name>.<output>

示例:

publish_output:
  - name: vpc_id
    description: 生产环境VPC ID
    value: deployment.production.vpc_id

其中:

  • productiondeployment.name

  • vpc_idtfcomponent.yaml中声明的output.name

引用上游资源栈输出

upstream_input字段声明需要引用的上游资源栈。

字段

类型

必填

说明

name

string

当前配置中的引用名称

type

string

来源类型,当前仅支持stack

source

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

表达式

示例

说明

var.<name>

var.region

引用variable声明的变量

component.<name>.<output>

component.vpc.vpc_id

引用其他组件的输出,并建立依赖

provider.<type>.<name>

provider.alicloud.this

引用Provider实例

each.value

each.value

引用for_each当前实例的值

Terraform函数

merge(var.tags, { created_by = "tf" })

调用Terraform内置函数

字符串插值

"${var.vpc_name}-vswitch"

在字符串中插入Terraform表达式

Terraform函数直接使用Terraform HCL表达式格式,不需要添加{{ }}

正确示例:

tags: merge(var.tags, { created_by = "tf" })

错误示例:

tags: '{{ merge(var.tags, { created_by = "tf" }) }}'

Deployment 表达式

以下表达式主要用于tfdeploy.yaml

表达式

使用位置

说明

local.<name>

deployment.inputs

引用locals中的值

store.<type>.<store_name>.<参数名>

deployment.inputs

引用参数集中的参数

upstream_input.<name>.<output>

deployment.inputs

引用上游资源栈输出

deployment.<name>.<output>

publish_output.value

发布指定Deployment的输出

context.plan.deployment

orchestrate.check.condition

当前Deployment名称

context.plan.changes.*

orchestrate.check.condition

Plan的整体变更统计

context.plan.component_changes["<组件>"].*

orchestrate.check.condition

指定组件的变更统计

context.plan.changescomponent_changes支持以下统计字段:

  • add

  • change

  • import

  • remove

  • total

条件表达式支持以下比较运算符:

==
!=
>
<
>=
<=

支持以下逻辑运算符:

&&
||

示例:

orchestrate:
  - type: auto_approve
    name: development_safe_changes
    check:
      - condition: 'context.plan.deployment == "development" && context.plan.changes.remove == 0'
        reason: "当前变更不满足开发环境自动执行条件。"

上线前检查

将资源栈配置用于实际环境前,完成以下检查:

  1. 检查工作目录中是否同时存在tfcomponent.yamltfdeploy.yaml

  2. 检查component.source字段中的本地模块路径是否以资源栈工作目录为起点。

  3. 检查Registry模块地址和版本是否正确。

  4. 检查Component引用的模块输入和输出是否真实存在。

  5. 检查每个Deployment是否为必填变量提供了值。

  6. 检查参数集是否已经关联到资源栈。

  7. 检查敏感参数对应的Component变量是否配置sensitive: true

  8. 检查跨账号资源栈引用是否已经获得共享授权。

  9. 执行Terraform Plan,确认资源新增、修改和删除范围。

  10. 确认Plan结果符合预期后,再人工确认Apply或配置自动执行规则。

常见问题

以下问题按照配置和执行阶段分类。

配置资源栈

component.source 字段可以指向哪些地址?

component.source字段可以配置以下地址:

  • 相对于资源栈工作目录的本地模块路径:

    source: "../modules/vpc"
  • Terraform Registry模块地址:

    source: "alibaba/vpc/alicloud"
    version: "1.11.0"

引用本地模块时,确保模块目录包含完整的Terraform文件,并且声明了Component所引用的输入变量和输出。

如何引用参数集中的参数?

在自动化服务台左侧导航栏选择参数集 > 参数集管理,创建参数集并获取参数集ID或名称,然后将该参数集关联到目标资源栈。

tfdeploy.yaml中声明参数集:

store:
  - type: varset
    store_name: tokens
    id: pts-xxxx
    category: terraform

随后,在deployment.inputs中显式引用需要使用的参数:

deployment:
  - name: production
    inputs:
      token: store.varset.tokens.example_token

配置store字段不会自动注入参数集中的全部参数。只有被deployment.inputs字段显式引用的参数才会传入Terraform。

如果引用的是敏感参数,tfcomponent.yaml中对应的变量必须配置sensitive: true

可以在参数集中保存 AccessKey 吗?

不要在参数集中长期保存AccessKey。执行Terraform时,优先使用资源栈RAM Role。

参数集适合保存应用密码、Token或其他需要在Deployment中引用的配置参数。

执行资源栈

不配置 orchestrate 字段时如何处理变更?

未配置orchestrate时,资源栈执行Terraform Plan后等待人工确认,不会自动执行Apply。

配置auto_approve后:

  • 全部condition均成立时,自动执行Apply。

  • 任一condition不成立时,等待人工确认。

为什么配置了 auto_approve,任务仍未自动执行?

可能原因包括:

  • check.condition不成立。

  • 条件表达式格式不正确,无法完成计算。

  • 变更触发了资源保护策略。

  • 任务配置了其他事前检查,且检查尚未通过。

  • Terraform Plan执行失败。

  • 任务缺少必要的权限或执行身份。

进入任务详情页,查看Plan结果和执行日志。

为什么找不到上游资源栈?

按以下顺序检查:

  • upstream_input.source是否符合{IaCEndpoint}/{AccountId}/{StackName}格式。

  • 上游资源栈名称和账号ID是否正确。

  • 上游资源栈是否已经成功部署。

  • 上游资源栈是否已经发布对应的publish_output

  • 跨账号引用时,是否已经完成资源栈共享授权。

上游输出变化后,下游是否自动执行?

上游发布输出发生变化后,系统会触发存在消费关系且满足运行条件的下游资源栈执行Terraform Plan。

下游是否继续自动执行Apply,取决于下游资源栈的orchestrate配置:

  • 未配置orchestrate:Plan后等待人工确认。

  • auto_approve条件全部成立:自动执行Apply。

  • 任一条件不成立:等待人工确认。

为什么 Component 输出引用在执行时失败?

检查被引用的Terraform模块是否声明了对应输出。

例如,配置中使用:

value: component.vpc.vpc_id

VPC模块的outputs.tf中必须包含:

output "vpc_id" {
  value = alicloud_vpc.this.id
}

配置文件的静态检查不一定能提前发现模块缺少输出的问题,因此在发布模板前执行Terraform Plan。