Pulumi IaC¶
一句话概述:Pulumi 是新一代基础设施即代码工具,用你熟悉的编程语言(Python/TypeScript/Go)而不是专用配置语言来定义云资源,有完整的 IDE 支持和测试能力。
核心知识点¶
| 概念 | 白话解释 |
|---|---|
| Stack | 栈 = 一套独立的基础设施实例(如 dev、staging、prod) |
| Project | 项目 = 一个 Pulumi 程序,包含基础设施代码 |
| Resource | 资源 = 一个云资源(如 EC2、S3 桶) |
| Output | 输出 = 资源创建后的返回值(如 IP、URL) |
| State | 状态 = 记录当前基础设施的快照 |
| Provider | 提供商 = 云平台的 SDK(AWS、Azure、GCP 等) |
| Config | 配置 = 每个 Stack 独立的参数设置 |
| ComponentResource | 组件资源 = 自定义的可复用资源组合 |
安装配置¶
# === 安装 Pulumi ===
# macOS/Linux
curl -fsSL https://get.pulumi.com | sh # 一键安装脚本
# macOS (Homebrew)
brew install pulumi # Homebrew 安装
# 验证安装
pulumi version # 查看版本
# === 配置后端 ===
# 方式1:Pulumi Cloud(默认,免费套餐够个人用)
pulumi login # 登录 Pulumi Cloud
# 方式2:本地存储(不联网)
pulumi login --local # 状态文件存本地
# 方式3:S3 后端
pulumi login s3://my-pulumi-state # 状态存到 S3
# === 创建新项目 ===
mkdir my-infra && cd my-infra # 创建项目目录
pulumi new aws-python # 创建 AWS + Python 项目(交互式)
# 会问你:项目名、描述、Stack 名、AWS 区域
基本使用¶
1. 创建 S3 桶(Python)¶
# __main__.py
import pulumi # 导入 Pulumi SDK
import pulumi_aws as aws # 导入 AWS Provider
# 创建 S3 桶
bucket = aws.s3.Bucket(
"my-bucket", # 资源逻辑名
bucket="my-bioinfo-data-2026", # 桶的物理名(全球唯一)
tags={"Environment": "dev", "Project": "bioinfo"}, # 标签
)
# 启用版本控制
versioning = aws.s3.BucketVersioningV2(
"my-bucket-versioning",
bucket=bucket.id, # 引用上面创建的桶
versioning_configuration=aws.s3.BucketVersioningV2VersioningConfigurationArgs(
status="Enabled", # 启用版本控制
),
)
# 导出桶名(在命令行可以看到)
pulumi.export("bucket_name", bucket.id) # 输出桶名
pulumi.export("bucket_arn", bucket.arn) # 输出桶的 ARN
# 执行流程
pulumi preview # 预览变更(类似 terraform plan)
pulumi up # 创建/更新资源(类似 terraform apply)
pulumi stack output bucket_name # 查看输出值
pulumi destroy # 销毁资源
2. 创建 EC2 + VPC¶
import pulumi
import pulumi_aws as aws
# 创建 VPC
vpc = aws.ec2.Vpc(
"main-vpc",
cidr_block="10.0.0.0/16", # IP 地址范围
enable_dns_hostnames=True, # 启用 DNS
tags={"Name": "main-vpc"},
)
# 创建子网
subnet = aws.ec2.Subnet(
"public-subnet",
vpc_id=vpc.id, # 关联到 VPC
cidr_block="10.0.1.0/24", # 子网范围
map_public_ip_on_launch=True, # 自动分配公网 IP
tags={"Name": "public-subnet"},
)
# 安全组(防火墙规则)
sg = aws.ec2.SecurityGroup(
"web-sg",
vpc_id=vpc.id,
description="Allow HTTP and SSH", # 允许 HTTP 和 SSH
ingress=[
{"protocol": "tcp", "from_port": 80, "to_port": 80, "cidr_blocks": ["0.0.0.0/0"]}, # HTTP
{"protocol": "tcp", "from_port": 22, "to_port": 22, "cidr_blocks": ["0.0.0.0/0"]}, # SSH
],
egress=[
{"protocol": "-1", "from_port": 0, "to_port": 0, "cidr_blocks": ["0.0.0.0/0"]}, # 允许所有出站
],
)
# 查找最新的 Amazon Linux AMI
ami = aws.ec2.get_ami(
most_recent=True,
owners=["amazon"],
filters=[{"name": "name", "values": ["amzn2-ami-hvm-*-x86_64-gp2"]}], # Amazon Linux 2
)
# 创建 EC2 实例
server = aws.ec2.Instance(
"web-server",
instance_type="t3.micro", # 实例类型
ami=ami.id, # 使用查到的 AMI
subnet_id=subnet.id, # 放在公有子网
vpc_security_group_ids=[sg.id], # 绑定安全组
tags={"Name": "web-server"},
)
pulumi.export("public_ip", server.public_ip) # 输出公网 IP
高级用法¶
1. 组件资源(可复用模块)¶
import pulumi
from pulumi import ComponentResource, ResourceOptions
import pulumi_aws as aws
class WebServer(ComponentResource):
"""自定义 Web 服务器组件(把多个资源打包成一个可复用的模块)"""
def __init__(self, name: str, instance_type: str = "t3.micro",
opts: ResourceOptions = None):
super().__init__("custom:WebServer", name, None, opts)
# 安全组
self.sg = aws.ec2.SecurityGroup(
f"{name}-sg",
ingress=[{"protocol": "tcp", "from_port": 80, "to_port": 80,
"cidr_blocks": ["0.0.0.0/0"]}],
opts=ResourceOptions(parent=self), # 设置父资源
)
# EC2 实例
self.instance = aws.ec2.Instance(
f"{name}-instance",
instance_type=instance_type,
ami="ami-xxx",
vpc_security_group_ids=[self.sg.id],
opts=ResourceOptions(parent=self),
)
self.register_outputs({"public_ip": self.instance.public_ip})
# 使用组件
web1 = WebServer("web1", instance_type="t3.small")
web2 = WebServer("web2", instance_type="t3.micro")
2. 多栈管理¶
pulumi stack init dev # 创建 dev 栈
pulumi stack init prod # 创建 prod 栈
pulumi stack select dev # 切换到 dev
pulumi stack ls # 列出所有栈
# 每个栈独立配置
pulumi config set aws:region us-east-1 # 设置当前栈的 AWS 区域
pulumi config set instanceType t3.micro # 设置实例类型
3. 单元测试¶
# test_infra.py
import pulumi
import unittest
class MyMocks(pulumi.runtime.Mocks):
"""模拟 Pulumi 资源(不真的创建)"""
def new_resource(self, args):
return [args.name + "_id", args.inputs]
def call(self, args):
return {}
pulumi.runtime.set_mocks(MyMocks())
from my_infra import bucket # 导入你的基础设施代码
class TestInfra(unittest.TestCase):
@pulumi.runtime.test
def test_bucket_tags(self):
"""测试 S3 桶有正确的标签"""
def check_tags(tags):
self.assertIn("Environment", tags)
bucket.tags.apply(check_tags)
常见报错¶
| 报错信息 | 原因 | 解决方法 |
|---|---|---|
error: no Pulumi.yaml project file found | 不在 Pulumi 项目目录 | cd 到项目根目录 |
error: could not load plugin | Provider 插件缺失 | pulumi plugin install |
error: the current stack does not exist | 未选择 Stack | pulumi stack select <name> |
error: duplicate resource URN | 资源名重复 | 给资源取不同的逻辑名 |
error: update failed | 资源创建失败 | 查看详细错误,检查 AWS 权限 |
速查表¶
# === 核心命令 ===
pulumi new <template> # 创建新项目
pulumi preview # 预览变更
pulumi up # 执行变更
pulumi destroy # 销毁资源
pulumi stack ls # 列出栈
pulumi stack select <n> # 切换栈
pulumi stack output # 查看输出
pulumi config set k v # 设置配置
pulumi refresh # 刷新状态
pulumi import <type> <name> <id> # 导入已有资源
pulumi logs # 查看日志
# === Pulumi vs Terraform 对比 ===
# Terraform: HCL 专用语言,学一门新语言
# Pulumi: Python/TS/Go/Java,用你已经会的语言
# Terraform: plan → apply
# Pulumi: preview → up
# Terraform: module 复用
# Pulumi: class/function 复用(原生编程能力)
# Terraform: 社区更大、资料更多
# Pulumi: IDE 支持更好、可写单元测试
参考:Pulumi 文档 | 更新于 2026 年