TT Lab
开始
学习 学习路径 课程

基础设施即代码

把复制粘贴的代码折成模块

在 TT Lab 中继续学习

一句话总结

如果同样的代码复制了三次,这就是它应该变成模块的信号。 不过,过早地把它做成模块,比复制粘贴更糟。

为什么需要它

有三个环境,就会有三个目录。

dev/main.tf     (300줄)
stage/main.tf   (300줄, dev 와 거의 같음)
prod/main.tf    (300줄, 인스턴스 크기만 다름)

要修改一条安全组规则,就得改三处,而且一定会漏掉一处。漏掉的那一处,往往就是 prod。

模块的作用

模块是接收输入并创建一组资源的函数。

module "web" {
  source        = "../modules/web-service"
  name          = "api"
  instance_size = "large"     # 환경마다 다른 것만 인자로
  replicas      = 6
}

三个环境使用同一个模块,只把不同的值作为参数传入。修改规则时,只需修改模块这一处。

好模块的条件

1. 边界自然 “一个 Web 服务所需要的全部内容”是好的边界。“我们公司的所有基础设施”是坏的边界。模块是复用的单位,不是打包的单位。

2. 输入少 有 30 个参数的模块不是模块,而是配置文件。参数增多,说明边界划错了。

3. 输出明确 把其他模块要引用的值(ID、端点)作为输出暴露出来。如果外部还必须知道内部实现,说明封装失败了。

4. 有版本 修改模块,会影响所有使用它的地方。给它加上版本,就能让不同环境使用不同时间点的模块——先在 dev 中试用新版本,prod 以后再升级。

过早的抽象

把三处使用的代码做成了模块,很快出现第四个使用方,于是“只有这种情况不同”就开始了。参数一个个增加,条件语句加了进来,最终变成没有人能看懂的模块。

经验法则如下。

重复是看得见、也改得了的,而错误的抽象既看不见,也很难改。没有把握时,保持重复反而更好。

在现场相遇的样子

下一项实验要做什么

在接下来的三项实验中,用 OpenTofu 亲自处理漂移和模块。用 plan -refresh-only 读取手工改过的文件,在吸收、回退和排除中做出选择;用 removed 块整理两份状态争夺同一个资源的情形,再用 import 导入现有的值;用 moved 把复制粘贴的两个环境在不替换的情况下改为模块调用,并用 git 标签固定版本。在最后的测验中,判断稳定的边界、版本固定和调用方的责任。