mcpField
C
cloudrun-development

cloudrun-development

github.com/tencentcloudbase云与 DevOps79986 次安装今天更新
代码仓库

关于 cloudrun-development

面向 CloudBase Run 开发的技能,供需要初始化、部署、检查或排查长期运行后端服务的开发者使用。它侧重部署前的运行模式、数据库网络、凭证和静态资源决策。

主要功能

  1. 01判断云托管与 HTTP 云函数
  2. 02规划 SDK 与 TCP 数据库访问
  3. 03检查网络、入口与凭证配置
  4. 04排查容器部署和探针故障

适用场景

  1. 01部署 WebSocket 或 SSE 服务
  2. 02迁移使用经典数据库驱动的应用
  3. 03诊断 CloudRun 服务启动失败

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tencentcloudbase/skills --skill cloudrun-development

安装后在 Claude Code 中输入/cloudrun-development确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.md
references/
image-deploy-troubleshooting.md
vpc-and-database.md

详细介绍

兄弟技能(仅限本地)

兄弟 CloudBase 技能与此技能一同提供。请使用 ../auth-tool-cloudbase/SKILL.md 这样的本地相对路径。

如果此环境中缺少引用的兄弟技能文件,请让用户安装完整的 CloudBase 插件(或缺少的技能)。不要通过 HTTP 将远程技能或协议 Markdown 获取到 Agent 上下文中。

跨领域协议(编写 HTTP 处理程序或部署镜像前必须阅读):

  • 敏感运行时数据保护:../cloudbase-platform/references/protocols/sensitive-runtime-data-protection.md
  • 部署门禁:../cloudbase-platform/references/protocols/deployment-gate.md

CloudBase Run 开发

激活约定

以下情况首先使用此技能
  • 任务是初始化、运行、部署、检查或调试 CloudBase Run 服务。
  • 请求需要长时间运行的 HTTP 服务、SSE、WebSocket、自定义系统依赖项或容器式部署。
  • 任务是在 CloudBase Run 上创建或运行 Agent 服务。
  • 任务是迁移使用传统 DATABASE_URL / TCP 数据库客户端的现有 / GitHub / 第三方后端。
  • 服务需要稳定的独立进程(长连接、自定义运行时、VPC 数据库访问)——请参阅下方「云托管 vs HTTP 云函数」决策部分。仅有 Dockerfile 不足以构成强触发条件。
编写代码前阅读(如果)
  • 你仍需在 Function 模式和 Container 模式之间做出选择。
  • 提示词提到了 queryCloudRun、manageCloudRun、Dockerfile、服务域名或公开/私有访问。
  • 应用通过 TCP 依赖 MySQL、PostgreSQL、Redis 或其他 VPC 私有资源 → 先做数据库访问方式决策(优先使用 SDK/网关,见下方「数据库访问方式决策门」);确认必须通过 TCP 直连后 → 还要阅读 references/vpc-and-database.md。
  • 你正在为无状态 HTTP 服务选择 CloudRun 还是 HTTP 云函数。
  • 服务通过 SDK 调用 CloudBase 资源(PG app.rdb()、NoSQL、存储、函数)→ 先通过「计算资源访问 CloudBase 的凭证决策门」:凭证由谁签发、如何注入、如何吊销,都必须在编写代码前确定。
  • 容器部署失败(deploy_failed、Pod 未就绪、就绪性检查/探针失败、第三方 imageUrl 无法保持运行)→ 还要阅读 references/image-deploy-troubleshooting.md 并遵循下方的容器部署失败 SOP。不要一开始就提高 InitialDelaySeconds。
然后还要阅读
  • 使用云函数而非 CloudRun -> ../cloud-functions/SKILL.md
  • Agent SDK 和 AG-UI 相关内容 -> ../cloudbase-agent/SKILL.md
  • 浏览器调用方的 Web 身份验证 -> ../auth-web-cloudbase/SKILL.md
  • 现有应用 + TCP 数据库网络 -> references/vpc-and-database.md
  • 容器镜像部署失败 / 探针 / deploy_failed -> references/image-deploy-troubleshooting.md
  • 服务通过 SDK 调用 CloudBase 资源(凭证来源 / 注入 / 吊销)-> ../cloud-functions/references/http-function-credentials.md
  • 关于 CloudRun 费用的计费问题(「没有部署任何内容,为什么还要收费」「免费额度还没用完」)-> ../cloud-api-operations/references/recipes/billing-charges-explained.md(赠送额度是总计 3 个月的额度,且只要实例数不为 0,容器就会产生费用)
请勿用于
  • 更适合函数模型的简单 Event Function 或 HTTP Function 工作流。
  • 没有后端服务的纯前端项目。
  • 数据库架构设计任务。
