agents-cli Cloud Run 部署基础设施详解:Terraform 服务配置、Dockerfile 构建、会话类型与网络入口控制
【免费下载链接】agents-cliThe CLI and skills that turn any coding assistant into an expert at creating, evaluating, and deploying AI agents on Google Cloud.项目地址: https://gitcode.com/GitHub_Trending/ag/agents-cli
本文围绕 agents-cli 的 Cloud Run 部署参考文档展开,系统讲解脚手架生成的 Cloud Run Terraform 配置(实例伸缩、并发、会话亲和)、单阶段uvDockerfile 构建、FastAPI 服务入口与路由、三类会话后端(In-memory / Cloud SQL / Agent Runtime)的接入方式,以及 ingress 与 IAP 网络安全策略。读完本文后,你可以准确理解每个脚手架参数的默认值与源码依据,并能在生产环境按源码级细节调整 Cloud Run 部署配置。
前提:本文所有配置均假设项目已通过
/google-agents-cli-scaffold技能(即agents-cli scaffold create/agents-cli scaffold enhance)完成脚手架生成。若项目尚未 scaffold,请先完成脚手架再阅读下文。
一、Cloud Run Terraform 服务配置:伸缩与资源默认值
agents-cli 在脚手架时会将 Cloud Run 基础设施写入deployment/terraform/single-project/service.tf(以及 CI/CD 场景下的cicd/service.tf变体)。仓库中的模板文件位于 service.tf,其中关键的伸缩与资源配置如下:
resources { limits = { cpu = "1" memory = "4Gi" } } max_instance_request_concurrency = 8 scaling { min_instance_count = 1 max_instance_count = 10 } session_affinity = true需要重点理解的四个配置项:
cpu/memory(资源限额):默认cpu = "1"、memory = "4Gi"。注意这里的cpu_idle(CPU 分配策略)由 Cloud Run 平台根据请求是否活跃决定计费方式——Cloud Run 在请求处理期间计费 CPU,空闲时(scale-to-zero 场景)可配置CPU_ALLOCATION_MODE决定是否持续占用 CPU。min_instance_count(冷启动规避):模板中固定为1,意味着生产部署始终保留一个温实例,避免冷启动延迟。与之对应,agents-cli deploy命令的--min-instances默认值是0(默认 scale-to-zero),即agents-cli deploy直接部署时开发/演示 agent 可以缩容到零,而 Terraform 生成的配置则钉在1以保障生产可用性。max_instance_request_concurrency(单实例并发):默认8。单个 uvicorn 进程通过事件循环并发处理请求,吞吐量来自并发度与水平扩容,而非多 worker 进程。session_affinity(会话亲和/粘性路由):默认true,将同一会话的请求路由到同一实例,保证多轮对话状态的一致性。
此外模板中还包含一条关键的lifecycle声明:
# This lifecycle block prevents Terraform from overwriting the container image when it's # updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines) lifecycle { ignore_changes = [ template[0].containers[0].image, ] }从源码结构看,这段注释明确了设计意图:容器镜像由agents-cli deploy/ CI/CD 流水线更新,lifecycle.ignore_changes防止terraform apply把镜像回滚到模板中的占位值(us-docker.pkg.dev/cloudrun/container/hello)。
规格参数的耦合调整(避免 OOM)
参考文档指向/google-agents-cli-deploy技能中的 "Sizing a deployment" 一节,其核心结论在 SKILL.md 中有完整表述,这里一并继承:
- 横向扩展而非纵向扩展:容器只跑一个 async 进程,吞吐来自
--concurrency与--max-instances;只有 profiling 显示事件循环或同步工具调用是 CPU 瓶颈时才提高--cpu。 - 内存约束并发度:每个并发请求在等待模型期间都会驻留完整工作集(上下文窗口、历史、RAG 分片、响应缓冲区),峰值内存 ≈ 基础内存 +
concurrency × 单请求内存。只提高--concurrency而不提高--memory是 OOM 的首要原因。 - 默认并发偏保守:
8是为内存密集型(RAG/多模态)agent 设置的保护值;轻量 agent 压测后可提升到 16–32。
示例——4 倍吞吐要同步放大所有参数:
# 4x throughput: scale every param, not just one agents-cli deploy --cpu 4 --concurrency 16 --memory 16Gi --max-instances 20配合脚手架自带的压测(tests/load_test/,仓库模板见 load_test 目录):驱动负载,观察最大延迟与内存/OOM 重启,再决定调参方向——最大延迟高 → 提高并发;OOM → 加内存或降并发。
二、Dockerfile:基于 uv 的单阶段构建
脚手架生成的 Python 项目使用单阶段构建,依赖管理交给uv。模板文件见 Dockerfile:
FROM python:3.12-slim RUN pip install --no-cache-dir uv==0.8.13 WORKDIR /code COPY ./pyproject.toml ./README.md ./uv.lock* ./ COPY ./app ./app RUN uv sync --frozen ARG AGENT_VERSION=0.0.0 ENV AGENT_VERSION=${AGENT_VERSION} EXPOSE 8080 CMD ["uv", "run", "uvicorn", "app.fast_api_app:app", "--host", "0.0.0.0", "--port", "8080"]逐行要点:
| 配置 | 说明 |
|---|---|
FROM python:3.12-slim | 基础镜像 Python 3.12 精简版,单阶段构建 |
pip install uv==0.8.13 | 版本钉死的uv,保证构建可复现 |
COPY ./pyproject.toml ./uv.lock* | 先拷贝依赖声明与锁文件,利用构建缓存 |
RUN uv sync --frozen | 按uv.lock精确安装依赖,--frozen禁止改写锁文件 |
EXPOSE 8080 | 声明 8080 端口,与 Cloud Run 的--port对应 |
CMD uv run uvicorn ... | 单进程 uvicorn 监听0.0.0.0:8080 |
值得注意的一个可选分支:当项目通过--agent-gateway参数(agents-cli create ... --agent-gateway或agents-cli scaffold enhance . --agent-gateway)开启 Agent Gateway 支持时,模板会在 Dockerfile 中追加ARG AGENT_GATEWAY_ROOT_CERTIFICATES及 CA 信任配置(SSL_CERT_FILE、REQUESTS_CA_BUNDLE、GRPC_DEFAULT_SSL_ROOTS_FILE_PATH),用于在出站流量经 egress gateway 做 TLS 解密检查时信任网关根证书。如果你的项目没有这段内容,说明未启用 Agent Gateway。
三、FastAPI 服务入口与路由
每个脚手架生成的 Python 项目都以uvicorn app.fast_api_app:app在 8080 端口提供服务。具体暴露哪些路由取决于框架,需查看项目根目录的app/fast_api_app.py。
ADK 项目的路由面
以仓库中的 ADK 模板 fast_api_app.py 为例,其结构是:
@contextlib.asynccontextmanager async def lifespan(app: FastAPI) -> AsyncIterator[None]: from {{cookiecutter.agent_directory}}.agent import app as adk_app from {{cookiecutter.agent_directory}}.agent import root_agent runner = Runner( app=adk_app, session_service=services.get_session_service(), artifact_service=services.get_artifact_service(), auto_create_session=True, ) app.state.runner = runner app.state.agent_app_name = adk_app.name await attach_a2a_routes( app, agent=root_agent, runner=runner, task_store=InMemoryTaskStore(), rpc_path=f"/a2a/{adk_app.name}", ) yield app: FastAPI = get_fast_api_app( agents_dir=AGENT_DIR, web=True, artifact_service_uri=services.ARTIFACT_SERVICE_URI, allow_origins=allow_origins, session_service_uri=services.SESSION_SERVICE_URI, otel_to_cloud=otel_to_cloud, lifespan=lifespan, )从源码可以确认 ADK 项目部署后提供:
- ADK HTTP 面:
get_fast_api_app(web=True, ...)挂载/run_sse、/apps/...等 ADK 流式 API 路由; - A2A 路由:
attach_a2a_routes挂载/a2a/{app_name}(JSON-RPC + agent card)——A2A 内建于每个 ADK agent; lifespan中的共享服务:Runner使用services.get_session_service()/services.get_artifact_service(),即下文第四节讨论的会话服务解析逻辑。
另外ALLOW_ORIGINS环境变量可配置 CORS 允许的来源(逗号分隔),默认None即不开启自定义 CORS。
四、会话类型:In-memory / Cloud SQL / Agent Runtime
参考文档给出的三类会话类型对照表如下(会话接线是 ADK 脚手架行为,但其使用的 Cloud SQL 基础设施与框架无关):
| 类型 | 配置方式 | 适用场景 |
|---|---|---|
| In-memory | 默认(shared://session由app_utils/services.py解析为内存实现) | 仅限本地开发;实例重启即丢失 |
| Cloud SQL | 脚手架时传--session-type cloud_sql | 生产级持久化会话(Postgres 15,IAM 认证) |
| Agent Runtime | 托管 Agent Engine 会话(agentengine://{resource_name}) | 使用 Agent Runtime 作为会话后端时 |
参考文档特别指出:cloud_sql/agent_platform_sessions的具体会话 URI 如今是在app_utils/services.py内部构建的,而不是在fast_api_app.py中。仓库模板 services.py 印证了这一设计:
- 文件顶部注册了两个进程级共享 URI:
SESSION_SERVICE_URI = "shared://session"、ARTIFACT_SERVICE_URI = "shared://artifact",通过get_service_registry()注册到 ADK 的服务注册表,使 ADK web 路由、A2A 路径与 reasoning_engine 适配器共享同一实例——在任一路由面上创建的会话对其它路由面可见。 - Cloud SQL 分支(
session_type == "cloud_sql"时生成):从环境变量DB_USER/DB_NAME/DB_PASS/INSTANCE_CONNECTION_NAME读取连接信息,URL 编码后拼出 Unix socket 连接串,走/cloudsql挂载点:
session_service_uri = ( f"postgresql+asyncpg://{encoded_user}:{encoded_pass}@" f"/{db_name}?host=/cloudsql/{encoded_instance}" )若环境变量缺失则优雅降级为InMemorySessionService。
- Agent Platform 会话分支(
session_type == "agent_platform_sessions"):通过agentplatformSDK 按display_name查找或自动创建 engine,返回agentengine://{engine.resource_name}URI;USE_IN_MEMORY_SESSION=true时降级内存。 - 默认分支:优先读
SESSION_SERVICE_URI环境变量;其次若平台注入了GOOGLE_CLOUD_AGENT_ENGINE_ID则构造VertexAiSessionService;否则回退InMemorySessionService。
Cloud SQL 基础设施(Terraform 自动配置)
Cloud SQL 的实例、数据库与 Unix socket 卷挂载全部由service.tf生成(见 service.tf 的session_type == "cloud_sql"条件块):
resource "google_sql_database_instance" "session_db" { name = "${var.project_name}-db" database_version = "POSTGRES_15" region = var.region settings { tier = "db-custom-1-3840" backup_configuration { enabled = false } # Enable IAM authentication database_flags { name = "cloudsql.iam_authentication" value = "on" } } }配套资源还包括:random_password(16 位随机口令)、google_secret_manager_secret+secret_version(口令入 Secret Manager)、google_sql_user(数据库用户)。容器侧则通过volumes { cloud_sql_instance { ... } }挂载 Cloud SQL Unix socket,并以volume_mounts挂到/cloudsql,同时注入INSTANCE_CONNECTION_NAME、DB_PASS(Secret Manager 引用)、DB_NAME、DB_USER环境变量。
手动部署警告:若绕过 Terraform 直接使用
gcloud run deploy --add-cloudsql-instances,必须手动授予运行时服务账号roles/cloudsql.client角色,否则连接会因授权错误失败。Terraform 管理的部署会自动处理该角色绑定。
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="serviceAccount:YOUR_RUNTIME_SA_EMAIL" \ --role="roles/cloudsql.client"五、网络与入口流量控制
Ingress 默认值与收紧方式
模板中默认入口为INGRESS_TRAFFIC_ALL(公网可访问):
resource "google_cloud_run_v2_service" "app" { ingress = "INGRESS_TRAFFIC_ALL" ... }需要收紧时,修改service.tf中的ingress取值:
| 取值 | 含义 |
|---|---|
INGRESS_TRAFFIC_ALL(默认) | 公网入口 |
INGRESS_TRAFFIC_INTERNAL_ONLY | 仅 VPC 内访问 |
INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER | 内部 + GCLB(外部流量经全局负载均衡器) |
IAP(Identity-Aware Proxy)
IAP 可通过部署开关直接启用,仅适用于 Cloud Run 目标:
agents-cli deploy --iap从 cmd_deploy.py 源码可以看到--iap被声明为is_flag=True、default=False的选项,帮助文本为 "Enable Identity-Aware Proxy (Cloud Run)",构造gcloud命令时若该标志为真则追加--iap参数。要点:
- IAP 由deploy 标志配置,而不是生成的 Terraform 变量——因此
service.tf中看不到 IAP 配置; - 启用后无需改任何代码即可要求请求携带 Google 身份认证;
- 用户/群组授权需在 Cloud Console 的 IAP 设置中管理。
VPC Connector
VPC connector默认不配置。若 agent 需要访问 VPC 内的私有资源(私有 Cloud SQL、内部 API 等),需要自行在自定义 Terraform 中添加 VPC egress 配置(参见references/terraform-patterns.md的自定义基础设施模式)。
其它网络相关能力(补充)
- 回滚:Cloud Run 支持基于 revision 的即时流量切换回滚(
gcloud run revisions list+gcloud run services update-traffic),无需新提交; - 未认证测试:脚手架默认
--no-allow-unauthenticated,直接curl已部署服务时 403 属预期行为,需携带Authorization: Bearer $(gcloud auth print-identity-token)请求头。
六、部署验证与日志排查
部署后可用agents-cli run --url <service-url>直接对已部署的 Cloud Run 服务发起带认证、会话与流式处理支持的请求;更深入的测试(自定义头、会话复用、压测)参见同技能的references/testing-deployed-agents.md(仓库路径 testing-deployed-agents.md)。
常见问题速查(摘自 SKILL.md 故障排查表,与 Cloud Run 强相关项):
| 问题 | 解决方案 |
|---|---|
| 冷启动太慢 | 将 Cloud Run Terraform 配置中min_instance_count设为 > 0 |
| Cloud Run 503 | 检查资源限额(内存/CPU),提高max_instance_count,或查看容器崩溃日志 |
| Cloud SQL 连接失败 / 403 | 手动部署时确认运行时服务账号已授roles/cloudsql.client |
| 部署失败或 agent 无响应 | 查 Cloud Logging:gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=SERVICE" --project=PROJECT --limit=50 |
| 刚授完 IAM 角色仍 403 | IAM 传播非即时,等待几分钟再重试,不要反复重复授权 |
小结
Cloud Run 作为 agents-cli 三大部署目标之一(另两个为 Agent Runtime 与 GKE),其脚手架模板在仓库中集中在 cloud_run 部署目标目录 下,按python/go/java/typescript分语言提供single-project与cicd两套 Terraform 变体。核心事实可以归纳为:
- 资源默认值:
cpu=1、memory=4Gi、concurrency=8、min=1/max=10实例、session_affinity=true,全部可在 service.tf 中查看与修改; - 构建:
python:3.12-slim+ 钉版uv的单阶段 Dockerfile,uv sync --frozen保证可复现; - 服务面:
uvicorn app.fast_api_app:app监听 8080;ADK 项目额外提供/run_sse、/apps/...与/a2a/{app_name}路由; - 会话:内存(默认)/ Cloud SQL(Postgres 15 + IAM 认证 + Secret Manager + Unix socket 卷)/ Agent Engine(
agentengine://)三选一,URI 解析集中在app_utils/services.py; - 网络:默认公网 ingress,可收紧为 VPC 内部;IAP 由
agents-cli deploy --iap一键启用;VPC connector 需自定义 Terraform。
如需完整部署流程(flag 全表、CI/CD 流水线、Secret Manager 接入、服务账号架构),请继续阅读同目录的 SKILL.md 与 terraform-patterns.md。
【免费下载链接】agents-cliThe CLI and skills that turn any coding assistant into an expert at creating, evaluating, and deploying AI agents on Google Cloud.项目地址: https://gitcode.com/GitHub_Trending/ag/agents-cli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考