在本地运行 Pulumi 管理 GCP 资源
用 CI/CD 流水线部署 GCP 基础设施,是 Cloud Engineering 的正道:比如 GitHub Actions 配合 Workload Identity Federation,把身份、权限、审计都收敛到流水线里,本地不必持有长期凭据。但在学习阶段,或者线上出了故障需要紧急手工修一把时,从本地跑 Pulumi 依然很实用。
麻烦往往出在本地认证上。Pulumi 的 GCP Provider 在没有显式配置时,会回退到 Application Default Credentials(ADC);而在企业环境里,这条路径经常被组织策略挡住,需要 Google Workspace 或 Cloud 管理员放行。本文记录一个更轻的技巧:复用 gcloud 已经登录的身份,打印一个临时访问令牌并导出成环境变量,就能让本地 Pulumi 直接跑起来。
常规的本地认证方式
Pulumi 的 GCP Provider 支持几种认证方式。本地开发时官方推荐的是先登录 ADC:
gcloud auth application-default login它会把用户凭据写进 ADC 文件,供 Pulumi 等客户端库读取。另一条路是创建服务账号密钥,再通过 GOOGLE_APPLICATION_CREDENTIALS 指向密钥文件。若没有配置任何凭据,Provider 最后才会回退到 ADC。
在企业环境里,这两条路都可能走不通:
- 创建服务账号密钥通常被组织策略禁用,例如约束
constraints/iam.disableServiceAccountKeyCreation。 - ADC 登录、以及在组织中放行某些认证方式,往往需要管理员操作。
于是就出现了”本地跑 Pulumi 还得找管理员开权限”的尴尬。下面这个技巧绕开了这些步骤:既不创建密钥,也不单独登录 ADC,只是复用 gcloud 已登录的用户身份。
技巧:用 gcloud 的临时访问令牌
前提是本机已经用 gcloud auth login 登录过,并且该账号本身能访问目标项目。
打印访问令牌
gcloud auth print-access-token它会打印当前 gcloud 活跃账号的 OAuth 2.0 访问令牌。
导出为 Pulumi 读取的环境变量
export GOOGLE_OAUTH_ACCESS_TOKEN="$(gcloud auth print-access-token)"这里有两个容易混淆的环境变量,值得单独说清楚:
GOOGLE_OAUTH_ACCESS_TOKEN:Pulumi 的 GCP Provider 读取的变量,对应 provider 的accessToken配置。CLOUDSDK_AUTH_ACCESS_TOKEN:gcloud CLI 自身读取的变量。
如果导出的是后者,gcloud 命令会正常使用它,但 Pulumi 依然认不出——这也是我一开始记不清”到底是哪个变量”的原因。
指定项目并执行
export GOOGLE_PROJECT="your-gcp-project-id"pulumi upGOOGLE_PROJECT 是 Provider 读取项目的环境变量之一;按其优先级依次还有 GOOGLE_CLOUD_PROJECT、GCLOUD_PROJECT、CLOUDSDK_CORE_PROJECT。当然,也可以在 Pulumi.<stack>.yaml 里用 gcp:project 指定项目。
这样一来,Pulumi 就用自己的用户身份调用 GCP API,不再需要单独配置 ADC 或服务账号密钥。pulumi preview、pulumi refresh、pulumi import 等命令同理,都能直接用这套凭据。
注意事项
- 令牌有有效期,默认 1 小时。Pulumi 命令要在有效期内跑完;超时就重新执行
gcloud auth print-access-token并重新导出即可。 - Pulumi 不会自动刷新这个令牌,它和 Terraform 的
access_token一样,只是拿来即用、过期作废。 - 不要把令牌写进代码或提交到 Git。临时会话用环境变量最省事;若一定要落到 Pulumi 配置里,至少用
pulumi config set --secret。 - 本文的环境变量技巧适用于
pulumi-gcp(classic)Provider。若你用的是较新的pulumi-google-native,它不读GOOGLE_OAUTH_ACCESS_TOKEN,需要把令牌通过pulumi config set放进 Provider 配置里。
先提权:用 PAM 临时拿权限
在权限收紧的组织里,日常账号通常没有部署所需的角色,需要先提权。Google Cloud 的 Privileged Access Manager(PAM)提供”按需、限时、可审批”的临时授权,正好适合这种场景。
先搜索自己可以申请的 entitlement:
gcloud pam entitlements search \ --caller-access-type=grant-requester \ --location=global \ --project="your-gcp-project-id"再发起授权申请,例如申请 1 小时:
gcloud pam grants create \ --entitlement="ENTITLEMENT_ID" \ --requested-duration=3600s \ --justification="emergency hotfix"如果 entitlement 配置了审批,还需要审批人执行:
gcloud pam grants approve GRANT_NAME --reason="approved"授权生效后,再用上面的方式打印令牌并运行 Pulumi 命令(例如 pulumi up)。GCP 在每次调用 API 时都会按当前 IAM 角色鉴权,因此 PAM 临时授予的角色会一并生效。
提示:
gcloud pam的部分子命令目前仍处于 beta / alpha,参数可能变化,以本机gcloud pam --help为准。
小结
- CI/CD 流水线仍是默认路径,Workload Identity Federation 能免去本地长期凭据。
- 需要在本地临时操作时,用
gcloud auth print-access-token配合GOOGLE_OAUTH_ACCESS_TOKEN最省事,无需 ADC 或服务账号密钥。 - 权限不够就先用 PAM 做限时提权。
- 令牌短命、用完即弃;事情处理完,回到流水线。