常见错误 / 注意事项
  • 只需要普通云函数时,却选择 CloudRun。
  • 在容器模式下忘记监听平台提供的 PORT——函数模式下也有相反的情况:在该模式下调用 app.listen(),而端口已由框架接管,第二次绑定会因 EADDRINUSE 失败。
  • 猜测凭据环境变量名称。 @cloudbase/node-sdk 读取的是 CLOUDBASE_APIKEY;臆造的名称(例如 TCB_API_KEY)会被静默忽略,直到运行时才表现为“没有凭据”。
  • 从本地客户端登录状态(auth.json、.cloudbase/)中复制服务端凭据,并将其注入已部署的服务。应改用 manageAppAuth(action="createApiKey", keyType="api_key") 创建密钥,这样密钥才有所有者、轮换方式和可撤销的 keyId。参见 ../cloud-functions/references/http-function-credentials.md。
  • 将静态内容打包进镜像——媒体文件、用户上传内容,或按各自节奏更新的资源。 三种情况,一个根本原因:每次部署和每次扩容都会重新构建、推送和拉取镜像,因此任何大型或独立变化的内容都会无谓地拖慢每次部署。
    • 媒体文件(*.mp4、大图、字体)通过 COPY . . 一并复制进来——一个演示视频就可能让 30 秒的部署变成几分钟。媒体文件应放在云存储中,并通过 URL 引用。添加 .dockerignore,排除 *.mp4、*.mov、*.zip、*.psd 以及 public/videos/ 等媒体目录。
    • 将用户上传内容写入容器文件系统——服务是无状态的;本地磁盘上的内容会在下次部署、重启或扩容时消失。上传内容应存入云存储。
    • 从镜像提供频繁更新的静态资源——如果资源按自己的节奏变化,每次变化都会触发整个服务重新部署。应从云存储提供这些资源,这样只有 代码 变更时才需要重新部署服务。
  • 将 CloudRun 当作有状态应用托管服务,并把重要状态存储在本地磁盘上。
  • 认为容器模式支持本地运行。
  • 场景只需要私有访问或小程序内部访问时,却默认开放公网访问。
  • 部署已有应用时配置了 DATABASE_URL / MySQL / PostgreSQL / Redis,却遗漏了 serverConfig.VpcConf——部署看似成功,随后运行时数据库连接失败。
  • 新应用部署默认选 TCP 直连数据库——能通过 SDK/网关访问的数据(PG app.rdb()、NoSQL、storage)不需要 VpcConf,也不需要数据库账号密码;只有迁移类应用(无法替换经典驱动/ORM)才使用 TCP 直连 + VpcConf。参见“数据库访问方式决策门”。
  • 混淆 OpenAccessTypes(用户如何访问服务)与 VpcConf(服务如何访问 VPC 数据库)。
  • 部署到尚未初始化 CloudRun 的环境——在没有大租户记录的环境中调用 CreateCloudRunServer,会静默进入旧版小租户路径,创建错误的小租户服务/版本。首次部署前务必先初始化环境(manageCloudRun(action="initEnv"),tcbr)。现在,manageCloudRun(action="deploy") 会阻止在未初始化的环境中创建新服务,并提供指引。
  • 使用旧版 tcb CloudRun API(CreateCloudBaseRunResource / DescribeCloudBaseRunResource / DeleteCloudBaseRunResource)——这些接口已弃用,是小租户开放 API,且在 callCloudApi 中被阻止。CloudRun 始终通过 tcbr(CreateCloudRunEnv / CreateCloudRunServer)运行。使用 DescribeEnvBaseInfo(必填 EnvId)查询单个环境的基本信息/CloudRun 是否已启用——使用 manageCloudRun(action="initEnv") 开启,并使用 queryCloudRun(action="envStatus") 轮询状态;使用 DescribeCloudRunEnvs(EnvId 为可选筛选条件)查询环境列表/资源信息。
  • 部署 httpbin / 请求回显镜像,或返回 req.headers / process.env——CloudBase 可能会注入 x-cloudbase-context(base64 临时凭据)。回显该内容会泄露账号的云访问权限。请遵循 ../cloudbase-platform/references/protocols/sensitive-runtime-data-protection.md。
  • 看到就绪探针失败 / deploy_failed 后,立即调高 InitialDelaySeconds——探针窗口已经约为 N+150 秒;崩溃循环和环回地址绑定问题并非启动缓慢。请遵循容器部署故障 SOP。
  • 部署第三方镜像前未阅读其运行文档——缺少 Cmd、绑定地址环境变量或 VolumesConf,看起来都与探针失败相同。
  • 对 imageUrl 部署调用 getDeployLog——那是 CODING 构建日志;请使用 getProcessLog。
  • 把启动横幅当作服务正常运行的证据——拉取两次 getProcessLog 并进行比较;如果启动序列重复出现,说明服务处于重启循环。
