# Agent 工程运维（三）：K8s 与 Serverless 的运行边界

作者：zhongling
原文：https://zhixia.pages.dev/posts/agent-infra-k8s-serverless/
发布日期：2026-11-12
更新日期：2026-11-12
语言：zh

摘要：从 Agent API、后台 Worker 与沙箱的运行需求出发，理解 Kubernetes 的调度、资源与探针，以及 Serverless 的冷启动、并发、实例生命周期和平台选择。

---


[上一篇](/posts/agent-infra-runtime/)把程序拆成进程、镜像、容器和文件。镜像已经能够运行以后，接下来要考虑：启动多少个实例？流量怎样进来？进程失败后谁来重启？发布时，旧实例正在执行的任务怎么办？

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

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

> 本文由 AI 辅助整理，属于 [Agent 工程运维系列](/posts/agent-infra-overview/)。配置片段用于解释机制，未部署到真实业务环境；具体配额、执行时限和产品功能以实际使用的平台为准。

## 先分清三类工作负载

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

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

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

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

## K8s 怎样维护期望状态

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

如果容器退出，平台可以按策略重启；如果工作负载副本丢失，控制器可以创建替代实例。这个机制使服务能够在实例变化中持续运行。[Kubernetes 概览](https://kubernetes.io/docs/concepts/overview/)和[自愈说明](https://kubernetes.io/docs/concepts/architecture/self-healing/)描述了这些能力。

对开发者来说，可以先认识这些对象：

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

其中，Service 让调用方不必写死某个 Pod 的地址；Gateway、Ingress 和网络策略需要相应实现才能生效。可以结合[Kubernetes 网络概念](https://kubernetes.io/docs/concepts/services-networking/)理解服务发现、流量入口与网络控制的关系。

Namespace 用于组织资源，并能作为权限、配额等策略的作用范围。租户隔离还需要进一步配置网络、存储和权限，具体边界见[多租户文档](https://kubernetes.io/docs/concepts/security/multi-tenancy/)。

## 资源配置怎样影响程序

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

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

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

例如，容器片段可以这样写：

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

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

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

## 健康检查应该检查什么

K8s 常见的三种探针，关注不同阶段：

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

启动探针适合初始化较慢的应用；就绪探针决定何时接流量；存活探针需要谨慎，避免将暂时性拥塞变成反复重启。[探针文档](https://kubernetes.io/docs/concepts/workloads/pods/probes/)对这三类语义有明确区分。

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

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

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

HPA 可以根据资源、自定义或外部指标调整副本数。对于大量时间花在等待模型响应的 Worker，可以结合排队时长、积压和执行槽位观察，而不是只看 CPU。[HPA 文档](https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/)提供了指标与扩缩容机制的说明。

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

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

因此，我会把两个配置分别记录：一份描述实例怎样运行，另一份描述任务怎样恢复。后者在[第四篇](/posts/agent-infra-durable-execution/)展开。

## Serverless 接管了哪些工作

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

以阿里云 FC 为例，当前[技术选型文档](https://help.aliyun.com/zh/functioncompute/selection-of-method-to-create-functions)覆盖 Web、事件、任务、GPU 和 Sandbox 等类型，分别面向 API、事件处理、异步工作和会话式执行环境等需求。

选择时，先读清楚运行规则：

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

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

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

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

阿里云 FC 的[实例生命周期文档](https://help.aliyun.com/zh/functioncompute/function-instance-lifecycle)说明了通用函数的冻结机制：调用阶段结束、没有请求执行时，实例会被冻结，后台进程、线程或协程无法继续推进。

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

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

## 冷启动、文件与网络

冷启动可能包括创建实例、拉取镜像、启动语言运行时、加载依赖和执行初始化。带浏览器或较多系统库的镜像，需要重点观察启动时间。[FC 自定义镜像文档](https://help.aliyun.com/zh/functioncompute/custom-container/)介绍了镜像体积、启动和临时存储等约束。

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

网络则继续沿用[第一篇](/posts/agent-infra-network/)的分析方法。FC 支持分别配置公网和 VPC 访问，也可以同时开启。需要固定出口 IP 时，再配置通过 VPC NAT 与 EIP 等能力出站，具体模式见[网络配置文档](https://help.aliyun.com/zh/functioncompute/configure-network-settings)。

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

平台在终止实例时，通常会提供一定的退出流程或回调。K8s 的 Pod 终止包含通知进程与宽限时间，之后仍可能强制结束，详见[Pod 生命周期](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination)。

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

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

## 怎样选择第一条部署路径

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

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

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

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

---

上一篇：[进程、容器与沙箱](/posts/agent-infra-runtime/) · 下一篇：[让长任务能够恢复](/posts/agent-infra-durable-execution/) · [系列导读](/posts/agent-infra-overview/)

