Pulumi PHP SDK 实践

解读

国内云原生岗位逐年增多,面试官问“Pulumi PHP SDK 实践”并不是想听概念背诵,而是考察候选人是否真用 PHP 写过“基础设施即代码”(IaC)。
核心诉求有三点:

  1. 你能否把 PHP 项目与多云资源(阿里云、腾讯云、华为云、AWS 中国)打通,实现“一行命令拉起一套环境”;
  2. 你能否把 Pulumi 纳入现有 PHP 研发流程(Composer、GitLab CI、Docker、K8s),让运维与开发使用同一门语言;
  3. 你能否解决国内典型痛点:慢、贵、合规(ICP、等保、跨境数据)。
    面试时,如果只说“Pulumi 是 IaC 工具”会被判为零分;必须给出落地路径、代码片段、踩坑记录与成本优化数字。

知识点

  1. Pulumi 架构:引擎(Go)+ 语言宿主(PHP)+ Provider(TF 插件桥接);理解“PHP 只写程序,引擎干脏活”才能定位性能瓶颈。
  2. 国内 Provider 差异:阿里云 Native Provider 覆盖率 90%,但某些地域的 ECS 规格需要显式设置 systemDiskCategory=cloud_efficiency;腾讯云 CVM 的 instanceType 枚举与官网文档不一致,必须查 pulumi schema
  3. 状态文件托管:国际版默认 Pulumi Cloud,国内必须切到阿里云 OSS + SSE-KMS 加密,否则 200 ms 的 RTT 会让 pulumi up 每次多花 30 s。
  4. Composer 集成:pulumi/pulumi 包依赖 gRPC 扩展,PHP 8.1+ 需要 pecl install grpc 并打开 ffi.enable=true;CI 镜像建议基于 php:8.1-cli-alpine 预编译 .so,把冷启动降到 5 s 内。
  5. 敏感数据:使用 pulumi config set --secret 写入 AK/SK,禁止落盘到 .env;配合阿里云 OIDC 临时凭证,把过期时间设为 15 min,满足等保“最小权限 + 最短时效”。
  6. 资源组织:一个项目(Project)对应一个微服务,堆栈(Stack)用“环境+地域”二维命名,如 dev-cn-beijingprod-cn-shanghai,避免“一套代码管全部”导致爆炸半径过大。
  7. 成本优化:PHP 里用 pulumi.automationApi 提前计算 ecs.InstanceTypes 的按量小时价,低于阈值才创建;夜间通过 CronJob 调用 pulumi destroy --target urn 回收开发环境,每月节省 42% 费用。
  8. 灰度发布:利用 pulumi up --target-dependents 分批更新 K8s Deployment,结合阿里云 SLB 权重,实现“按 10% 流量递增”的无人值守发布。
  9. 故障演练:在 PHP 代码里注入 pulumi.runtime.registerStackTransformation 随机给 ECS 打 chaos=cpu-burn 标签,再由 ChaosMonkey 消费,验证监控告警 < 2 min 到位。
  10. 合规审计:开启阿里云 Config 规则,Pulumi 每次运行后自动触发 config-rule-evaluate,PHP 侧捕获评估结果,写入 ElasticSearch,仪表盘展示“不合规资源 = 0”才能合并 MR。

答案

【场景】公司电商大促前需要 3 套环境:压测、预发、生产,均跑在阿里云华北 3,要求 30 min 内全量交付,日费用 ≤ 500 元。

【项目结构】
iac/
├─ composer.json # 依赖 pulumi/pulumi ^3.12
├─ index.php # 主程序
├─ Pulumi.dev.yaml # dev 堆栈配置
├─ Pulumi.pressure.yaml # 压测堆栈配置
└─ src/
├─ VpcStack.php # 双可用区 VPC
├─ EcsStack.php # ESS 伸缩组 + 抢占式实例
├─ RdsStack.php # PolarDB MySQL Serverless
├─ RedisStack.php # Tair RDB 1G 容量
└─ K8sStack.php # ACK Pro 托管版

【核心代码片段】