Minimal checklist
  • Choose Function mode or Container mode explicitly.
  • Confirm the environment has CloudRun initialized before the first deploy — a brand-new environment must call CreateCloudRunEnv (tcbr) first; never CreateCloudRunServer on an uninitialized environment (it falls back to the legacy 小租户 path). manageCloudRun(action="deploy") validates this automatically and blocks new services on uninitialized environments. When blocked, first call manageCloudRun(action="initEnv", envId=...) (异步开通) and poll queryCloudRun(action="envStatus") until Status=normal, or reconsider an HTTP cloud function to bypass CloudRun entirely.
  • Confirm whether the service should be public, VPC-only, or mini-program internal (ingress).
  • If the app uses TCP databases/caches, resolve and set VpcConf (egress / private network) before deploy — see references/vpc-and-database.md.
  • Keep the service stateless and externalize durable data.
  • Separate static from dynamic: media files, user uploads, and frequently-updated assets live in cloud storage, not in the image. Check what the Dockerfile copies in.
  • Settle the credential path for every CloudBase SDK call before writing code — a server API Key issued through manageAppAuth(action="createApiKey") and injected via EnvParams, never a key copied out of the local client login state.
  • Use absolute paths for every local project path.
  • Confirm handlers never echo x-cloudbase-context, full headers, or credential env vars; do not deploy httpbin-style reflectors.
  • For third-party images, complete the five-item docs checklist (Cmd / port / bind env / volume / health) before deploy.

Overview

Use CloudBase Run when the task needs a deployed backend service rather than a short-lived serverless function.

云托管 vs HTTP 云函数(按需求选,不按文件选)

核心原则:HTTP 云函数优先。只有需求真正需要云托管时才用云托管;有 Dockerfile 不等于必须上云托管。

HTTP 云函数更合适(优先):

  • 无状态 HTTP 服务,监听 PORT/9000,只做「请求进来 → 处理 → 响应」的响应式逻辑
  • 短生命周期请求,无长连接需求(SSE/WebSocket 之外的普通 API、CRUD、转发)
  • 标准 runtime 够用(不需要自定义系统依赖、不需要非标准语言)——需要时也能用镜像函数(Custom Image HTTP Function)跑,仍然在函数这条线上
  • 部署更快、费用更低(按请求计费,可缩容到 0)、无需初始化云托管环境
  • 有 Dockerfile 但服务本质是无状态 HTTP → 优先 HTTP 云函数(HTTP Function / Custom Image HTTP Function),不必上云托管

云托管才需要(只有以下之一才选云托管):

  • 长连接:WebSocket、SSE 长连接、服务端推送
  • 需要常驻的独立进程:后台任务循环、常驻缓存 / 连接池、自管端口的服务
  • VPC 内数据库 / Redis 访问(VpcConf 私有网络连通)
  • Agent 服务(Function mode CloudRun)
  • 迁移已有 / GitHub / 第三方应用

语言不是上云托管的条件:非标准语言(Java / Rust / C++ / PHP / .NET 等)或需要自定义系统依赖时,只要服务仍是「请求进来 → 响应」且无长连接,打成镜像用 Custom Image HTTP Function,就还是函数;只有再叠加常驻 / 长连接 / VPC 才上云托管。

决策示例: 一个带 Dockerfile 的 Go/Python HTTP API,无长连接、无自定义系统依赖、不碰 VPC 数据库 → 选 HTTP 云函数而不是云托管;同一份代码若有 WebSocket 长连接 → 才选云托管。

数据库访问方式决策门(部署前必答:SDK 优先,TCP 直连兜底)

核心原则:能用 CloudBase SDK/网关访问的数据,一律优先 SDK 路径。 TCP 直连会引入 VPC、安全组、数据库账号密码三件套,全是部署后才暴露的问题(ETIMEDOUT、安全组拦截、密码注入),能不碰就不碰。

优先:SDK / 网关路径(无需 VpcConf、无需数据库账号密码)

  • CloudBase PG → app.rdb()(js-sdk v3 / node-sdk,走 PG HTTP 网关;详见 ../postgresql-development-cloudbase/SKILL.md)
  • NoSQL → app.database();对象存储 → app.storage
  • 新应用 / CloudBase 原生数据 → 数据层直接按 SDK 路径设计,部署时完全不需要 VPC 配置;若只用到这些数据面,还可结合上一节的「HTTP 云函数优先」进一步免掉云托管

仅当以下情况才走 TCP 直连(须完成 references/vpc-and-database.md 全流程):

  • 迁移已有 / GitHub / 第三方应用,数据层是经典驱动或 ORM(mysql2、pg、Prisma、SQLAlchemy、WordPress / Ghost 等),改造成 SDK 的成本高或用户明确要求保留
  • 需要 SDK 不覆盖的能力(特定 SQL 方言、存储过程、Redis 原生协议等)

