如何用 Terraform 在 GCP Cloud Run 部署 LiteLLM Proxy 并解决 GHCR 镜像拉取问题
LiteLLM 仓库自带一套 Terraform 模块(terraform/litellm/gcp),可以把组件化的 LiteLLM Proxy 一次性部署到 GCP:Cloud Run v2 上跑 gateway(端口 4000)、backend(4001)、ui(3000)三个服务,外加 Cloud SQL for PostgreSQL(写入实例 + 跨区只读副本)、Memorystore Redis(缓存与限流)、GCS 桶、Secret Manager 条目,以及一个外部全局 HTTP(S) 负载均衡器。数据库迁移通过一个一次性 Cloud Run Job(litellm-migrations)执行 prisma migrate deploy 完成。
这条路径中有一个必须先解决的前置问题:四个镜像(litellm-gateway、litellm-backend、litellm-ui、litellm-migrations)发布在 GHCR 上,而 Cloud Run 只接受 Artifact Registry、[region.]gcr.io 或 docker.io 的镜像,会在 apply 阶段直接拒绝 ghcr.io URI。下面的步骤就是围绕打通这一点展开的。
准备条件
- 一个已开启 billing 的 GCP 项目。这套栈会创建付费资源(Cloud SQL、Memorystore、LB anycast IP)。
gcloud已完成认证(gcloud auth login)。- 目标项目中启用以下 9 个 API(可直接执行):
gcloud services enable \
run.googleapis.com \
sqladmin.googleapis.com \
redis.googleapis.com \
secretmanager.googleapis.com \
vpcaccess.googleapis.com \
compute.googleapis.com \
servicenetworking.googleapis.com \
storage.googleapis.com \
artifactregistry.googleapis.com
解决 GHCR 镜像拉取:创建 Artifact Registry 直通仓库
在目标项目中创建指向 GHCR 的 remote 仓库(每个项目只需做一次):
gcloud artifacts repositories create litellm \
--repository-format=docker \
--location=us-central1 \
--mode=remote-repository \
--remote-repo-config-desc="GitHub Container Registry passthrough" \
--remote-docker-repo=https://ghcr.io
如果仓库已存在,该命令会退出并报错,此时直接继续即可。之后 Cloud Run 拉镜像会走这个 remote 仓库,由 GCP 侧透传到 GHCR。
仓库文档同时说明了两个容易踩的细节:
- 栈创建的运行时 service account 不需要
roles/artifactregistry.reader权限——Cloud Run 拉镜像用的是项目级 serverless agent(service-<project-num>@serverless-robot-prod.iam.gserviceaccount.com),不是运行时 SA。 - 如果环境完全离线,可以不走 remote 仓库,改为把镜像
docker pull/docker tag/docker push到一个普通 AR 仓库,然后把image_registry设为不带/berriai后缀的路径(镜像布局里没有 org 段)。
配置 terraform.tfvars 并执行部署
examples/default/ 是一个薄入口:配置 google / google-beta provider 并调用上层模块(入口),一键部署路径如下:
cd terraform/litellm/gcp/examples/default
cp terraform.tfvars.example terraform.tfvars
terraform init
terraform apply
terraform.tfvars 中需要编辑的关键项(完整字段见 terraform.tfvars.example 的注释):
project_id = "my-gcp-project" # 替换为你的 GCP 项目 ID
region = "us-central1"
tenant = "acme" # 所有资源名的前缀:${tenant}-litellm-${env}
env = "stage"
# 必须设置:指向上面创建的 Artifact Registry remote 仓库
image_registry = "us-central1-docker.pkg.dev/my-gcp-project/litellm/berriai"
image_tag = "v1.86.0-dev"
image_registry 不能保留默认值 ghcr.io/berriai——默认值只是为了让本地 terraform plan 能跑通,真实部署时 Cloud Run 会在 apply 时拒绝它。四个 litellm-<component>:${image_tag} 镜像 URI 就是由 image_registry + image_tag 拼出来的,升级 LiteLLM 时两个变量要一起升。只有需要单独固定某个组件镜像时,才在 examples/default/main.tf 的 module "litellm" 块里直接设置 gateway_image / backend_image / ui_image / migrations_image 覆盖(示例层没有把这些暴露成变量)。
密钥类输入建议用环境变量而不是写进 tfvars,因为写进 tfvars 的值会进入 terraform.tfstate:
export TF_VAR_litellm_master_key="sk-..." # 可选;省略时栈自动生成随机 sk-… 值
export TF_VAR_litellm_license="lic-..." # 可选;省略则 OSS-only 运行
export TF_VAR_ui_password="..." # 可选;省略时 UI 登录回落到 master key
首次 terraform apply 大约需要 20–25 分钟,其中大部分时间花在 Cloud SQL 创建上。顺序是:依赖资源就绪 → 迁移 Job 自动执行 prisma migrate deploy → 之后 gateway / backend / ui 才开始对外服务。apply 返回时栈已可接流量。
可选的 1-click 路径:GCP Cloud Shell 内置了 DeployStack 安装器,回答项目、区域、tenant、env、image tag、image_registry、TLS 等提示后由它执行 terraform apply,提示定义见 deploystack.json。
验证部署结果
terraform output lb_url
lb_url 是 Proxy 的对外地址:dashboard 在 /,API 在 /v1/*。HTTP-only 试用部署下它是 http://<lb-ip> 形式。
UI 登录账号是 admin,密码是 master key。如果部署时自动生成了 master key,用下面命令从 Secret Manager 读出来:
gcloud secrets versions access latest \
--secret="$(terraform output -raw master_key_secret_id)"
其他常用输出:lb_ip(LB anycast IP)、gateway_service_url / backend_service_url / ui_service_url(绕过 LB 的 Cloud Run 直连地址)、migration_run_command(迁移 Job 的 break-glass 手动重跑命令)。
从 HTTP 切到 TLS
默认情况下 terraform plan 会拒绝只建 HTTP 的 LB——TLS 才是受支持的状态。两种走法:
试用 / 开发(HTTP-only):显式设置 allow_plaintext_lb = true 且保持 lb_domains = []。不加这个 flag 而 lb_domains 为空时,plan 会报指向 precondition 的明确错误。
生产 / 预发(Google 托管证书):
- 先用
allow_plaintext_lb = trueapply 一次,读出 anycast IP:terraform output -raw lb_ip; - 把要使用的 DNS 域名 A 记录指向该 IP;
- 设置
lb_domains = ["proxy.example.com"],移除allow_plaintext_lb,重新 apply。
结果是 443 forwarding rule 挂上覆盖每个域名的托管证书,80 端口改写为 301 到 HTTPS。首次 apply 后托管证书会处于 PROVISIONING 状态约 15–60 分钟(等 DNS 传播),可以用 gcloud compute ssl-certificates describe <tenant>-litellm-<env>-cert 查看状态。
后续:添加模型 provider 的 API key
provider 密钥(OpenAI、Anthropic 等)放 Secret Manager,而不是 tfvars。先建 secret:
echo -n "sk-proj-..." | gcloud secrets create openai-api-key --data-file=-
然后在 terraform.tfvars 中引用它的资源 ID(Cloud Run 运行时 SA 会自动获得该 secret 的 roles/secretmanager.secretAccessor),并在 proxy_config 里通过环境变量名引用它:
gateway_extra_secrets = {
OPENAI_API_KEY = "projects/my-gcp-project/secrets/openai-api-key"
}
proxy_config = {
model_list = [
{
model_name = "gpt-4o"
litellm_params = {
model = "openai/gpt-4o"
api_key = "os.environ/OPENAI_API_KEY"
}
},
]
}
注意 secret 只传裸资源 ID(projects/.../secrets/openai-api-key),不能带 /versions/3 这样的版本后缀——secret_key_ref 绑定和 IAM 授权都会拒绝,版本恒定为 latest。改完重新 terraform apply。proxy_config 会被编码成 YAML 上传到专用 GCS 桶并以 gcsfuse 只读挂载到 gateway 和 backend 的 /etc/litellm;配置内容的 hash 作为环境变量随行,保证编辑配置就触发新 revision。
限制与清理
- 数据保留保护:
cloudsql_deletion_protection默认为true(destroy 时拒绝删库),gcs_force_destroy默认为false(拒绝销毁非空桶)。只有临时 / CI 栈才应把它们翻转,且意味着接受数据丢失。 - 数据库认证方式:栈使用密码认证(随机密码存 Secret Manager,容器 entrypoint 在启动 uvicorn 前拼装
DATABASE_URL,密码不出现在服务 spec 和日志里),而不是 GCP IAM 认证。如需 IAM 认证,文档给出的方向是在 Cloud Run v2 的多容器能力下加cloud-sql-proxysidecar 走 Unix socket,并替换密码式 URL。 - 多租户:
(tenant, env)对不同的栈可以在同一项目内并存(例如acme-litellm-stage-gateway与globex-litellm-dev-license);但模块未声明configuration_aliases,for_each只能在一个项目内扇出多租户,跨项目/区域需要每项目一个 root。 - 完整输入变量参考 variables.tf,模块各
.tf文件分工见 terraform/litellm/gcp/README.md 的 Files 表格;分步教程见 TUTORIAL.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00