1. 简介
概览
在本实验中,您将部署一个生产就绪的智能体开发套件 (ADK) 智能体,该智能体具有 GPU 加速的 Gemma 后端。重点在于关键部署模式:设置启用 GPU 的 Cloud Run 服务、将模型后端与 ADK 代理集成,以及在负载下观察自动扩缩行为。
您将执行的操作
在本实验中,您将重点学习以下关键的生产环境部署方面:
- 将 Gemma 部署到支持 GPU 的 Cloud Run - 设置高性能 Gemma 模型后端
- 将 Gemma 部署与 ADK 代理集成 - 将代理连接到 GPU 加速模型
- 使用 ADK Web 界面进行测试 - 验证对话式智能体是否正常运行
- 执行负载测试 - 观察两个 Cloud Run 实例在负载下如何自动扩缩
重点在于生产部署模式,而不是广泛的代理开发。
学习内容
- 将 GPU 加速的 Gemma 模型部署到 Cloud Run 以供生产环境使用
- 将外部模型部署与 ADK 代理集成
- 配置和测试可用于生产环境的 AI 代理部署
- 了解 Cloud Run 在负载下的自动扩缩行为
- 观察多个 Cloud Run 实例在流量高峰期间如何协调工作
- 应用负载测试来验证性能和自动扩缩
2. 项目设置
- 如果您还没有 Google 账号,则必须先创建一个 Google 账号。
- 请改用个人账号,而不是工作账号或学校账号。工作账号和学校账号可能存在限制,导致您无法启用本实验所需的 API。
- 登录 Google Cloud 控制台。
- 在 Cloud 控制台中启用结算功能。
- 完成本实验的 Cloud 资源费用应不到 1 美元。
- 您可以按照本实验结束时的步骤删除资源,以避免产生更多费用。
- 新用户符合参与 $300 USD 免费试用计划的条件。
- 创建新项目或选择重复使用现有项目。
3. 打开 Cloud Shell Editor
- 点击此链接可直接前往 Cloud Shell 编辑器
- 如果系统在今天任何时间提示您进行授权,请点击授权继续。
- 如果终端未显示在屏幕底部,请打开它:
- 点击查看
- 点击终端
- 在终端中,使用以下命令设置项目:
- 格式:
gcloud config set project [PROJECT_ID]
- 示例:
gcloud config set project lab-project-id-example
- 如果您不记得项目 ID,请执行以下操作:
- 您可以使用以下命令列出所有项目 ID:
gcloud projects list | awk '/PROJECT_ID/{print $2}'
- 您可以使用以下命令列出所有项目 ID:
- 格式:
- 您应会看到以下消息:
如果您看到Updated property [core/project].
WARNING
并被问到Do you want to continue (Y/n)?
,则很可能是您输入的项目 ID 有误。按n
,按Enter
,然后尝试再次运行gcloud config set project
命令。
4. 启用 API 并设置默认区域
在部署支持 GPU 的 Cloud Run 服务之前,我们需要启用所需的 Google Cloud API 并配置项目设置。
- 在终端中,启用以下 API:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com
如果系统提示您进行授权,请点击授权继续。
此命令可能需要几分钟时间才能完成,但最终应会生成类似如下所示的成功消息:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
- 设置默认 Cloud Run 区域。
gcloud config set run/region europe-west1
5. 准备 Python 项目
我们来设置包含 Gemma 后端和 ADK 代理服务的基本结构的起始代码。
- 克隆初始代码库:
cd ~ git clone https://github.com/amitkmaraj/accelerate-ai-lab3-starter.git cd accelerate-ai-lab3-starter
- 查看项目结构:
您应该会看到以下初始结构:ls -R
accelerate-ai-lab3-starter/ ├── README.md # Project overview ├── ollama-backend/ # Ollama backend (separate deployment) │ └── Dockerfile # Backend container (🚧 to implement) └── adk-agent/ # ADK agent (separate deployment) ├── pyproject.toml # Python dependencies (✅ completed) ├── server.py # FastAPI server (🚧 to implement) ├── Dockerfile # Container config (🚧 to implement) ├── load_test.py # Load testing (🚧 to implement) └── production_agent/ # Agent implementation ├── __init__.py # Package init (✅ completed) └── agent.py # Agent logic (🚧 to implement)
6. 架构概览
在实现之前,我们先来了解一下双服务架构:
关键洞见:在负载测试期间,您会发现这两个服务会独立扩缩 - GPU 后端(瓶颈服务)会扩缩到 1-3 个实例以处理推理负载,而 ADK 代理会保持在 1 个实例以处理请求。
7. 将 Gemma 后端部署到支持 GPU 的 Cloud Run
第一个关键步骤是部署 GPU 加速的 Gemma 模型,该模型将作为 ADK 代理的大脑。在需要单独的微调模型或需要隔离扩缩的架构中,分离式已部署的 LLM 可能更具优势。
- 导航到 Ollama 后端目录:
cd ollama-backend
- 打开并实现 Ollama Dockerfile:
将 TODO 注释替换为:cloudshell edit Dockerfile
🔧 此工具的作用:FROM ollama/ollama:latest # Listen on all interfaces, port 8080 ENV OLLAMA_HOST 0.0.0.0:8080 # Store model weight files in /models ENV OLLAMA_MODELS /models # Reduce logging verbosity ENV OLLAMA_DEBUG false # Never unload model weights from the GPU ENV OLLAMA_KEEP_ALIVE -1 # Store the model weights in the container image ENV MODEL gemma3:270m RUN ollama serve & sleep 5 && ollama pull $MODEL # Start Ollama ENTRYPOINT ["ollama", "serve"]
- 使用官方 Ollama 映像作为基础
- 将
OLLAMA_HOST
设置为接受来自任何 IP 地址的连接 - 公开端口 8080
- 部署支持 GPU 的 Gemma 后端:
gcloud run deploy ollama-gemma3-270m-gpu \
--source . \
--region europe-west1 \
--concurrency 4 \
--cpu 8 \
--set-env-vars OLLAMA_NUM_PARALLEL=4 \
--gpu 1 \
--gpu-type nvidia-l4 \
--max-instances 3 \
--memory 16Gi \
--allow-unauthenticated \
--no-cpu-throttling \
--no-gpu-zonal-redundancy \
--timeout 600 \
--labels dev-tutorial=codelab-agent-gpu
如果您收到“从源代码进行部署需要 Artifact Registry Docker 代码库来存储构建的容器。系统会显示一条消息,指出“将在 [europe-west1] 区域中创建一个名为 [cloud-run-source-deploy] 的代码库”,请继续。
⚙️ 主要配置说明:
- GPU:NVIDIA L4,因其在推理工作负载方面具有出色的性价比而入选。L4 提供 24 GB GPU 内存和优化的张量运算,非常适合用于 2.7 亿参数模型(例如 Gemma)
- 内存:16 GB 系统内存,用于处理模型加载、CUDA 操作和 Ollama 的内存管理
- CPU:8 个核心,可实现最佳 I/O 处理和预处理任务
- 并发性:每个实例 4 个请求,可在吞吐量和 GPU 内存用量之间实现平衡
- 超时:600 秒,可满足初始模型加载和容器启动的需求
💰 费用注意事项:GPU 实例比仅使用 CPU 的实例贵得多(每小时约 2-4 美元,而后者每小时约 0.10 美元)。--max-instances 1
设置有助于防止不必要的 GPU 实例扩缩,从而控制费用。
- 等待部署完成,并记下服务网址:
export OLLAMA_URL=$(gcloud run services describe ollama-gemma3-270m-gpu \ --region=europe-west1 \ --format='value(status.url)') echo "🎉 Gemma backend deployed at: $OLLAMA_URL"
8. 实现 ADK 代理集成
现在,我们来创建一个连接到已部署的 Gemma 后端的最小 ADK 代理。
- 前往 ADK 代理目录:
cd ../adk-agent
- 打开并实现代理配置:
将所有 TODO 注释替换为此极简实现:cloudshell edit production_agent/agent.py
🔧 此工具的作用:import os from pathlib import Path from dotenv import load_dotenv from google.adk.agents import Agent from google.adk.models.lite_llm import LiteLlm import google.auth # Load environment variables root_dir = Path(__file__).parent.parent dotenv_path = root_dir / ".env" load_dotenv(dotenv_path=dotenv_path) # Configure Google Cloud try: _, project_id = google.auth.default() os.environ.setdefault("GOOGLE_CLOUD_PROJECT", project_id) except Exception: pass os.environ.setdefault("GOOGLE_CLOUD_LOCATION", "europe-west1") # Configure model connection gemma_model_name = os.getenv("GEMMA_MODEL_NAME", "gemma3:270m") # Production Gemma Agent - GPU-accelerated conversational assistant gemma_agent = Agent( model=LiteLlm(model=f"ollama_chat/{gemma_model_name}"), name="gemma_agent", description="A production-ready conversational assistant powered by GPU-accelerated Gemma.", instruction="""You are 'Gem', a friendly, knowledgeable, and enthusiastic zoo tour guide. Your main goal is to make a zoo visit more fun and educational for guests by answering their questions. You can provide general information and interesting facts about different animal species, such as: - Their natural habitats and diet. 🌲🍓 - Typical lifespan and behaviors. - Conservation status and unique characteristics. IMPORTANT: You do NOT have access to any tools. This means you cannot look up real-time, specific information about THIS zoo. You cannot provide: - The names or ages of specific animals currently at the zoo. - The exact location or enclosure for an animal. - The daily schedule for feedings or shows. Always answer based on your general knowledge about the animal kingdom. Keep your tone cheerful, engaging, and welcoming for visitors of all ages. 🦁✨""", tools=[], # Gemma focuses on conversational capabilities ) # Set as root agent root_agent = gemma_agent
- 通过 LiteLlm 连接到已部署的 Gemma 后端
- 创建简单的对话式智能体
- 配置 Google Cloud 集成
- 打开并实现 FastAPI 服务器:
将所有 TODO 注释替换为:cloudshell edit server.py
🔧 此工具的作用:import os from dotenv import load_dotenv from fastapi import FastAPI from google.adk.cli.fast_api import get_fast_api_app # Load environment variables load_dotenv() AGENT_DIR = os.path.dirname(os.path.abspath(__file__)) app_args = {"agents_dir": AGENT_DIR, "web": True} # Create FastAPI app with ADK integration app: FastAPI = get_fast_api_app(**app_args) # Update app metadata app.title = "Production ADK Agent - Lab 3" app.description = "Gemma agent with GPU-accelerated backend" app.version = "1.0.0" @app.get("/health") def health_check(): return {"status": "healthy", "service": "production-adk-agent"} @app.get("/") def root(): return { "service": "Production ADK Agent - Lab 3", "description": "GPU-accelerated Gemma agent", "docs": "/docs", "health": "/health" } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8080, log_level="info")
- 创建与 ADK 集成的 FastAPI 服务器
- 启用用于测试的 Web 界面
- 提供健康检查端点
- 打开并实现 Dockerfile:
将所有 TODO 注释替换为:cloudshell edit Dockerfile
技术选择说明:FROM python:3.13-slim # Copy uv from the official image COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv # Install system dependencies RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* # Set working directory WORKDIR /app # Copy all files COPY . . # Install Python dependencies RUN uv sync # Expose port EXPOSE 8080 # Run the application CMD ["uv", "run", "uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8080"]
- uv:比 pip 快 10-100 倍的现代 Python 软件包管理器。它使用全局缓存和并行下载,可显著缩短容器构建时间
- Python 3.13-slim:最新的 Python 版本,具有最少的系统依赖项,可减小容器大小和攻击面
- 多阶段构建:从官方映像复制 uv 可确保我们获得最新的优化二进制文件
9. 配置环境并部署代理
现在,我们将配置 ADK 代理以连接到已部署的 Gemma 后端,并将其部署为 Cloud Run 服务。这包括设置环境变量并部署具有正确配置的代理。
- 设置环境配置:
cat << EOF > .env GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) GOOGLE_CLOUD_LOCATION=europe-west1 GEMMA_MODEL_NAME=gemma3:270m OLLAMA_API_BASE=$OLLAMA_URL EOF
了解 Cloud Run 中的环境变量
环境变量是键值对,可在运行时配置应用。它们特别适用于以下情况:
- API 端点和服务网址(例如我们的 Ollama 后端)
- 在不同环境(开发、预演、生产)之间发生变化的配置
- 不应进行硬编码的敏感数据
部署 ADK 智能体:
export PROJECT_ID=$(gcloud config get-value project)
gcloud run deploy production-adk-agent \
--source . \
--region europe-west1 \
--allow-unauthenticated \
--memory 4Gi \
--cpu 2 \
--max-instances 1 \
--concurrency 10 \
--timeout 300 \
--set-env-vars GOOGLE_CLOUD_PROJECT=$PROJECT_ID \
--set-env-vars GOOGLE_CLOUD_LOCATION=europe-west1 \
--set-env-vars GEMMA_MODEL_NAME=gemma3:270m \
--set-env-vars OLLAMA_API_BASE=$OLLAMA_URL \
--labels dev-tutorial=codelab-agent-gpu
⚙️ 主要配置:
- 自动扩缩:固定为 1 个实例(轻量级请求处理)
- 并发:每个实例 10 个请求
- 内存:4GB(适用于 ADK 代理)
- 环境:连接到 Gemma 后端
🔒 安全注意事项:为简单起见,本实验使用 --allow-unauthenticated
。在生产环境中,请使用以下方法实现适当的身份验证:
- 使用服务账号进行 Cloud Run 服务到服务身份验证
- Identity and Access Management (IAM) 政策
- 用于外部访问的 API 密钥或 OAuth
- 考虑使用
gcloud run services add-iam-policy-binding
来控制访问权限
获取代理服务网址:
export AGENT_URL=$(gcloud run services describe production-adk-agent \
--region=europe-west1 \
--format='value(status.url)')
echo "🎉 ADK Agent deployed at: $AGENT_URL"
根据 Cloud Run 环境变量文档,✅ 环境变量最佳实践:
- 避免使用预留变量:请勿设置
PORT
(Cloud Run 会自动设置此变量)或以X_GOOGLE_
开头的变量 - 使用描述性名称:为变量添加前缀以避免冲突(例如,
GEMMA_MODEL_NAME
,而非MODEL
) - 转义英文逗号:如果您的值包含英文逗号,请使用其他分隔符:
--set-env-vars "^@^KEY1=value1,value2@KEY2=..."
- 更新与替换:使用
--update-env-vars
可添加/更改特定变量,而不会影响其他变量
如何在 Cloud Run 中设置变量:
- 来自文件:
gcloud run deploy SERVICE_NAME --env-vars-file .env --labels dev-tutorial codelab-adk
(从文件加载多个变量) - 多个标志:对于无法以英文逗号分隔的复杂值,请重复使用
--set-env-vars
10. 使用 ADK Web 界面进行测试
部署完这两项服务后,接下来需要验证 ADK 代理是否可以成功与 GPU 加速的 Gemma 后端通信并响应用户查询。
- 测试健康端点:
您应该会看到:curl $AGENT_URL/health
{ "status": "healthy", "service": "production-adk-agent" }
- 在新的浏览器标签页中输入
production-adk-agent
的网址,与您的代理互动。您应该会看到 ADK 网页界面。 - 不妨使用以下示例对话测试您的代理:
- “小熊猫在野外通常吃什么?”
- “你能告诉我一些关于雪豹的趣闻吗?”
- “为什么箭毒蛙的颜色如此鲜艳?”
- “我在动物园的哪里可以找到新出生的小袋鼠?”
- 代理会使用您部署的 Gemma 模型进行回答。您可以通过查看已部署的 Gemma 服务的日志来验证这一点。我们将在下一部分中执行此操作
- 回答由 GPU 加速的后端生成
- 网页界面提供简洁的聊天体验
11. 实现并运行负载测试
为了解生产部署如何处理实际流量,我们将实施全面的负载测试,以触发 ADK 代理和 GPU 后端服务之间的自动扩缩。
- 打开并实现负载测试脚本:
将 TODO 注释替换为:cloudshell edit load_test.py
🔧 此工具的作用:import random import uuid from locust import HttpUser, task, between class ProductionAgentUser(HttpUser): """Load test user for the Production ADK Agent.""" wait_time = between(1, 3) # Faster requests to trigger scaling def on_start(self): """Set up user session when starting.""" self.user_id = f"user_{uuid.uuid4()}" self.session_id = f"session_{uuid.uuid4()}" # Create session for the Gemma agent using proper ADK API format session_data = {"state": {"user_type": "load_test_user"}} self.client.post( f"/apps/production_agent/users/{self.user_id}/sessions/{self.session_id}", headers={"Content-Type": "application/json"}, json=session_data, ) @task(4) def test_conversations(self): """Test conversational capabilities - high frequency to trigger scaling.""" topics = [ "What do red pandas typically eat in the wild?", "Can you tell me an interesting fact about snow leopards?", "Why are poison dart frogs so brightly colored?", "Where can I find the new baby kangaroo in the zoo?", "What is the name of your oldest gorilla?", "What time is the penguin feeding today?" ] # Use proper ADK API format for sending messages message_data = { "app_name": "production_agent", "user_id": self.user_id, "session_id": self.session_id, "new_message": { "role": "user", "parts": [{ "text": random.choice(topics) }] } } self.client.post( "/run", headers={"Content-Type": "application/json"}, json=message_data, ) @task(1) def health_check(self): """Test the health endpoint.""" self.client.get("/health")
- 会话创建:使用正确的 ADK API 格式,通过 POST 请求发送到
/apps/production_agent/users/{user_id}/sessions/{session_id}
。创建session_id
和user_id
后,可以向代理发出请求。 - 消息格式:遵循 ADK 规范,包含
app_name
、user_id
、session_id
和结构化new_message
对象 - 对话端点:使用
/run
端点一次性收集所有事件(建议用于负载测试) - 实际负载:创建等待时间较短的对话负载,以触发自动扩缩
- 会话创建:使用正确的 ADK API 格式,通过 POST 请求发送到
- 安装依赖项:
uv sync pip install locust
- Locust 是一款基于 Python 的开源负载测试工具,旨在对 Web 应用和其他系统进行性能和负载测试。它的主要特点是使用标准 Python 代码定义测试场景和用户行为,与依赖图形界面或特定于网域的语言的工具相比,具有更高的灵活性和表现力。我们将使用 Locust 模拟对服务的用户流量。运行负载测试。
尝试更改测试中的参数,并观察输出结果。您会注意到# Run a load test to trigger autoscaling locust -f load_test.py \ -H $AGENT_URL \ --headless \ -t 50s \ -u 3 \ -r 1
ollama-gemma3-270m-gpu
峰值达到 2-3 个实例。📊 负载测试参数:- 时长:50 秒
- 用户:3 位并发用户
- 生成速率:每秒 1 位用户
- 目标:在两个服务上触发自动扩缩
12. 观察自动扩缩行为
在负载测试运行期间,您将能够观察到 Cloud Run 的自动扩缩功能在运行。在此处,您将看到将 ADK 代理与 GPU 后端分离的主要架构优势。
在负载测试期间,在控制台中监控这两个 Cloud Run 服务的扩缩情况。
- 在 Cloud 控制台中,前往:
- Cloud Run → production-adk-agent → 指标
- Cloud Run → ollama-gemma3-270m-gpu → 指标
👀 您应观察到的情况:
🤖 ADK Agent Service:
- 在流量增加时,应保持稳定在 1 个实例
- 高流量期间 CPU 和内存用量激增
- 高效处理会话管理和请求路由
🎮 Gemma 后端服务(瓶颈):
- 根据推理需求将实例数量从 1 个扩缩到 3 个
- 在负载下,GPU 利用率显著提高
- 由于 GPU 密集型模型推理,此服务成为瓶颈
- 由于 GPU 加速,模型推理时间保持不变
💡 重要数据洞见:
- GPU 后端是瓶颈,并且扩展速度更快(1-3 个实例)
- ADK 代理保持一致
- 两种服务会根据各自的负载特征独立扩缩
- 自动扩缩有助于在不同的负载条件下保持性能
13. 总结
恭喜!您已成功部署了生产就绪型 ADK 代理,该代理具有 GPU 加速的 Gemma 后端,并观察了自动扩缩行为。
✅ 您完成的操作
- ✅ 在 Cloud Run 上部署了 GPU 加速的 Gemma 模型后端
- ✅ 创建并部署了与 Gemma 后端集成的 ADK 代理
- ✅ 使用 ADK 网页界面测试了代理
- ✅ 观察到两个协调的 Cloud Run 服务之间的自动扩缩行为
💡 本实验的关键分析洞见
- 🎮 GPU 加速:NVIDIA L4 GPU 可显著提升模型推理性能
- 🔗 服务协调:两个 Cloud Run 服务可以无缝协同工作
- 📈 独立扩缩:每个服务都会根据其各自的负载特征进行扩缩
- 🚀 生产环境就绪状态:架构可有效处理实际流量模式
🔄 后续步骤
- 尝试不同的负载模式并观察扩缩行为
- 尝试不同的 Gemma 模型大小(相应地调整内存和 GPU)
- 为生产环境部署实现监控和提醒
- 探索多区域部署,实现全球可用性
🧹 清理
为避免产生费用,请在完成后删除资源:
gcloud run services delete production-adk-agent --region=europe-west1
gcloud run services delete ollama-gemma3-270m-gpu --region=europe-west1