决策动作: 扫描到 DATABASE_URL / DB 依赖信号时,先停下来回答「这个数据访问能不能换成 SDK/网关」,再决定是否进入 VPC checklist——不要默认按 TCP 直连方案往下走。

计算资源访问 CloudBase 的凭证决策门(部署前必答)

核心原则:SDK 路径免掉的是数据库账号密码,不是 CloudBase 资源访问凭证。 服务代码要调 CloudBase 资源(PG app.rdb() / NoSQL / storage / functions)时,先把凭证来源定下来,再写代码、再部署。

三件事必须先答:

  1. 谁签发 — CloudBase 服务端 API Key:manageAppAuth(action="createApiKey", keyType="api_key", keyName="<service>-<env>"),或 CLI tcb env apikey create my-key -e env-xxx。不要从本地客户端登录态(auth.json / .cloudbase/)里取一把来用。
  2. 怎么注入 — 经 serverConfig.EnvParams 注入 CLOUDBASE_APIKEY(@cloudbase/node-sdk 自动读取该变量;显式字段是 accessKey)。变量名以官方为准,不要自造。改环境变量时保留已有键值,不要整份覆盖。
  3. 怎么吊销 — 每个服务一把专用 key,记录 keyName 与轮换负责人;下线或轮换时 manageAppAuth(action="deleteApiKey", keyId=...) 并重新部署。轮换后旧实例里残留的副本不会报错,只会静默失效。

不要假设云托管容器已自动带上可用的 CloudBase 凭证 —— 部署后用一次真实的 SDK 读取验证(验证两次以上,不要只看进程起没起来)。完整步骤、Manager SDK 的腾讯云密钥对路径、环境变量合并的安全写法见 ../cloud-functions/references/http-function-credentials.md。

api_key 是环境级凭证:可绕过 RLS,单环境签发数量有限。不要给每个服务灌同一把 —— 任一实例失陷即整环境失陷。

When CloudRun is a better fit
  • Long connections: WebSocket, SSE, server push
  • Long-running request handling or persistent service processes
  • Custom runtime environments or system libraries
  • Arbitrary languages or frameworks
  • Stable external service endpoints with elastic scaling
  • AI Agent deployment on Function mode CloudRun
  • Migrating existing containerized or multi-language apps that need VPC access to databases

Mode selection

DimensionFunction modeContainer mode
Best forFast start, Node.js service patterns, built-in framework, Agent flowsExisting containers, arbitrary runtimes, custom system dependencies
Port modelThe function framework binds the platform port itself — your code must not call app.listen()App must listen on the injected PORT
DockerfileNot requiredRequired — but a Dockerfile alone does not mean CloudRun; first check whether the service needs long connections / custom runtime. Stateless HTTP services with a Dockerfile may fit HTTP cloud functions better.
Local run through toolsSupportedNot supported
Typical useStreaming APIs, low-latency backend, Agent serviceCustom language stack, migrated container app

如何使用此技能(面向编码 Agent)

  1. 先选择模式

    • 函数模式 -> HTTP/SSE/WebSocket 或 Agent 场景下最快捷的路径
    • 容器模式 -> 确实需要 Docker/自定义运行时环境时使用
  2. 遵循强制运行时规则

    • 容器模式:监听注入的 PORT。函数模式:框架会为你绑定端口——绝不要调用 app.listen()
    • 在编写任何 CloudBase SDK 调用之前,先确定凭证管理机制(由谁签发、如何注入、如何撤销)
    • 保持服务无状态
    • 将持久化数据存放在 DB/存储/缓存中
    • 精简依赖和镜像体积——镜像只包含代码和依赖;媒体、用户上传内容和频繁更新的资源应放到云存储中(参见常见错误)
    • 遵循资源配比建议:Mem = 2 × CPU
  3. 使用正确的工具

    • 读取操作 -> queryCloudRun
    • 写入操作 -> manageCloudRun
    • 删除操作需要明确确认并设置 force: true
    • 始终使用绝对 targetPath
  4. 遵循部署顺序

    • 初始化或下载代码
    • 对于全新环境,确保先初始化 CloudRun——在首次部署前调用 manageCloudRun(action="initEnv", envId=...)(异步、幂等);在未初始化的环境中,manageCloudRun(action="deploy") 会阻止创建新服务,并提示你调用 initEnv
    • 对于容器模式,验证 Dockerfile
    • 扫描 DB/缓存依赖信号(DATABASE_URL、docker-compose DB 服务、ORM 配置)
    • 如果需要 TCP DB 访问,在部署前完成 references/vpc-and-database.md 中的 VPC 检查清单
    • 如可行,先在本地运行
    • 配置入口访问模型,并在需要时配置出口 VpcConf
    • 对于 imageUrl / 第三方镜像,在部署前完成容器部署失败 SOP 中的五项文档检查清单
    • 部署并验证详情输出和 DB 连通性
    • 如果部署失败,请遵循容器部署失败 SOP(references/image-deploy-troubleshooting.md)——文档 → getProcessLog → 配置;不要从 InitialDelaySeconds 入手

