基础架构部文档
基础架构部文件格式标准参考
技术文档
mr_doc 接入ucenter 认证登录
loki日志收集
https证书与ssl/tls 加密
FTP 主动模式和被动模式的区别
Hadoop-windows10安装部署Hadoop2.7.3
JKS和PFX证书文件格式相互转换方法
KVM 基础操作
k8s nginx ingress日志收集到ELK并分析
Django基础
clash http代理 socks代理服务器搭建 配置
Ubuntu 22.04 安装 FFmpeg v7.0
ORM
AI MCP 介绍
Django 模板
ZooKeeper命令行(zkCli)的常用操作
Office正版化项目的个人体验和心得
重置jenkins构建历史
K8S实施方案
k8s的yaml文件语法
Docker的优势与虚拟机的区别
问题处理文档
HR推送数据问题处理报
Nginx从入门到放弃01-nginx基础安装
Nginx从入门到放弃02-Nginx基本命令和新建WEB站点
Nginx从入门到放弃03-Nginx调优
Nginx从入门到放弃04-Nginx的N种特别实用示例
JMeter教程
01-mariadb编译安装
02-mariadb二进制安装
Docker修改默认的存储路径
01-influxdb2时序数据库简介及安装
02-influxdb2时序数据库核心概念
03-influxdb2时序数据库flux查询语言
04-influxdb2--Python客户端influxdb-client
05-Spring boot 集成influxdb2
06-influxdb2其他知识
OA添加waf后相关问题的解决过程
排除java应用cpu使用率过高
exsi迁移文档
视频测试
阿里云产品试题
超融合服务器和传统服务器的区别
Serv-U问题集锦
文件夹共享操作手册
磁盘脱机处理方案
Office内存或磁盘空间不足处理方法
Cmd中ping不是内部或外部命令的解决方法
ELK 搭建文档
限制用户的远程桌面会话数量
Docker快速安装rocketmq、redis、zookeeper
超融合建设方案
git 入门
HR系统写入ES数据报错403
ELK搭建文档
KVM 安装和基础使用文档
helm 安装 rancher
访问共享提示禁用当前用户解决方法
K8S StorageClass搭建
KVM 扩展磁盘
借助sasl构建基于AD用户验证的SVN服务器
fastdfs编译安装并迁移数据
关闭系统保护的必要性
SCF 前置机部署
阿里云OSS学习文档
阿里云学习文档-VPC
(k8s踩坑)namespace无法删除
rancher-helm安装
zookeeper集群安装
批量替换K8s secrets 中某个特定域名的tls证书
kibana 批量创建索引模式
centos7 恢复Yum使用
ACP云计算部分知识点总结
Loki 日志系统搭建文档
自动更新k8s集群中所有名称空间中特定证书
AI分享
(AI)函数调用与MCP调用的区别
安装戴尔DELL Optilex 7040 USB驱动时提示无法定位程序输入点 kernel32\.dll
新华三服务器EXSI 显卡直通
conda
双流本地k8s搭建
通义灵码介绍
ELK高亮显示字段过大的问题
LInux常用工具
Ollama部署本地deepseek
人工智能如何重塑ACG宇宙
网络基础协议
远程桌面忽略本地机的文本缩放设置
ComfyUI :构建可视化 Stable Diffusion 工作流
Clawdbot介绍
Dify:开启AI应用开发的“乐高时代”
Kubernetes 证书过期处理
Openclaw安装
Openclaw介绍
zk高可用集群安装
AI代码审计
IaC学习
本文档使用「觅思文档专业版」发布
-
+
首页
IaC学习
# IaC **基础设施即代码** (Infrastructure as Code,IaC)通过代码定义、部署和管理基础设施,替代手动操作,实现自动化、可重复的基础设施交付。 ## **IaC工作原理** 主流 IaC 工具以配置文件描述基础设施,根据文件中的资源描述,通过 API 与云服务交互,自动创建和配置资源。 IaC 的基本工作流程如下: 1. **定义基础设施**:使用配置语言或编程语言编写配置文件,描述所需的资源及其依赖关系。 2. **自动化部署**:IaC 工具根据配置文件,通过云服务 API 自动创建和配置资源。 3. **变更管理**:配置文件变更时,工具自动识别差异,增量更新基础设施以保持与配置一致。 **IaC的优势** - **复用性**:同一份配置文件可持续创建和管理多个环境(开发、测试、生产等),确保环境一致性。 - **自动化**:自动化创建和管理云资源,可集成到 CI/CD 流水线实现持续交付。 - **流程化**:配置文件的修改经过代码审查和自动验证,以变更管理的方式处理基础设施更改。 - **可审计**:配置文件纳入版本控制,保留完整的变更历史,支持审计和回滚。 ## 阿里云支持的IaC工具  ## Terraform Terraform 是 HashiCorp 开源的声明式 IaC 工具。声明式”意味着只需在配置文件中描述资源的期望状态(例如“一台 2 核 4G 的 ECS 实例,位于华东 1 地域”),Terraform 自动处理 API 调用、依赖关系和执行顺序。 与控制台操作的区别:  Terraform 将基础设施管理从“手动操作”变为“编写和维护代码”,适合管理多个资源、多套环境或需要团队协作的场景。如果只是临时创建少量资源,控制台操作更直接。 ## **Terraform 如何管理资源**  整个过程分为三步: 1. **编写**:在配置文件中描述云资源及其属性,例如 ECS 的规格、镜像、所属网络等。 2. **预览**:Terraform 对比配置文件与实际资源状态,生成变更计划,列出将要创建、修改或删除的资源。资源发生实际变化之前,可以先审查这份计划。 3. **执行**:确认计划无误后,Terraform 通过阿里云 OpenAPI 自动完成所有操作,并记录资源的最新状态。 后续每次修改配置文件并重新执行时,Terraform 只处理差异部分——新增的资源创建、变更的属性更新、移除的资源销毁,未变更的资源不受影响。 ## **使用 Terraform 的优势** - **执行前可预览**:每次执行前,Terraform 生成变更计划,列出将要创建、修改或删除的资源,避免意外变更。 - **增量更新**:只处理发生变化的部分,不重建未变更的资源。 - **多云统一管理**:支持多个云平台的 Provider,可在同一套工作流中管理阿里云、AWS 等不同平台的资源。 - **模块化复用**:将常用的资源组合(如 VPC + 子网 + 安全组)封装为模块,在不同项目和环境中复用。 - **状态持续追踪**:通过状态文件持续记录每个资源与实际云资源的对应关系,确保管理的一致性。 **Terraform 操作对已有云资源有什么影响?** Terraform 只管理配置文件中定义的资源,不影响未纳入管理的已有资源。需要注意的是,Terraform 执行的创建、修改、删除操作直接作用于真实云资源,执行前建议审查变更计划。 **已经在控制台创建的资源能纳入 Terraform 管理吗?** 可以。通过 `import` 功能将已有资源导入 Terraform 管理范围,导入后编写对应的配置文件描述这些资源,即可通过 Terraform 统一管理。 **通过 Terraform 管理的资源还能在控制台操作吗?** 技术上可以,但不推荐。Terraform 通过状态文件追踪资源状态,在控制台手动修改会导致状态文件与实际状态不一致,下次执行时可能覆盖手动修改或产生冲突。建议 Terraform 管理的资源统一通过 Terraform 操作。 使用terraform的两种方式:  ## Terraform安装 ```powershell yum install -y dnf-plugin-releasever-adapter yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo yum install terraform ``` ### 配置环境变量 ``` export ALICLOUD_ACCESS_KEY="LTAI5t8XfEVVwS4MpjJRBQGp" export ALICLOUD_SECRET_KEY="pNeHke8Mj9WjeUc1za05L9oOYiDACh" export ALICLOUD_REGION="cn-wulanchabu" ``` ### terraform初始化 防止初始化失败,使用国内的镜像源 ``` # ~/.terraformrc plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" provider_installation { network_mirror { # 指定国内镜像源 url = "https://mirrors.aliyun.com/terraform/" # 包含你需要用到的 provider 地址 include = ["registry.terraform.io/hashicorp/*", "registry.terraform.io/aliyun/*"] } direct { # 其他 provider 仍从官方源下载,可按需配置 exclude = ["registry.terraform.io/hashicorp/*", "registry.terraform.io/aliyun/*"] } } ``` terraform初始化 ``` terraform init ``` ### 查看相关资源 ``` terraform plan ```  ### 执行变更 ``` terraform plan ```  ### 查看创建的资源 ``` terraform show ```  ### 列出所有已创建的资源 ``` terraform state list ```  ### 查看某个资源的详细信息 ``` terraform state show <资源类型>.<资源名称> ```  ## terraform目录 Terraform 工作流程包括模板编写、初始化、预览、执行四部分。  - **根模块** 根模块也被称为根配置文件,是运行 Terraform 命令的工作目录。在该目录中,Terraform 将寻找所有 .tf 文件,并使用它们来创建执行计划。您可以在单个根配置文件中编写所有的资源和其他代码结构(如入参变量,出参定义,提供商等),但最佳实践是按照逻辑将资源拆分到不同的配置文件中。 - **子模块** 子模块是可选的,每个子模块可以是出于对某类复用功能的抽象,也可以是出于对根模块复杂逻辑的简化。根模块通过对子模块的引用来降低根模块的编写复杂度,提升复用性和可读性。 ## HCL语法 ``` <Block Type> "<Block Label>" "‹Block Label>" ( # Block Body <Identifier> = <Value/Expression> # Argument } resource "alicloud_vpc" "myvpc" { vpc_name = "the-first-vpc" cidr_block = "172.16.0.0/12" } ``` - **块(Block)** 块是一系列属于某种类型的代码行,比如资源(resource)、变量(variable)、输出(output)、模块(module)等。块可以是简单的类型,也可以是嵌套另一种块类型的复杂类型。 - **参数(Argument)** 参数是块的一部分,用于给名称分配值。块包含必填的参数和可选的参数。 - **标识符(Identifier)** 标识符是参数、块类型或任何 Terraform 特定结构的名称。标识符可以包括字母、下划线、连字符和数字,但不能以数字开头。 - **表达式(Expression)** 可以用来在代码块中给标识符分配一个值。这些表达式可以是简单类型的值,如字符串,数字等,也可以是复杂类型的值,如对象,数组,Map 等。 - **注释** 注释以`#`开始和结束,用于单行注释。除此之外,`//`也用于单行注释,`/*`和`*/`用于多行注释。 值得注意的是,HCL 本质上是声明式的,意味着模板中定义的块代表了基础设施的最终状态。因此,块或文件的顺序并不重要。 ## 基本术语 资源、提供商、变量、输出、状态、模块 ### **资源(Resources)** 资源(Resources)是定义基础设施组件的代码块,通常定义在 main.tf 文件中。资源通过关键字 resource 来标识,之后是具体的资源类型和自定义名称。资源类型取决于您在配置文件中定义的提供商(Provider)。在花括号内是指定资源类型的参数。 ```terraform resource "resource_type" "resource_name" { # resource_name 必须唯一,且不能是terraform的关键字 # 指定资源类型的参数(Argument) } ``` ### **提供商(Provider)** 提供商实现了每一种可配置的资源类型;如果没有提供商,Terraform 将无法管理任何类型的基础设施。提供商通常定义在 providers.tf 文件中,您需要指定包含提供商定义的 Terraform 块。当声明了提供商后,Terraform 通过 init 命令自动下载提供商插件。 ```terraform terraform { required_providers { alicloud = { source = "hashicorp/alicloud" version = "1.277.0" # 如果未指定版本,将在初始化期间下载最新的版本 } } } provider "alicloud" { # 配置你的阿里云凭据和地域信息 # 出于安全考虑,建议不要在这个文件中直接包含你的阿里云AccessKey和SecretKey,推荐使用环境变量或其它安全方式设置凭据: # export ALICLOUD_ACCESS_KEY="<你的阿里云Access Key>" # export ALICLOUD_SECRET_KEY="<你的阿里云Secret Key>" region = "cn-wulanchabu" } ``` 提供商将具体的管理资源的 API 编排为 Terraform 资源,并管理资源与 API 之间的交互。由于历史原因,阿里云提供商 alicloud 支持两个 source 值:aliyun/alicloud 和 hashicorp/alicloud。两者的实现完全一致。 access_key,secret_key,region 等参数是专用于配置阿里云 Provider 的。如果 Terraform 配置中没有包含 provider 块,Terraform 会假定一个空的默认配置,并且 access_key,secret_key,region 默认会从环境变量中获取。如果环境变量中没有指定 region,默认将使用 cn-beijing。 ### **变量(Variables)** 在无需更改源配置代码的情况下轻松定制和共享配置。一旦定义了变量,在 Terraform 运行时可以有多种不同的方式来设置其值:环境变量、CLI 参数、键值文件等。建议单独使用variables.tf来定义变量,使用my-vars.tfvars来自定义变量值。  #### **type** type 参数指定了变量接受的值的类型。Terraform 支持以下基本变量类型: - **bool**,用于二进制值,如 true 或 false(不带引号) - **number**,用于数值变量 - **string**,用于字符序列 #### **default** default 是变量的另一个元参数,用于给属性分配默认值。 要访问模块内声明的变量值,可以使用表达式 `var.`。 ```go resource "alicloud_vpc" "my_vpc" { vpc_name = "main-vpc" cidr_block = var.vpc_cidr_block description = "" } variable "vpc_cidr_block" { default = "10.0.0.0/16" } ``` #### **description** description 用于记录变量的用途。当变量没有定义默认值时,描述将在 plan 或者 apply 阶段显示:  description 字符串通常包含在文档中,应当解释变量的用途和预期值。因此应从用户使用视角而非维护者的角度去编写。维护者可以使用注释,而非直接写到 description 中。 #### **sensitive** sensitive 是一个变量参数,顾名思义,用于保护敏感信息不会显示在命令输出或日志文件中。敏感值的可接受值为true。当设置为true时,变量的值在 terraform plan 或terraform apply 的输出中标记为敏感。 #### **validation** 验证块包含一个条件参数,用于指定验证规则。你可以通过在变量块中包含验证子块来验证赋给变量的值。 ```go variable "vpc_name" { validation { condition = length(var.vpc_name) > 4 && substr(var.vpc_name, 0, 3) == "tf-" error_message = "The vpc name must start with 'tf-' and be longer than 4 characters." } } ``` #### **变量的设置方式** ```shell # .tfvars 文件(推荐) $ terraform apply -var-file my-vars.tfvars # CLI 选项 $ terraform apply -var vpc_cidr_block=“172.16.0.0/16” # 环境变量 $ export TF_VAR_vpc_dicr_block=“172.16.0.0/16” $ terraform apply # 默认的变量文件 terraform.tfvars $ terraform apply ``` 建议采用第一种方式 ### 输出(Outputs) outputs.tf 文件保存了资源的输出值。由 Terraform 管理的每个资源实例都可以导出属性,这些属性的值可在 Terraform 配置的其他地方被引用。如果需要,输出值是用来暴露这些信息的方法。 ```go output "vswitch_id" { value = alicloud_vswitch.main_vswitch.id } ``` ### 状态(State) Terraform 在状态文件中保存它管理的资源的状态。默认情况下,状态文件是存储在本地,但它也可以远端存储。在团队协作场景中,远端存储通常是首选方法。 Terraform 状态是你的基础设施配置的元数据存储库。 ``` { "version": 4, "terraform_version": "1.14.9", "serial": 13, "lineage": "2f6ef241-7be2-7eee-f44f-25e47f5c8756", "outputs": { "vswitch_id": { "value": "vsw-0jllxa9ar149ms2nqf4mw", "type": "string" } }, "resources": [ { "mode": "managed", "type": "alicloud_oss_bucket", "name": "example-bucket", "provider": "provider[\"registry.terraform.io/hashicorp/alicloud\"]", "instances": [ { "schema_version": 0, "attributes": { "access_monitor": [ { "status": "Disabled" } ], "acl": "private", "bucket": "luoheng-tqls", "cors_rule": [], "creation_date": "2026-04-28", "extranet_endpoint": "oss-cn-wulanchabu.aliyuncs.com", "force_destroy": false, "id": "luoheng-tqls", "intranet_endpoint": "oss-cn-wulanchabu-internal.aliyuncs.com", "lifecycle_rule": [], "lifecycle_rule_allow_same_action_overlap": false, "location": "oss-cn-wulanchabu", "logging": [], "logging_isenable": null, "owner": "1296269206896752", "policy": "", "redundancy_type": "LRS", "referer_config": [], "resource_group_id": "rg-acfmxppxxocea4a", "server_side_encryption_rule": [], "storage_class": "Standard", "tags": {}, "transfer_acceleration": [], "versioning": [], "website": [] }, "sensitive_attributes": [], "identity_schema_version": 0, "private": "bnVsbA==" } ] }, { "mode": "managed", "type": "alicloud_vpc", "name": "myvpc", "provider": "provider[\"registry.terraform.io/hashicorp/alicloud\"]", "instances": [ { "schema_version": 0, "attributes": { "cidr_block": "10.0.0.0/8", "classic_link_enabled": false, "create_time": "2026-04-28T08:36:56Z", "description": "", "dns_hostname_status": "DISABLED", "dry_run": null, "enable_ipv6": false, "force_delete": null, "id": "vpc-0jlbzenhnl8o04lf3r7kv", "ipv4_cidr_mask": null, "ipv4_ipam_pool_id": null, "ipv6_cidr_block": "", "ipv6_cidr_blocks": [], "ipv6_isp": null, "is_default": null, "name": "the-first-vpc", "region_id": "cn-wulanchabu", "resource_group_id": "rg-acfmxppxxocea4a", "route_table_id": "vtb-0jld0mezhjv4xxvsnrin5", "router_id": "vrt-0jly5n7ul6fafogyrd89s", "router_table_id": "vtb-0jld0mezhjv4xxvsnrin5", "secondary_cidr_blocks": [], "secondary_cidr_mask": null, "status": "Available", "system_route_table_description": "", "system_route_table_name": "", "system_route_table_route_propagation_enable": true, "tags": {}, "timeouts": null, "user_cidrs": [], "vpc_name": "the-first-vpc" }, "sensitive_attributes": [], "identity_schema_version": 0, "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6MzAwMDAwMDAwMDAwLCJ1cGRhdGUiOjMwMDAwMDAwMDAwMH19" } ] }, { "mode": "managed", "type": "alicloud_vswitch", "name": "main_vswitch", "provider": "provider[\"registry.terraform.io/hashicorp/alicloud\"]", "instances": [ { "schema_version": 0, "attributes": { "availability_zone": "cn-wulanchabu-a", "cidr_block": "10.0.1.0/24", "create_time": "2026-04-28T08:43:48Z", "description": "", "enable_ipv6": null, "id": "vsw-0jllxa9ar149ms2nqf4mw", "ipv6_cidr_block": "", "ipv6_cidr_block_mask": null, "is_default": null, "name": "main-vswitch", "status": "Available", "tags": {}, "timeouts": null, "vpc_id": "vpc-0jlbzenhnl8o04lf3r7kv", "vswitch_name": "main-vswitch", "zone_id": "cn-wulanchabu-a" }, "sensitive_attributes": [], "identity_schema_version": 0, "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozMDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJ1cGRhdGUiOjMwMDAwMDAwMDAwMH19", "dependencies": [ "alicloud_vpc.myvpc" ] } ] } ], "check_results": null } ``` ### 模块(Modules) 模块是 Terraform 中代码复用的主要方法,它们通过指定可以检索代码的源来重复使用。源可以是本地的也可以是远程的。  ## Terraform State ### 什么是Terraform State Terraform State 是指 Terraform 状态,是 Terraform 生命周期过程中必不可少的元素。本质上讲,Terraform 状态是你的基础设施配置的元数据存储库,Terraform 把它管理的资源状态保存在一个状态文件中。 每个在资源块中创建的基础设施资源都是通过其`resource_name`在 Terraform 状态中进行标识的,其对资源的管理流程大致如下: - 当第一次通过 terraform apply 应用 Terraform 配置时,会创建基础设施资源,同时自动生成一个状态文件,该文件引用资源块中声明的名称 - 如果一个资源已经在 Terraform 状态文件中有标识,那么 Terraform 会将配置文件与状态文件和当前的资源远端的实际状态进行比较,并根据比较结果,会生成一个执行计划 - 当执行该计划时,它会更新资源的状态以匹配配置文件中的定义,如果由于远端 API 限制无法实现就地更新参数,那么该执行计划将会先销毁资源,然后再重新创建新的资源;如果是一个资源销毁的计划,将发起资源的销毁操作 - 计划执行成功后,Terraform 状态文件会更新以反映当前的基础设施状态 - 如果某资源已从当前 Terraform 配置中移除但在状态文件中仍然存在,Terraform 则会比较配置文件并销毁不再存在的资源 ### 存储Terraform State Terraform 默认将本地状态文件保存在当前工作目录中,扩展名为 .tfstate,因此它们不需要额外的维护。本地状态文件适用于只有一个开发人员工作的项目,当多个开发人员同时运行 Terraform 并且每台机器都有对当前基础设施的理解和配置时,默认的本地状态文件的配置方式就会变得棘手。 在团队协作开发场景中使用本地状态时主要存在以下几个问题: 1. **本地状态没有共享访问权限** 当使用 Terraform 更新你的基础设施,团队中的每个成员都需要访问相同的状态文件,这意味着这些文件必须存储在一个共享的位置,比如 ECS 实例特定的位置,而这无形中增加了管理成本。 2. **不能锁定本地状态文件** 如果两个团队成员同时运行 Terraform,他们可能会遇到竞争条件,因为多个 Terraform 进程可能同时在更新状态文件。在这种情况下,可能带来导致冲突、数据丢失和状态文件损坏等风险。 3. **本地状态文件不保密** 当信息以明文形式存储在状态文件中时,敏感数据将存在被暴露的风险,例如数据库凭证,SSH 登录密码等。 因此,当一个团队中有多个开发人员通过编写代码来管理基础设施时,我们推荐你应该将状态文件存储在一个远端的中心位置。这样,当基础设施发生变化时,Terraform 状态文件会更新并同步,团队中的所有人员将始终使用最新的基础设施状态。 面对本地状态存在的问题,当使用远端状态存储时,这些问题将会得到解决: 1. **远端状态文件会自动更新** 当远程存储时,状态文件会自动更新,即一旦配置了远程后端,每次运行 plan 或 apply 命令时,Terraform 将自动从远端加载状态文件。除此之外,它还会在每次 apply 后自动将状态文件同步存储在远端中,因此不存在手动错误的情况。 2. **远端状态文件支持状态锁定** 当执行 Terraform 命令时,可以对远端状态文件进行加锁,这样如果多个开发人员同时运行 terraform apply,它不会因同时更新而损坏。 3. **远端状态文件存储比本地存储更安全** OSS Bucket 支持本地传输加密和远端加密功能。此外,OSS Bucket 包括多种配置访问权限的方法,因此你可以以精细化的方式控制状态文件的访问 ### Terraform State 的最佳实践** 针对 Terraform 状态文件,我们从状态优化和安全性方面给出如下建议: 1. **团队协作场景使用远端状态** 首先,在团队协作场景中应使用远程状态,以便锁定和版本控制状态文件。阿里云的客户应使用 OSS 作为远端状态存储后端,并使用 OTS 来锁定状态文件。将敏感信息与 Terraform 配置文件的版本控制分开,并确保只有构建系统和高权限管理员可以访问远程状态存储 Bucket。为了防止意外地将开发环境的状态文件提交到源代码版本控制系统中(如Github,Gitlab等),请为 Terraform 状态文件配置 gitignore。 2. **不要在状态中存储敏感数据** 许多资源和数据提供者会将敏感数据以明文形式存储在状态文件中,这是存在安全隐患的。如果可能,尽量避免在状态文件中存储敏感信息。 3. **对状态进行加密** 增加一层防御,始终对远端状态文件进行加密。阿里云 OSS 存储支持 KMS、AES256、SM4 三种加密方式的,客户可以通过自定义的 KMS 密钥对状态文件提供额外一层保护。 4. **不要手动修改 Terraform 状态** 状态文件是维护 Terraform 配置和阿里云基础设施资源之间的映射关系的关键,状态文件的损坏可能导致重大的基础设施问题。因此不要尝试手动修改 Terraform 状态文件内容。 ## Variables 变量可以让你参数化在资源之间共享的值,除此之外,使用变量还具有以下好处: 1. **增加通用性** 输入变量作为参数提供给 Terraform 使用,将源代码和属性赋值分离,可以实现对同一份 Terraform 配置的轻松定制和共享,而无需更改源代码。 2. **提高灵活性** 定义变量后,在运行时(apply)有多种方法可以为属性自定义设置其值,包括环境变量、CLI 选项和键值对文件。在如下的示例中,名称、描述和网段都是硬编码的。你可以将这些属性中的任何一个声明为变量,并在运行时指定具体的值。 ### type type 参数指定了变量接受的值的类型。Terraform 支持以下基本变量类型: - **bool**,用于二进制值,如 true 或 false(不带引号) - **number**,用于数值变量 - **string**,用于字符序列 ### default default 是变量的另一个元参数,用于给属性分配默认值。 ``` resource "alicloud_vpc" "my_vpc" { vpc_name = "main-vpc" cidr_block = var.vpc_cidr_block description = "" } variable "vpc_cidr_block" { default = "10.0.0.0/16" } ``` ### **description** description 用于记录变量的用途。description 字符串通常包含在文档中,应当解释变量的用途和预期值。 ### **sensitive** sensitive 是一个变量参数,顾名思义,用于保护敏感信息不会显示在命令输出或日志文件中。敏感值的可接受值为true。当设置为true时,变量的值在 terraform plan 或terraform apply 的输出中标记为敏感。 当处理如数据库凭证或 AccessKey 或者登录密码等敏感信息时,此参数非常有用,将变量标记为敏感将消除意外暴露机密信息的风险。 ### **validation** 验证块包含一个条件参数,用于指定验证规则。你可以通过在变量块中包含验证子块来验证赋给变量的值。 ``` variable "vpc_name" { validation { condition = length(var.vpc_name) > 4 && substr(var.vpc_name, 0, 3) == "tf-" error_message = "The vpc name must start with 'tf-' and be longer than 4 characters." } } ``` ## 资源依赖 Terraform 有两种依赖关系:隐式依赖(Implicit Dependence)和显式依赖(Explicit Dependence)。隐式依赖是 Terraform 已知的,而显式依赖是未知的。   有时,某个资源只能在另一个资源创建后才能创建,在这种情况下,你需要显式地引入依赖关系,该依赖关系配置在 Terraform 配置代码内部,对 Terraform 不可见。在这种情况下,你可以使用 depends_on 来显式声明依赖关系。   ## Module Terraform Module(模块)是 Terraform 基础设施即代码(IaC)生态系统中的核心概念,用于组织和重用 Terraform 代码的基本单位。随着云基础设施规模的扩大,将所有基础设施配置都放在单个 Terraform 文件中会变得难以维护和管理。模块允许用户将基础设施配置封装为可重用、可共享的组件,使其更易于阅读和管理。模块化设计是构建可维护、可扩展和标准化基础设施代码的基础,特别适合于大规模、多环境或团队协作的云基础设施管理场景。 Terraform 模块本质上是一组相关资源的集合,可以将其视为基础设施代码的“函数”。通过定义输入变量、输出值和资源配置,模块提供了一种抽象机制,使复杂的基础设施组件可以以一致且简化的方式被重复部署。这不仅提高了代码重用率,降低了维护成本,还促进了组织内部的标准化实践和最佳实践的实施。 由于历史原因,使用阿里云 Module 时需要特别注意 provider 的配置,建议将 provider source 指定为 "hashicorp/alicloud",示例如下: ```hcl terraform { required_providers { alicloud = { source = "hashicorp/alicloud" version = "1.245.0" } } } provider "alicloud" { region = "cn-hangzhou" } ``` 虽然使用 "hashicorp/alicloud" 会产生警告信息,但这个警告可以安全忽略。使用source = "aliyun/alicloud"可能导致资源无法创建、资源未能在指定的 Region 中创建以及其他意外行为。 ### 模块调用语法 ```hcl module "vpc" { source = "alibaba/vpc/alicloud" # source:模块源路径(必需) version = "1.10.0" # version:模块版本(推荐,仅用于 Registry 模块) vpc_name = "example-vpc" cidr_block = "172.16.0.0/16" } ``` #### **source 参数** 所有模块都需要 `source` 参数,它可以是本地目录路径也可以是远程模块源。需要注意的是: 1. 值必须是字面字符串,不允许使用表达式 2. 同一个源地址可以在多个模块中使用,创建多个资源副本 3. 修改模块后需要运行 `terraform init` 重新初始化 #### **version 参数** 使用 Registry 模块时,建议明确指定版本约束: ```hcl module "slb" { source = "alibaba/slb/alicloud" version = "1.10.0" name = "example-slb" } ``` 版本约束说明: - 仅支持 Registry 模块 - 本地路径模块不支持版本控制 - Terraform 会使用满足约束的最新版本 ### 元参数 #### **count** count 用于创建模块的多个实例,每个实例都有相同的配置,可以通过 count.index 访问当前实例的索引 ```hcl module "ecs" { count = 3 source = "./modules/ecs" } ``` - 适用场景: - 创建多个相同配置的资源组 - 基于条件创建资源(count = 条件 ? 1 : 0) - 批量部署测试环境 - 注意事项: - count 值必须在执行命令前前确定 - 删除中间实例会影响其他实例的索引 - 不适合配置有明显差异的实例 #### **for_each** 用于基于映射或集合创建多个模块实例,每个实例可以有不同的配置,可以通过 each.key 和 each.value 访问当前实例的键值。 ```hcl module "ecs" { for_each = toset(["web", "app", "db"]) source = "./modules/ecs" name = each.key } ``` - 适用场景: - 创建配置各不相同的资源 - 基于动态数据创建资源 - 管理具有标识符的资源集合 - 注意事项: - for_each 值必须在执行命令配置前确定 - 支持 map 或 set 类型的值 - 比 count 更适合管理有标识符的资源 #### **providers** 用于将 provider 配置传递给子模块,允许在不同区域或账号中创建资源,可支持多个 provider 配置的映射。 ```hcl module "vpc" { source = "./modules/vpc" providers = { alicloud = alicloud.hz alicloud.backup = alicloud.bj } } ``` - 适用场景: - 跨区域部署资源 - 多账号资源管理 - 灾备架构设计 - 注意事项: - 未指定时子模块继承父模块的默认 provider - provider 别名必须在父模块中定义 - 确保所有必需的 provider 都已配置 #### **depends_on** 用于声明模块间的显式依赖关系,确保资源按正确顺序创建和销毁,可以依赖多个资源或模块。 ```hcl module "ecs" { source = "./modules/ecs" depends_on = [module.vpc, module.security_group] } ``` - 适用场景: - 处理隐式依赖无法满足的场景 - 确保基础设施按特定顺序部署 - 管理复杂的资源依赖关系 - 注意事项: - 仅在必要时使用,避免过度使用 - 不能创建循环依赖 - 影响部署效率,增加部署时间 ### Module Source详解 #### 1. 本地路径 (Local Paths) 本地路径引用允许在单个源代码仓库内部重用代码。 ```hcl module "vpc" { source = "./vpc" } module "ecs" { source = "../modules/ecs" } ``` 本地路径必须以 `./` 或 `../` 开头,以表明是本地路径,而不是远端地址。 - **特点**: - 本地路径模块不会被"安装",而是直接使用 - 父模块升级时,源代码会自动更新 - 不建议使用绝对文件系统路径引用模块 - **引用子模块**: 对于本地路径,可以直接指定子目录路径来引用子模块: ```hcl module "vpc_subnet" { source = "./vpc/modules/subnet" } ``` #### **2. Terraform Registry** Registry 是跨多个配置分发 Terraform 模块的原生方式,它支持完整的模块版本控制。 ```hcl module "ecs" { source = "alibaba/ecs-instance/alicloud" version = "1.2.0" } ``` - **地址格式**:`<NAMESPACE>/<NAME>/<PROVIDER>` - `**<NAMESPACE>**`:表示模块发布者或组织。它定义了谁拥有和维护该模块。 - 对于阿里云的模块,主要命名空间包括: - `alibaba`:阿里云官方维护的主要模块 - `aliyun`:阿里云备用命名空间下的模块 - `terraform-alicloud-modules`:早期阿里云模块组织方式 - `alibabacloud-automation`:阿里云自动化团队维护的模块 - 例如,`alibaba/ecs-instance/alicloud` 中的 `alibaba` 表示该模块由阿里云官方维护 - `**<NAME>**`:表示模块的名称,反映模块的功能或用途。 - 名称通常描述该模块创建和管理的资源类型 - 例如,`alibaba/ecs-instance/alicloud` 中的 `ecs-instance` 表示该模块用于创建和管理阿里云 ECS 实例 - 其他常见名称还有 `vpc`、`slb`、`rds`、`security-group` 等,反映了相应的阿里云资源 - `**<PROVIDER>**`:表示该模块适用的 Terraform 提供商。 - 对于阿里云的模块,此值固定为 `alicloud` - 提供商标识了该模块与哪个云平台集成 - 例如,`alibaba/ecs-instance/alicloud` 中的 `alicloud` 表示该模块使用阿里云提供商 - 完整示例: - `alibaba/vpc/alicloud`:创建阿里云 VPC 的官方模块 - `terraform-alicloud-modules/security-group/alicloud`:创建阿里云安全组的模块 - `alibabacloud-automation/multiple-vpc-networks-peering/alicloud`: 构建高效、安全且高可用的同区域多VPC网络架构 - 更多阿里云官方模块可在 [Terraform Registry](https://registry.terraform.io/browse/modules?provider=alibaba)找到。 - **引用子模块**: Registry模块通常会将相关功能拆分为子模块,可以通过双斜杠语法 `//` 引用: ```hcl module "nat_gateway" { source = "alibaba/vpc/alicloud//modules/nat-gateway" version = "1.10.0" } ``` #### **3. GitHub** Terraform 会自动识别 GitHub URL 并将其解释为 Git 仓库源。 ```hcl # HTTPS 方式 module "vpc" { source = "github.com/alibabacloud-automation/terraform-alicloud-ram" } # SSH 方式 module "vpc" { source = "git@github.com:alibabacloud-automation/terraform-alicloud-ram.git" } ``` 这些 GitHub 方案实际上是通用 Git 仓库地址方案的别名,因此它们以相同的方式获取凭据,并支持 `ref` 参数来选择特定版本。 **引用子模块**: ```hcl # 引用GitHub仓库中的子模块 module "vpc_subnet" { source = "github.com/alibabacloud-automation/terraform-alicloud-ram//modules/ram-user" } # 通过SSH方式引用特定版本的子模块 module "vpc_subnet" { source = "git@github.com:alibabacloud-automation/terraform-alicloud-ram.git//modules/ram-user?ref=v2.1.0" } ``` #### **4. 通用 Git 仓库** 可以通过在地址前加上特殊前缀 `git::` 来使用任意 Git 仓库: ```hcl # HTTPS 方式 module "vpc" { source = "git::https://github.com/alibabacloud-automation/terraform-alicloud-vpc.git" } # SSH 方式 module "vpc" { source = "git::ssh://git@github.com/alibabacloud-automation/terraform-alicloud-vpc.git" } ``` **引用子模块**: ```hcl # 引用Git仓库中的子模块并选择特定版本 module "vpc_subnet" { source = "git::https://github.com/alibabacloud-automation/terraform-alicloud-ram.git//modules/ram-user?ref=v2.1.0" } # 引用私有Git仓库中的子模块 module "security_component" { source = "git::ssh://git@example.com/company/terraform-modules.git//security/waf?ref=v1.0.0" } ``` #### **选择特定版本** 默认情况下,Terraform 会克隆并使用所选仓库中的默认分支。可以使用 `ref` 参数来指定分支、标签或提交哈希: ```hcl # 选择特定标签 module "vpc" { source = "git::https://github.com/alibabacloud-automation/terraform-alicloud-vpc.git?ref=v1.11.0" } # 选择特定提交 module "vpc" { source = "git::https://github.com/alibabacloud-automation/terraform-alicloud-vpc.git?ref=51d462976d84fdea54b47d80dcabbf680badcdb8" } ``` #### **浅克隆** 对于较大的存储库,您可能希望仅进行浅克隆以减少检索远程存储库所需的时间: ```hcl module "vpc" { source = "git::https://github.com/alibabacloud-automation/terraform-alicloud-vpc.git?depth=1&ref=v1.11.0" } ``` #### **5. HTTP URLs** 当使用 HTTP 或 HTTPS URL 时,Terraform 会向给定URL发送 GET 请求,该 URL 可以返回另一个源地址: ```hcl module "vpc" { source = "https://example.com/modules/vpc" } ``` 如果 Terraform 检测到 URL 具有与归档文件格式相关的扩展名,它将直接使用引用的归档内容作为模块源代码: ```hcl module "vpc" { source = "https://example.com/vpc-module.zip" } ``` 支持的扩展名包括: - zip - bz2, tar.bz2, tar.tbz2, tbz2 - gz, tar.gz, tgz - xz, tar.xz, txz **引用子模块**: ```hcl # 从zip归档文件中引用子模块 module "vpc_subnet" { source = "https://example.com/vpc-module.zip//modules/subnet" } ``` #### 最佳实践 1. **选择合适的源类型**: - 对于密切相关的模块,推荐使用本地文件路径 - 对于需要在多个配置间共享的模块,推荐使用 Terraform Registry 2. **版本控制**: - 始终在生产环境中指定模块版本 - 使用语义化版本控制选择适当的版本约束 3. **阿里云特定建议**: - 优先使用阿里云官方模块 - 确保模块与目标区域兼容 - 注意区域特定的资源限制 4. **安全性考虑**: - 使用 HTTPS 或 SSH 协议获取模块 - 对于私有仓库,正确配置凭据 - 定期更新模块版本以获取安全修复
罗衡
2026年5月5日 22:11
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期