site logo

Marico's space

如何使用 Terraform 和 Python 管理基础设施

编程技术 2026-07-16 20:56:07 6

最近折腾了一下用 Python 来控制 Terraform,踩了几个坑,这篇把问题说清楚。

想象一下这个场景:你盯着终端,第N次手动跑 terraform initplanapply,就因为 CI/CD 流水线又挂了。你心里清楚 Python 是自动化的绝杀技能,能写测试、能做胶水逻辑——但 Terraform 看起来就像个只认 HCL(HCL 是 HashiCorp 配置语言)的黑盒子。凭什么不能用 Python 来驾驭它?用写 API 或者数据管道的优雅方式去编排基础设施部署?不仅可行,而且实用,今天就能用上。

为什么要把 Terraform 和 Python 凑一起?

Terraform 的强项是声明式基础设施即代码(IaC),让你用人类可读的 HCL 文件定义云资源。Python 呢,自动化、脚本编写、系统集成是把好手。两边一结合,就是一套混合工作流:基础设施写在 .tf 文件里(保留 Terraform 的优势),然后用 Python 脚本驱动整个生命周期——init、plan、apply、输出解析,全都可以。

这种玩法特别适合:

  • 在 CI/CD 里自动化那些重复的 Terraform 工作流
  • 根据应用状态动态生成 Terraform 变量
  • 用条件逻辑串联 Terraform 模块
  • 提取和转换 Terraform 输出,给下游系统用

不需要把 Terraform 配置用 Python 重写一遍,Python 扮演的是控制层的角色。

首选工具:python-terraform

沟通 Python 和 Terraform 最直接的方式就是用 python-terraform 这个包。它给 Terraform CLI 命令套了一层 Pythonic 的壳,让你能直接在脚本里调 init()plan()apply()output()

第一步:装包

先装库:

pip install python-terraform

确保 Terraform CLI 已经装好,环境变量 PATH 里能找到。可以验证一下:

terraform -v

第二步:准备好 Terraform 配置

在一个专用目录里创建标准的 Terraform 文件(比如 main.tf)。下面是个最小化的阿里云 ECS 示例:

provider "alicloud" { region = "cn-hangzhou"
} resource "alicloud_instance" "example" { image_id = "ubuntu_18_04_64_20G_alibase_20220113.vhd" instance_type = "ecs.n2.small" security_groups = [alicloud_security_group.group.id] tags = { Name = "Python-Terraform-Example" }
} resource "alicloud_security_group" "group" { name = "tf-sg"
}

把这个存到 ./terraform/aliyun-ecs 这种路径下。

第三步:用 Python 驱动它

现在写个 Python 脚本来管理生命周期:

import terraform # 初始化 Terraform 工作目录
tf = terraform.Terraform(working_dir='./terraform/aliyun-ecs') # 初始化 providers 和插件
tf.init() # 规划基础设施变更(可选,用于预览)
tf.plan() # 应用变更,跳过交互式确认
tf.apply(skip_plan=True) # 获取并打印 Terraform 输出
output = tf.output()
print("Terraform outputs:", output)

跑起来:

python deploy_ecs.py

你会看到 Terraform 初始化 providers、规划变更、执行变更,然后打印输出(比如你定义的实例 ID 之类的)。

注意python-terraform 不处理 providers 认证(比如阿里云 AccessKey)。运行脚本之前,必须通过环境变量或者 Terraform 内置的认证机制配置好凭证。

进阶玩法:动态变量和条件逻辑

如果你想根据环境(测试环境 vs 生产环境)跑不同的实例规格怎么办?Python 能动态注入变量:

import terraform
import os env = os.getenv("ENV", "dev")
image_id = "ubuntu_18_04_64_20G_alibase_20220113.vhd" if env == "dev" else "ubuntu_20_04_64_20G_alibase_20220113.vhd"
instance_type = "ecs.n2.small" if env == "dev" else "ecs.n2.medium" tf = terraform.Terraform(working_dir='./terraform/aliyun-ecs') # 动态传入变量
tf.apply( skip_plan=True, var={ "image_id": image_id, "instance_type": instance_type, "env": env }
) print(tf.output())

对应的 main.tf 要改成接收这些变量:

variable "image_id" {}
variable "instance_type" {}
variable "env" {} resource "alicloud_instance" "example" { image_id = var.image_id instance_type = var.instance_type tags = { Name = "Python-Terraform-${var.env}" }
}

这套模式对多环境部署、特性开关基础设施、或者跟应用状态联动都非常舒服。

备选方案:CDK for Terraform(cdktf)

如果你压根不想写 HCL,想直接用 Python 定义基础设施,HashiCorp 提供了 CDK for Terraform(cdktf)。它让你用 Python 类定义资源,然后合成成 Terraform JSON 再部署。

安装依赖:

npm install -g cdktf-cli
pip install cdktf

初始化 Python 项目:

cdktf init --template=python --project=my-project

用 Python 定义资源:

from constructs import Construct
from imports.aliyun import Instance class MyStack(TerraformStack): def __init__(self, scope: Construct, id: str): super().__init__(scope, id) Instance(self, "example", image_id="ubuntu_18_04_64_20G_alibase_20220113.vhd", instance_type="ecs.n2.small", tags={ "Name": "cdktf-example" } ) app = App()
MyStack(app, "my-stack")
app.synth()

然后部署:

cdktf deploy

功能很强大,但 cdktf 增加了复杂度,还得装 Node.js 依赖。对大多数团队来说,python-terraform + HCL 文件的组合更简单、更容易维护。

今天就能落地的真实场景

三个可以马上动手的例子:

  1. CI/CD 流水线集成:把 deploy_ecs.py 脚本嵌到 GitHub Actions 或者阿里云云效的 job 里。动态传入环境变量,解析输出更新部署面板。

  2. 基础设施测试:用 Python 的 pytest 验证 Terraform 输出。比如断言某个实例创建时带了正确的标签,或者数据库 endpoint 可以连通。

  3. 多云编排:在一个 Python 脚本里串联多个 Terraform 模块(阿里云、腾讯云、华为云)。根据用户输入或系统状态决定部署哪些。

常见坑及避坑指南

  • 凭证没配:跑脚本之前一定要设置好 ALICLOUD_ACCESS_KEYALICLOUD_SECRET_KEY(或者用 aliyun configure)。
  • 工作目录写错了:确保 working_dir 指向包含 main.tf 的文件夹。找不到配置的话 init() 会直接报错。
  • 卡在交互提示:用 apply(skip_plan=True) 跳过 "Proceed with terraform apply?" 的确认提示,否则脚本会挂起等你输入。
  • Provider 认证python-terraform 不处理 OAuth 或 API Token,请通过 Terraform 原生机制或环境变量配置。

结语:基础设施,现在由 Python 掌控

不需要抛弃 HCL 就能把 Python 带进 Terraform 工作流。有了 python-terraform,你可以用干净、可脚本化的接口驱动完整的 IaC 生命周期——init、plan、apply、输出解析——同时保持基础设施定义声明式且可复用。

从小处着手:找一块你常用的 Terraform 模块,写个 python-terraform 脚本去部署它,然后跑起来。加点动态变量,串联几个模块,测试输出。一小时之内你就能有一套可复用的自动化层,省时间、减少出错、还能随团队一起扩展。

动手吧:挑一个你天天用的 Terraform 模块,写个 python-terraform 脚本,今天就跑起来。把脚本分享到掘金或者团队的技术频道——肯定有别人正在被同样的手动流程折磨。一起搞更聪明的自动化。