工具路由

读取操作
  • queryCloudRun(action="list") -> 列出服务
  • queryCloudRun(action="detail") -> 检查单个服务及其最新部署状态(如有)
  • queryCloudRun(action="templates") -> 查看可用的启动模板
  • queryCloudRun(action="getDeployLog") -> 构建日志(CODING / DescribeCloudRunBuildLog)。仅在云端源码构建时有意义;已有镜像部署(imageUrl)没有构建过程,不要用它诊断镜像部署失败。未登录 CODING 的账号会报错(例如 User not created or may not qcloud user)
  • queryCloudRun(action="getProcessLog") -> 运行日志(tcbr/DescribeCloudRunProcessLog)。返回部署阶段步骤(如 create_version_check_vpc / create_eks_virtual_service / check_eks_virtual_service)以及容器启动/运行日志(s6-overlay、应用进程、readiness probe 失败原因)。镜像部署与源码构建均可使用,不依赖 CODING。参数:detailServerName/serverName + 可选 runId(不传则获取最新部署的 RunId;也可从 detail / getDeployRecords 的 latestDeploy.RunId 获取 RunId)
  • queryCloudRun(action="getDeployRecords") -> 列出部署记录(按时间从新到旧;包含 BuildId / RunId / FlowRatio / Status)——在流量操作前用于查看发布历史和回滚上下文
  • queryCloudRun(action="envStatus") -> 检查环境的 CloudRun 是否已开通及其开通过程状态(Status=creating 表示正在开通 / normal 表示已开通)——在 initEnv 后用于轮询进度,或在 deploy 前确认已就绪
  • queryCloudRun(action="getManageTask") -> 发布任务状态(tcbr/DescribeServerManageTask)。返回 taskId / taskStatus 和最新部署记录状态 latestDeployStatus。用于两种情况:遇到「已有部署发布任务运行中」时,先确认任务是否确实在推进;以及部署长时间没有进展时,区分「任务仍在推进」和「任务已卡住」。不知道任务状态时,不要反复重试 deploy
日志查询 SOP(构建日志 vs 运行日志)

排查部署失败时,必须区分两类日志,不要只用 getDeployLog:

  1. 云端源码构建(传入 targetPath,走 CODING 构建)
    • 先用 queryCloudRun(action="getDeployLog", detailServerName=..., buildId=...) 查询构建日志(编译/打包失败)
    • 再用 queryCloudRun(action="getProcessLog", detailServerName=..., runId=...) 查询运行日志(部署步骤 + 容器启动/健康检查)
  2. 已有镜像部署(传入 imageUrl、DeployType=image)
    • 跳过 getDeployLog(没有构建过程;且依赖 CODING,未登录会直接失败)
    • 直接用 queryCloudRun(action="detail") 或 getDeployRecords 获取 latestDeploy.RunId,再用 getProcessLog 查询运行日志
{
  "action": "getProcessLog",
  "detailServerName": "my-svc",
  "runId": "<from latestDeploy.RunId>"
}
部署任务 SOP(遇到「已有部署发布任务运行中」时)

manageCloudRun(action="deploy") 报错「已有部署发布任务运行中」/ already has a deploy task running 时,不要盲目重试,也不要反复修改 Dockerfile / serverConfig —— 先确认任务的实际状态:

  1. queryCloudRun(action="getManageTask", detailServerName=...) → 查看 taskId / taskStatus / latestDeployStatus
  2. queryCloudRun(action="getProcessLog") → 间隔 20–40 秒拉取两次并进行对比,确认部署阶段的步骤是否仍在推进
  3. 根据结果分支处理:
观察情况操作
taskStatus 仍为运行态,部署步骤有推进继续等待,不要重新发送 deploy
任务已结束(非运行态),但 deploy 仍被拒绝此时才考虑重试
任务长时间停留在非终态,版本也停在 creating 没有变化记录 taskId / latestDeployStatus / 时间范围作为证据,不要空转重试

force=true 无法解决此问题:它只会跳过本工具的确认提示,不会取消或覆盖服务端已有的发布任务 —— 把它当作「强制覆盖」只会白白失败一次。

日志排查顺序(构建日志 vs 运行日志、先查日志再查配置)见上面的 日志查询 SOP 与 容器部署失败 SOP。

