上一篇把程序拆成进程、镜像、容器和文件。镜像已经能够运行以后,接下来要考虑:启动多少个实例?流量怎样进来?进程失败后谁来重启?发布时,旧实例正在执行的任务怎么办?

K8s 和 Serverless 都会参与这些问题,但接管的职责和暴露的配置不同。理解平台时,我更关心两件事:它怎样管理运行资源,以及应用需要怎样配合它的生命周期。

本文继续使用“上传 Excel,调用模型,在沙箱中分析并生成报告”的例子,分别看 API、Worker 和沙箱应该怎样运行。

本文由 AI 辅助整理,属于 Agent 工程运维系列。配置片段用于解释机制,未部署到真实业务环境;具体配额、执行时限和产品功能以实际使用的平台为准。

先分清三类工作负载

同一个 Agent 系统,里面的程序未必适合使用相同的运行方式。

组件 主要工作 更关心的运行条件
API 鉴权、创建任务、查询状态、输出事件 接入延迟、连接数、健康检查、多副本
Worker 调用模型和工具、推进执行、保存状态 执行并发、下游配额、中断恢复、退出规则
沙箱 运行分析代码或浏览器操作 隔离、CPU 与内存、临时文件、会话与回收

API 可以先返回任务编号,再由 Worker 执行。浏览器持续接收进度,与后台任务持续运行,分别有自己的生命周期。沙箱则可能只在某个工具步骤需要时创建,也可能为了保留浏览器或文件上下文而维持一个会话。

这种拆分让平台选择具体起来:需要托管的是一个常驻服务、一个有结束目标的任务,还是一个有会话状态的执行环境?

K8s 怎样维护期望状态

Kubernetes 接收声明式配置,再持续协调实际状态。例如声明运行三个 API 副本,控制器会维护副本数量;调度器选择运行位置;节点上的组件启动并观察容器。

如果容器退出,平台可以按策略重启;如果工作负载副本丢失,控制器可以创建替代实例。这个机制使服务能够在实例变化中持续运行。Kubernetes 概览和自愈说明描述了这些能力。

对开发者来说,可以先认识这些对象:

对象 作用 在示例中怎样使用
Node 承载工作负载的机器 提供 CPU、内存和磁盘
Pod 一个或多个紧密协作的容器组成的运行单位 一个 API 实例或 Worker 实例
Deployment 管理副本与滚动更新 长期运行的 API 和 Worker
Service 给一组可替换的 Pod 提供稳定入口 Worker 通过服务名调用工具服务
Gateway / Ingress 定义外部流量如何进入服务 按域名和路径将请求导向 API
Job / CronJob 管理有完成目标的任务或定时任务 批量评测、定期数据整理
ConfigMap / Secret 传递普通配置与敏感配置 模型地址、数据库配置与凭据
PVC 申请持久卷存储 需要卷语义的持久数据

其中,Service 让调用方不必写死某个 Pod 的地址;Gateway、Ingress 和网络策略需要相应实现才能生效。可以结合Kubernetes 网络概念理解服务发现、流量入口与网络控制的关系。

Namespace 用于组织资源,并能作为权限、配额等策略的作用范围。租户隔离还需要进一步配置网络、存储和权限,具体边界见多租户文档。

资源配置怎样影响程序

在运行一个解析文件的 Worker 时,很容易遇到两类不同现象:Pod 一直没有被安排运行,或者运行一段时间以后被结束。

前者要检查调度条件和资源需求,后者要检查实际退出原因与资源使用。这里涉及两个字段:

  • requests:调度时用于计算资源需求,也参与部分运行时资源分配。
  • limits:对运行时资源使用施加约束。

例如,容器片段可以这样写:

# 示意片段,放在实际 Pod 模板的 containers 下。
resources:
  requests:
    cpu: "500m"
    memory: "512Mi"
  limits:
    cpu: "2"
    memory: "1Gi"

500m 表示 0.5 个 CPU 单位。CPU 达到 limit 后,通常表现为使用时间被节流;内存继续申请而触及限制,则可能触发 OOM 终止。节点当前使用率较低,也可能因为已声明的资源需求或其他调度约束而无法容纳新 Pod。官方资源管理文档解释了调度核算和运行时约束的差别。

这组数字只是例子。实际值应观察文件规模、分析库和浏览器的峰值使用,再为任务类别设置合适的资源。把轻量 API 与内存密集的分析工具放在同一份资源预算里,会增加定位和扩容的难度。

健康检查应该检查什么

K8s 常见的三种探针,关注不同阶段:

探针 检查的问题 失败后的主要影响
Startup 应用初始化是否完成 在阈值内等待启动,持续失败时按规则结束容器
Readiness 当前是否适合接收服务流量 不再将正常 Service 流量导向这个实例
Liveness 应用是否失去正常推进能力 达到阈值后触发容器重启

启动探针适合初始化较慢的应用;就绪探针决定何时接流量;存活探针需要谨慎,避免将暂时性拥塞变成反复重启。探针文档对这三类语义有明确区分。

假设外部模型服务暂时限流,API 自身仍能查询任务、接收取消和返回状态。这时,可以通过排队、退避或限制新任务进入来处理。是否改变就绪状态,要根据该实例承担的服务判断;直接让所有实例的存活检查失败,可能额外制造启动压力。

对于从队列主动取任务的 Worker,还要注意:Service 的就绪状态控制入站流量,暂停领取队列任务需要消费逻辑配合。 不能只改一个 HTTP 健康接口,就假定 Worker 已经停止领取新工作。

