这次准备把一个 AI Agent 的工具服务放到 K8s 上跑。还没到完整上线阶段,只是先做预检:MCP Server 能不能启动,工具依赖能不能就绪,Secret 怎么放,日志能不能看清楚。
我不想一上来就写一堆 Deployment。Agent 工具服务一旦接 Git、浏览器、数据库,权限和边界会比普通接口服务更敏感。
这个环境后面主要服务几个场景:代码仓库巡检、发布前测试页面巡检、只读数据查询和运维 runbook。Agent 的好处是把这些动作串成一段流程,让人少在 Git、测试环境、日志和数据面板之间来回切。
所以这次预检不是为了单独证明某个依赖能下载,而是为了确认这些工具服务以后能被稳定、受控地调起来。
先在节点上验证工具依赖
如果基础依赖没有就绪,后面看 Pod 事件只会看到 ImagePullBackOff 或长时间 Pulling。
docker pull ghcr.1ms.run/github/github-mcp-server
docker pull mcr.1ms.run/playwright/mcp
docker pull docker.1ms.run/postgres:16-alpine
docker pull docker.1ms.run/redis:7-alpine
这一步是为了把工具依赖问题先排除。真正的权限和网络问题,留到 Pod 启动后再看。
工具服务单独放一个 namespace
我先建了一个 agent-tools:
apiVersion: v1
kind: Namespace
metadata:
name: agent-tools
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: mcp-runner
namespace: agent-tools
这样至少不会和主业务服务混在一个 namespace 里。后面要收网络出口、资源限制和 Secret,也比较清楚。
MCP Server 先跑最小版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-github
namespace: agent-tools
spec:
replicas: 1
selector:
matchLabels:
app: mcp-github
template:
metadata:
labels:
app: mcp-github
spec:
serviceAccountName: mcp-runner
containers:
- name: mcp-github
image: ghcr.1ms.run/github/github-mcp-server
envFrom:
- secretRef:
name: github-readonly-token
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
这个版本只做几件事:独立 namespace,独立 ServiceAccount,token 放 Secret,容器尽量只读。
事件和日志要先能看清
kubectl -n agent-tools get pod
kubectl -n agent-tools describe pod -l app=mcp-github
kubectl -n agent-tools logs deploy/mcp-github --tail=120
如果是依赖问题,事件里会很直接。
如果是 token 或网络问题,通常要看 MCP Server 自己的日志。
我不希望所有错误都只落到 Agent 应用日志里。工具服务既然独立跑,就要能独立定位。
这次预检保留下来的几条
- 工具依赖先拆开验证,不把所有问题留给 Pod 事件。
- MCP Server 放独立 namespace。
- token 用 Secret,不写进镜像和配置文件。
- 工具容器先按只读文件系统处理。
- 日志要能看到工具服务自己的错误。
- Agent 应用和 MCP Server 后续要能独立回滚。
复盘
K8s 上跑 AI Agent 工具服务,不能只看 Deployment 是否创建成功。Agent 的价值在于把代码、测试、数据和运维检查串起来;接入 MCP 后,真正要看的是依赖来源、Secret、网络出口、日志和回滚边界。
这次只是预检,但至少把第一层问题分清了:工具依赖是一层,工具权限是一层,K8s 运行边界又是一层。分开看,后面接更多工具时不会乱。