写操作
  • manageCloudRun(action="initEnv") -> 为环境打开(初始化)CloudRun — 异步、幂等(Status=normal → 已打开,不会重新创建)。用于全新环境首次部署前,或 deploy 因「尚未初始化云托管」而受阻时。参数:envId(默认为已配置的环境)、packageType(默认 Trial)。轮询 queryCloudRun(action="envStatus"),直到 Status=normal。
  • manageCloudRun(action="init") -> 创建本地项目
  • manageCloudRun(action="download") -> 拉取远程代码
  • manageCloudRun(action="run") -> Function 模式下本地运行
  • manageCloudRun(action="deploy") -> 触发部署 + 等待注册完成(轻量等待)(不会一直等待完整构建;如果不需要 buildId,传入 waitRegistration=false 可跳过这段等待)。返回 buildId / runId / taskId + 根据 DeployType 提供的 next_step:source → 先调用 getDeployLog,再调用 getProcessLog;image(imageUrl,BuildId 通常为 0)→ 跳过 getDeployLog,通过 getDeployRecords/detail 获取 RunId,再调用 getProcessLog。请遵循返回的 next_step —— 不要总是轮询构建日志。对于已有服务:RMW 会保留远程 VpcConf / EnvParams 键 / OpenAccessTypes;对于新服务,会自动验证环境的 CloudRun 是否已初始化 —— 如果尚未初始化,部署会受阻,并提示先调用 initEnv
  • manageCloudRun(action="updateConfig") -> 仅更新配置(不上传代码;VPC / EnvParams / 扩缩容 / 访问类型)
  • manageCloudRun(action="traffic") -> 流量管理 / 灰度发布(与 tcb cloudrun traffic 保持一致):trafficOp="set" 调整稳定版/灰度版的流量比例(stablePercent + canaryPercent 必须等于 100,例如 90/10);trafficOp="promote" 将灰度版本提升为全量发布(100%,关闭灰度发布,不可逆);trafficOp="rollback" 回滚到上一稳定版本(停止正在发布的灰度版本)。先检查 queryCloudRun(action="getDeployRecords"),了解当前版本和流量情况
  • manageCloudRun(action="delete") -> 删除服务
  • manageCloudRun(action="createAgent") -> 创建 Agent 服务

Deploying an existing image (imageUrl)

已有一个现成镜像(本地构建好、或第三方发布)时,不需要本地源码目录,直接 manageCloudRun(action="deploy") 传入 imageUrl 即可,走 DeployType="image"(容器型)部署,targetPath 可省略。若用户明确提到使用某个镜像或无需重新构建代码,必须传 imageUrl,不要仅因本地有源码目录就回退到源码构建。

决策路径(直填 vs 本地中转):

  1. 公网匿名可拉取(如 ccr.ccs.tencentyun.com/...、公开 Docker Hub 镜像)→ 直填 imageUrl:manageCloudRun(action="deploy", serverName=..., imageUrl="ccr.ccs.tencentyun.com/ns/img:v1", serverConfig={...})。CloudBase 会直接拉取该 registry 地址构建部署。若 docker.io / Docker Hub 在节点上反复拉取失败,不要空转重试:改用 Dockerfile FROM <public-image> + targetPath 源码构建(CODING 拉公网镜像,产物进 CCR 内网拉取)。见下方 SOP 第 4 步。
  2. 私有 / 需登录的 registry(ghcr.io、私有 ECR/Harbor 等)→ 本地中转到 CCR:
    docker pull ghcr.io/example/app:latest
    docker tag ghcr.io/example/app:latest ccr.ccs.tencentyun.com/<ns>/app:latest
    docker login ccr.ccs.tencentyun.com
    docker push ccr.ccs.tencentyun.com/<ns>/app:latest
    
    然后把 ccr.ccs.tencentyun.com/<ns>/app:latest 作为 imageUrl 传入。中转只解决拉取,不能替代镜像文档里的启动命令 / 环境变量 / 数据目录。

与 initEnv 联动: 镜像部署同样要求环境已开通云托管。新环境首次部署前先 manageCloudRun(action="initEnv", envId=...),并用 queryCloudRun(action="envStatus") 轮询到 Status=normal;未开通时 deploy 会被拦截并引导先 initEnv。

示例:

{
  "action": "deploy",
  "serverName": "my-image-svc",
  "imageUrl": "ccr.ccs.tencentyun.com/ns/app:latest",
  "serverConfig": {
    "OpenAccessTypes": ["PUBLIC"],
    "Cpu": 0.5,
    "Mem": 1,
    "MinNum": 1,
    "MaxNum": 3,
    "Port": 8080,
    "Cmd": ["node", "server.js"],
    "EnvParams": "{\"PORT\":\"8080\",\"BIND_HOST\":\"0.0.0.0\"}"
  }
}

