
最近折腾了一下用 Python 来控制 Terraform,踩了几个坑,这篇把问题说清楚。
想象一下这个场景:你盯着终端,第N次手动跑 terraform init、plan、apply,就因为 CI/CD 流水线又挂了。你心里清楚 Python 是自动化的绝杀技能,能写测试、能做胶水逻辑——但 Terraform 看起来就像个只认 HCL(HCL 是 HashiCorp 配置语言)的黑盒子。凭什么不能用 Python 来驾驭它?用写 API 或者数据管道的优雅方式去编排基础设施部署?不仅可行,而且实用,今天就能用上。
Terraform 的强项是声明式基础设施即代码(IaC),让你用人类可读的 HCL 文件定义云资源。Python 呢,自动化、脚本编写、系统集成是把好手。两边一结合,就是一套混合工作流:基础设施写在 .tf 文件里(保留 Terraform 的优势),然后用 Python 脚本驱动整个生命周期——init、plan、apply、输出解析,全都可以。
这种玩法特别适合:
不需要把 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 文件(比如 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 脚本来管理生命周期:
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}" }
}
这套模式对多环境部署、特性开关基础设施、或者跟应用状态联动都非常舒服。
如果你压根不想写 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 文件的组合更简单、更容易维护。
三个可以马上动手的例子:
CI/CD 流水线集成:把 deploy_ecs.py 脚本嵌到 GitHub Actions 或者阿里云云效的 job 里。动态传入环境变量,解析输出更新部署面板。
基础设施测试:用 Python 的 pytest 验证 Terraform 输出。比如断言某个实例创建时带了正确的标签,或者数据库 endpoint 可以连通。
多云编排:在一个 Python 脚本里串联多个 Terraform 模块(阿里云、腾讯云、华为云)。根据用户输入或系统状态决定部署哪些。
ALICLOUD_ACCESS_KEY 和 ALICLOUD_SECRET_KEY(或者用 aliyun configure)。working_dir 指向包含 main.tf 的文件夹。找不到配置的话 init() 会直接报错。apply(skip_plan=True) 跳过 "Proceed with terraform apply?" 的确认提示,否则脚本会挂起等你输入。python-terraform 不处理 OAuth 或 API Token,请通过 Terraform 原生机制或环境变量配置。不需要抛弃 HCL 就能把 Python 带进 Terraform 工作流。有了 python-terraform,你可以用干净、可脚本化的接口驱动完整的 IaC 生命周期——init、plan、apply、输出解析——同时保持基础设施定义声明式且可复用。
从小处着手:找一块你常用的 Terraform 模块,写个 python-terraform 脚本去部署它,然后跑起来。加点动态变量,串联几个模块,测试输出。一小时之内你就能有一套可复用的自动化层,省时间、减少出错、还能随团队一起扩展。
动手吧:挑一个你天天用的 Terraform 模块,写个 python-terraform 脚本,今天就跑起来。把脚本分享到掘金或者团队的技术频道——肯定有别人正在被同样的手动流程折磨。一起搞更聪明的自动化。