扩副本与恢复任务分别处理

HPA 可以根据资源、自定义或外部指标调整副本数。对于大量时间花在等待模型响应的 Worker,可以结合排队时长、积压和执行槽位观察,而不是只看 CPU。HPA 文档提供了指标与扩缩容机制的说明。

副本变多,还需要节点资源容纳它们;节点扩容通常由另一层集群或云资源能力处理。模型配额、数据库连接和沙箱容量也需要一起核算。

副本恢复后,新的 Worker 怎样知道刚才分析到了哪一列、哪些工具已经执行过?这个问题交给应用的持久状态和检查点。Job 可以管理有结束目标的任务,也可能产生重试;业务写操作仍需要设计幂等。

因此,我会把两个配置分别记录:一份描述实例怎样运行,另一份描述任务怎样恢复。后者在第四篇展开。

Serverless 接管了哪些工作

Serverless 将部分实例创建、容量调整和回收交给平台,应用通过代码包、镜像或其他产品支持的形式运行。云服务器、容器、K8s 和 Serverless 处于不同层次:容器镜像既可以交给 K8s,也可以交给支持自定义镜像的 Serverless 平台。

以阿里云 FC 为例,当前技术选型文档覆盖 Web、事件、任务、GPU 和 Sandbox 等类型,分别面向 API、事件处理、异步工作和会话式执行环境等需求。

选择时,先读清楚运行规则:

规则 要确认的问题
触发与完成 HTTP、消息还是异步任务?平台什么时候认为本次执行结束?
执行时限 单次执行、请求连接和工具调用分别有什么时限?
实例并发 一个实例同时处理多少请求?共享对象是否并发安全?
生命周期 何时启动、冻结或回收?会话保活是什么语义?
存储 可写层、临时目录、挂载存储分别保存多久?
网络与身份 怎样访问 VPC 数据源、外部模型和云服务?
失败处理 是否重投或重试?怎样查询执行结果和取消任务?

“支持自定义镜像”解决了运行环境的交付问题,其他规则仍需要逐项对应到程序设计。

请求已经返回,后台工作还能继续吗

一个常见写法是在接口里启动后台协程,然后立即返回任务已提交。在普通进程里,它依赖进程继续存活;放到 Serverless 环境,还要满足平台的请求与实例生命周期规则。

阿里云 FC 的实例生命周期文档说明了通用函数的冻结机制:调用阶段结束、没有请求执行时,实例会被冻结,后台进程、线程或协程无法继续推进。

因此,需要独立持续执行的工作,应交给平台明确支持的异步任务机制或独立 Worker。会话沙箱、常驻或其他特殊模式,要按各自的生命周期核对,不能把一个模式的规则直接套到所有 Serverless 产品上。

类似地,HTTP 网关允许等待多久,与后台任务允许执行多久,也应分别核对。对于耗时分析,可以尽快返回 run_id,通过查询或事件连接展示后续进度。

冷启动、文件与网络

冷启动可能包括创建实例、拉取镜像、启动语言运行时、加载依赖和执行初始化。带浏览器或较多系统库的镜像,需要重点观察启动时间。FC 自定义镜像文档介绍了镜像体积、启动和临时存储等约束。

在 Excel 分析这个例子中,我会让沙箱把本地文件当作工作副本:输入从对象存储获取,最终报告上传到对象存储,数据库保存任务与产物的关联。需要保留会话文件时,也要确认保活、挂载或快照机制实际覆盖的生命周期。

网络则继续沿用第一篇的分析方法。FC 支持分别配置公网和 VPC 访问,也可以同时开启。需要固定出口 IP 时,再配置通过 VPC NAT 与 EIP 等能力出站,具体模式见网络配置文档。

发布时,正在运行的分析怎么办

平台在终止实例时,通常会提供一定的退出流程或回调。K8s 的 Pod 终止包含通知进程与宽限时间,之后仍可能强制结束,详见Pod 生命周期。

应用需要配合完成几件事:停止接收新工作,结束能在期限内完成的步骤,保存必要状态,按照队列协议确认或释放任务,再关闭连接。运行很久的分析不适合完全依赖“把宽限时间调大”;节点故障或强制终止仍可能跳过正常退出流程。

对沙箱还要记录谁负责回收。Worker 已经退出,但分析子进程或会话还在运行,会同时影响状态和成本。任务状态、执行环境和产物引用需要能够重新核对。

怎样选择第一条部署路径

我的选择顺序是先看现有平台,再看工作负载的实际要求:

已知条件 可以优先尝试的路径
希望完整理解程序启动、网络和磁盘 本地或云服务器上的 Docker Compose
团队已经有成熟 K8s 平台 按现有规范部署 API 与 Worker,补齐探针和资源配置
希望减少实例维护,任务符合平台运行规则 对应的 Serverless Web、任务或托管容器产品
需要执行生成代码或浏览器会话 单独评估沙箱的隔离、会话、文件和回收能力

这些路径可以组合。例如 API 使用团队已有集群,分析工具使用按需沙箱,数据库与对象存储使用托管服务。决策依据是组件职责、团队已有能力和实际运行约束。

第一轮验证可以聚焦四件事:新实例能否接到请求;启动失败能否看到原因;发布时旧任务能否完成或恢复;实例回收后结果是否仍能查询。把这条路径验证清楚,再扩展副本与自动化,会更容易定位变化带来的问题。


上一篇:进程、容器与沙箱 · 下一篇:让长任务能够恢复 · 系列导读