Port / Cmd / EnvParams 必须来自镜像官方文档的五要素清单,不要套用 3000 或省略启动命令。第三方镜像的完整对照见 references/image-deploy-troubleshooting.md 附录。

部署后:manageCloudRun(deploy) 对镜像返回的 next_step 默认指向 getProcessLog(或先 getDeployRecords 取 RunId),不要改去调 getDeployLog。也可用 queryCloudRun(action="detail") 查看 imageInfo(镜像地址与部署类型)。镜像部署失败排查走下方 SOP。

Container deploy failure SOP

顺序:先查镜像官方文档 → 再查运行日志 → 最后才动配置。禁止一看到 probe failed / deploy_failed 就调 InitialDelaySeconds。

详情与案例:references/image-deploy-troubleshooting.md。

1. 部署前:从镜像官方文档确认五要素

不要靠 Docker Hub tag 或「常见默认值」猜。部署前必须确认:

  1. 启动命令 EntryPoint / Cmd(进程如何前台常驻)→ serverConfig.EntryPoint / Cmd
  2. 服务端口(进程真正 bind 的端口;不要假设 80/3000,也不要假设镜像尊重 PORT)→ serverConfig.Port
  3. 对外监听环境变量(必须 0.0.0.0 而不是 127.0.0.1、功能开关默认关闭等)→ EnvParams
  4. 数据目录挂载 → serverConfig.VolumesConf
  5. 健康端点(CloudRun readiness 探的是服务端口,不是任意 HTTP path)

缺任何一项再部署,失败看起来都会像「健康检查失败」。

2. 部署失败:用 getProcessLog 定性

镜像部署(imageUrl)跳过 getDeployLog(那是云端源码构建的构建日志)。从 detail / getDeployRecords 取 RunId,再 queryCloudRun(action="getProcessLog")。

启动日志存在 ≠ 服务正常运行。 banner、s6/tini 行、sidecar "listening" 都不能证明探针目标已起来。

两次日志对比判活: 隔 20–40 秒再拉一次 getProcessLog。

观察定性
只有调度/创建步骤(create_eks_*),没有容器 stdoutPod 调度中 / 镜像拉取
同一段启动 banner / PID 1 行重复出现(时间戳在走、内容几乎一样)容器启动即退出 / 重启循环
进程还在,但 listen 在 127.0.0.1 或端口 ≠ serverConfig.Port端口 / 绑定地址问题
两次拉取是同一条启动过程在往后打日志,banner 不重复才可能是启动慢
3. Readiness probe 真实机制(严禁先调延迟)

部署步骤完成后:先等 N 秒(InitialDelaySeconds),再大约 每 5 秒 探一次服务端口,连续约 30 次全失败 才判本次部署失败。窗口 ≈ N+150s。不是「N 秒后立即失败」。

  • 禁止: 看到 probe failed 就把 N 改成 120。崩溃循环和 loopback 绑定不会因为 N 变大而好。
  • 允许调大 N 仅当: 两次日志证明同一个进程还在一次性初始化(JVM 预热、迁移)且尚未 listen。
4. 公网镜像(docker.io)反复失败 → Dockerfile 源码构建

节点直连 Docker Hub 反复失败时,不要空转 imageUrl。写:

FROM docker.io/example/app:latest

用 targetPath 走云端源码构建:CODING 构建机拉公网镜像,产物进 CCR,云托管节点内网拉取。这只解决拉取拓扑,不替代第 1 步的 Cmd / 环境变量 / 卷。

5. Supervisor 镜像(s6 / tini / supervisord)启动即退出

PID 1 往往是监督进程,不是 HTTP 应用。用两次日志找子进程重启风暴。若镜像 issue 记录了 PID 1 / pgrep -f 误匹配,按文档 workaround(绝对路径 Cmd、关闭 supervise),不要调探针延迟。示例见 reference 附录。

Access guidance

  • Web/public scenarios -> enable PUBLIC ingress intentionally and pair it with the right auth flow.
  • Mini Program -> prefer internal direct connection and avoid unnecessary public exposure.
  • Private ingress scenarios -> keep public access off unless the product requirement clearly needs it.
  • Database / Redis in a VPC -> this is not solved by OpenAccessTypes. You must set serverConfig.VpcConf and use the database private address. Read references/vpc-and-database.md.

Quick examples

