停止脚本,开始架构:OOP 方法在 Terraform 中

发布: (2025年12月11日 GMT+8 00:52)
4 min read
原文: Dev.to

Source: Dev.to

TL;DR

问题: Terraform 代码库常常出现 蔓延——复制粘贴的资源、紧耦合以及泄漏的抽象,使得扩展变得痛苦。

解决方案: 将 Terraform 模块视为 ,模块实例视为 对象

关键映射

OOP 概念Terraform 等价
子模块(例如 ./modules/web_server/
对象module 块(实例化)
接口variables.tf(输入)和 outputs.tf(获取器)
私有状态locals 和内部资源
最佳实践更倾向于 组合(由其他模块构建模块)而非继承。通过传递资源 ID(例如 vpc_id)实现 依赖注入,而不是在内部使用 data 源进行查找。

面向对象的方式将混乱、重复的 HCL 转变为可扩展的基础设施架构。通过将 OOP 原则——封装、抽象、组合和多态——映射到 Terraform 模块,我们能够构建出像应用代码一样可维护、可测试的基础设施。


问题:单块 Terraform 文件

在项目的早期阶段,单个 main.tf 文件使用起来很方便。随着基础设施的增长,这种 “脚本化” 思维导致脆弱性:硬编码的值在不同环境中重复出现,安全组与实例内联定义,且完全缺乏可复用性。

当 Terraform 仅被当作配置脚本来使用时,我们会错失软件工程设计模式带来的结构化优势。我们需要从 编写脚本 转向 构建对象


核心类比:模块即类

OOP 概念Terraform 实现
类定义./modules/web_server/ – 定义 如何 构建某物的蓝图,而不是 构建什么
构造函数variables.tf – 定义实例化类所需的输入。
公共方法 / 属性outputs.tf – 定义显式向调用方暴露的数据。
私有成员localsresource – 对父作用域隐藏的内部逻辑和状态。
对象实例module "web_prod" { … } – 对蓝图的具体实现。

可视化:模块接口

classDiagram
    class Module {
        >
        +variables.tf
        +outputs.tf
        -locals
        -resources
    }
    class ChildModule {
        +module "instance" {}
    }
    Module  B[networking]
    A --> C[compute]
    B --> D[VPC & Subnets]
    C --> E[EC2 Instances]

代码示例

# /modules/app_stack/main.tf
module "networking" {
  source = "../networking"
  cidr   = var.cidr
}

module "compute" {
  source    = "../compute"
  subnet_id = module.networking.private_subnet_id   # Wiring components together
  vpc_id    = module.networking.vpc_id
}

app_stack 模块充当外观,协调网络层和计算层之间的交互,同时保持每个子模块专注于单一职责。


4. 抽象与复用:“接口”行为

(源文档中此部分内容被截断,原则仍然是通过 variables.tfoutputs.tf 定义清晰的输入/输出合约,以实现可复用、可互换的模块。)

Back to Blog

相关文章

阅读更多 »