<?php
// index.php
require __DIR__ . '/vendor/autoload.php';
use Pulumi\Pulumi;
use Pulumi\AliCloud\Ecs\Instance;
use Pulumi\AliCloud\Ess\ScalingGroup;
use Pulumi\AliCloud\Ess\ScalingConfiguration;
use Pulumi\AliCloud\Vpc\Network;
use Pulumi\AliCloud\Rds\Instance as PolarDB;

// 读取配置
$config = Pulumi::getConfig();
$env = $config->require('env');          // dev|pressure|prod
$region = $config->require('region');    // cn-zhangjiakou

// 创建 VPC
$vpc = new Network("vpc-$env", [
    'cidrBlock' => '10.0.0.0/16',
    'description' => "vpc for $env",
]);

// 抢占式实例配置,最高出价 0.08 元/小时
$scalingConfig = new ScalingConfiguration("sc-$env", [
    'scalingGroupId' => $scalingGroup->id,
    'imageId' => 'centos_8_5_x64_20G_alibase_20221130.vhd',
    'instanceType' => 'ecs.c6.large',
    'spotStrategy' => 'SpotAsPriceGo',
    'spotPriceLimit' => 0.08,
    'systemDiskCategory' => 'cloud_efficiency',
    'userData' => base64_encode(<<<EOF
#!/bin/bash
yum install -y php81 docker
systemctl start docker
docker run --restart=always -p 80:80 registry.cn-beijing.aliyuncs.com/company/app:$env
EOF
    ),
]);

// PolarDB Serverless,最小 1 PCU,最大 8 PCU
$db = new PolarDB("polardb-$env", [
    'dbType' => 'MySQL',
    'dbVersion' => '8.0',
    'payType' => 'Serverless',
    'serverlessConfig' => [
        'minCapacity' => 1,
        'maxCapacity' => 8,
        'autoPause' => true,
        'switchForce' => false,
    ],
    'vswitchId' => $vsw->id,
]);

// 输出
Pulumi::export('vpcId', $vpc->id);
Pulumi::export(' PolarDBConn', $db->connectionString);

【CI/CD】
GitLab CI 使用 pulumi/pulumi-php:3.84 镜像,阶段如下:

  1. composer install --no-dev
  2. pulumi stack select company/iac/$CI_COMMIT_REF_NAME
  3. pulumi preview --diff --non-interactive --suppress-outputs
  4. 人工审批后 pulumi up --yes
  5. 输出资源清单到 COS 桶,供审计。

【踩坑记录】

  1. 抢占式实例在华北 3 下午 4 点价格飙升,被自动释放,解决方案:ESS 多可用区权重 + 5 种实例规格兜底,释放率从 30% 降到 3%。
  2. PolarDB Serverless 首次冷启动 40 s,PHP 连接超时,改长连接 + 连接池,QPS 恢复 95%。
  3. 状态文件放 OSS 后,因 KMS 密钥轮换导致 403,解决:给 CI 角色加 kms:Decrypt 版本权限,而非 *

【结果】
pulumi up 平均 12 min 完成 62 个资源创建,日费用 468 元,比人工控制台搭建节省 73% 时间,大促期间 0 人工干预。

拓展思考

  1. 多云灾备:如何用同一套 PHP 代码在阿里云 + 华为云之间做 MySQL 双向同步,并保证 RPO < 5 min?
  2. 策略即代码:把公司财务部的“预算 1 万元”写成 PHP Policy Pack,一旦 pulumi preview 预测费用超支就拒绝执行,如何与钉钉审批流打通?
  3. GitOps 深度:如果状态文件达到 200 MB,PHP 自动化 API 每次下载 30 s,如何拆分为微堆栈 + Remote State Reference,把计划时间压缩到 10 s 以内?
  4. 安全左移:PHP 开发者习惯把 AK 写到 config.php,如何基于 OpenID Connect + STS 实现“代码零密钥”,并让等保测评老师现场扫描也找不到一条明文?
  5. Serverless 化:把 Pulumi 引擎本身跑在阿里函数计算 PHP Custom Runtime,按次计费,每次 pulumi up 成本 < 0.01 元,如何冷启动 < 3 s?