Initialize
{ "action": "init", "serverName": "my-svc", "targetPath": "/abs/ws/my-svc" }
Local run (Function mode)
{ "action": "run", "serverName": "my-svc", "targetPath": "/abs/ws/my-svc", "runOptions": { "port": 3000 } }
Deploy (no VPC-private dependencies)
{
  "action": "deploy",
  "serverName": "my-svc",
  "targetPath": "/abs/ws/my-svc",
  "serverConfig": {
    "OpenAccessTypes": ["PUBLIC"],
    "Cpu": 0.5,
    "Mem": 1,
    "MinNum": 1,
    "MaxNum": 5
  }
}
部署(连接到 MySQL / PostgreSQL / Redis 的现有应用,通过 TCP 连接)
{
  "action": "deploy",
  "serverName": "my-existing-app",
  "targetPath": "/abs/ws/my-existing-app",
  "serverConfig": {
    "OpenAccessTypes": ["PUBLIC"],
    "Cpu": 0.5,
    "Mem": 1,
    "MinNum": 1,
    "MaxNum": 5,
    "EnvParams": "{\"DATABASE_URL\":\"postgres://user:[email protected]:5432/app\"}",
    "VpcConf": {
      "VpcId": "vpc-xxxxxxxx",
      "SubnetId": "subnet-xxxxxxxx"
    }
  }
}

有效的 OpenAccessTypes 值:OA(办公网访问)、PUBLIC(公网访问)、MINIAPP(小程序访问)、VPC(VPC 访问)。需要公开 HTTPS 访问的 Web 应用请使用 PUBLIC。

如果希望降低冷启动延迟,建议将 MinNum: 1 设为默认值。如果用户明确更看重低成本,并且接受更多冷启动,请说明其中的权衡,并允许他们将 MinNum 降至 0。

最佳实践

  1. 尽可能优先使用 PRIVATE/VPC 或小程序内部入口。
  2. 对于 TCP 数据库访问,始终将私有数据库 URL 与 VpcConf 配套使用,并确保二者位于数据库所在的同一 VPC/地域。
  3. 使用环境变量存放机密信息和各环境的配置——仅在服务端读取;绝不要在 HTTP 响应中返回这些信息。CloudBase API Keys 应通过 manageAppAuth(action="createApiKey") 创建,而不是从本地客户端登录文件中获取。
  4. 在部署前后使用 queryCloudRun(action="detail") 验证配置。
  5. 尽量减少启动时执行的工作,以降低冷启动的影响。
  6. 对于 Agent 场景,请使用 Agent SDK 技能了解协议和适配器详情,不要在此处重复说明。
  7. 对于冒烟测试,请返回固定的 { "ok": true } / 健康状态负载——绝不要部署 httpbin 或任何会回显请求头的服务。

故障排查提示

  • 访问失败 -> 检查入口访问类型、域名设置,以及实例是否已缩容至零。
  • 部署因“尚未初始化云托管 / not initialized”而被阻止 -> 必须先为环境启用 CloudRun:调用 manageCloudRun(action="initEnv", envId=...)(异步开通),并轮询 queryCloudRun(action="envStatus"),直至 Status=normal;或者打开控制台 环境 → 云托管 → 开通。对于无状态 HTTP 服务,可以考虑完全改用 HTTP 云函数,而不是 CloudRun。
  • 部署失败 -> 按照上文的容器部署失败 SOP(以及 references/image-deploy-troubleshooting.md)操作:镜像部署会跳过 getDeployLog,仅使用 getProcessLog;通过两次拉取日志区分调度问题、端口问题和启动即退出问题。在日志证明初始化确实缓慢之前,不要调高 InitialDelaySeconds。同时检查 Dockerfile(源码)和 CPU/内存比例。
  • 部署因“a deploy task is already running” /「已有部署发布任务运行中」而被拒绝 -> 首先使用 queryCloudRun(action="getManageTask") 读取实际任务状态。不要盲目重试,也不要设置 force=true 期待覆盖——它只会跳过此工具的确认提示。请参阅上文的部署任务 SOP。
  • 部署已被接受,但版本一直处于 creating 状态 -> 使用 queryCloudRun(action="getManageTask") 检查 latestDeployStatus 和 taskStatus,然后使用 getProcessLog 查看部署阶段的步骤。只有在日志确实指向代码或配置问题时,才修改 Dockerfile / serverConfig。
  • 本地运行失败 -> 请记住,本地运行工具仅支持 Function 模式。
  • 性能问题 -> 减少依赖、优化初始化,并调整最小实例数。
  • 部署成功后仍无法连接数据库 / Redis -> 几乎总是缺少或配置错误的 VpcConf、私有主机地址错误或安全组配置错误。重写应用代码之前,请先按照 references/vpc-and-database.md 操作。
  • 服务中的 CloudBase SDK 调用因凭据缺失 / 无效而失败 -> 跳过了上述凭据检查,或者变量名不是官方名称。使用 manageAppAuth(action="createApiKey") 创建密钥,通过 EnvParams 将其注入为 CLOUDBASE_APIKEY,重新部署,然后验证实际读取。请参阅 ../cloud-functions/references/http-function-credentials.md。

参考索引

所有打包的参考文件(技能 lint 可达性检查所必需):

评论

支持 Markdown