mcpField
K
Kubernetes Ephemeral Job

Kubernetes Ephemeral Job

本地服务
github.com/inhuman开发工具014 周前更新

关于 Kubernetes Ephemeral Job

Kubernetes Ephemeral Job 是面向 Agent 和自动化流程的 MCP 服务,可在 Kubernetes 中创建临时 Job 执行命令,并返回状态、输出和文件产物。它支持同步与后台任务,执行后删除 Pod,并通过服务端生成清单而非接受调用方提供的 YAML。

主要功能

  1. 01在临时 Kubernetes Pod 中运行命令
  2. 02同步运行或提交后台任务
  3. 03返回退出码、输出和文件产物
  4. 04支持仓库克隆与可控资源限制
  5. 05执行后删除 Pod

适用场景

  1. 01在指定镜像中运行构建或测试
  2. 02启动长时间任务并稍后收取结果
  3. 03克隆仓库后执行代码检查
  4. 04从运行结果中收集生成文件

MCP 相关

作为 MCP 服务,它向客户端提供 run_job、submit_job 和 fetch_job 工具,可通过 stdio、HTTP 或 SSE 使用。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"inhuman-mcp-k8s-ephemeral-job": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"MCP_K8S_ALLOWED_IMAGES",
"-e",
"MCP_K8S_KUBECONFIG",
"-e",
"MCP_K8S_NAMESPACE",
"-e",
"MCP_K8S_TRANSPORT",
"-e",
"MCP_K8S_DEFAULT_TIMEOUT_S",
"-e",
"MCP_K8S_MAX_TIMEOUT_S",
"-e",
"MCP_K8S_MAX_OUTPUT_BYTES",
"-e",
"MCP_K8S_MAX_ARTIFACT_BYTES",
"-e",
"MCP_K8S_MAX_CONCURRENT",
"-e",
"MCP_K8S_DEFAULT_CPU",
"-e",
"MCP_K8S_DEFAULT_MEMORY",
"-e",
"MCP_K8S_SIDECAR_IMAGE",
"-e",
"MCP_K8S_CLONE_IMAGE",
"-e",
"MCP_K8S_CLONE_SECRET",
"-e",
"MCP_K8S_CACHE_PVC",
"-e",
"MCP_K8S_CACHE_MOUNT_PATH",
"-e",
"MCP_K8S_JOB_EXTRA_ENV",
"-e",
"MCP_K8S_AUTH_TOKEN",
"docker.io/idconstruct/mcp-k8s-ephemeral-job:v0.7.1"
],
"env": {
"MCP_K8S_ALLOWED_IMAGES": "<MCP_K8S_ALLOWED_IMAGES>",
"MCP_K8S_KUBECONFIG": "<MCP_K8S_KUBECONFIG>",
"MCP_K8S_NAMESPACE": "<MCP_K8S_NAMESPACE>",
"MCP_K8S_TRANSPORT": "<MCP_K8S_TRANSPORT>",
"MCP_K8S_DEFAULT_TIMEOUT_S": "<MCP_K8S_DEFAULT_TIMEOUT_S>",
"MCP_K8S_MAX_TIMEOUT_S": "<MCP_K8S_MAX_TIMEOUT_S>",
"MCP_K8S_MAX_OUTPUT_BYTES": "<MCP_K8S_MAX_OUTPUT_BYTES>",
"MCP_K8S_MAX_ARTIFACT_BYTES": "<MCP_K8S_MAX_ARTIFACT_BYTES>",
"MCP_K8S_MAX_CONCURRENT": "<MCP_K8S_MAX_CONCURRENT>",
"MCP_K8S_DEFAULT_CPU": "<MCP_K8S_DEFAULT_CPU>",
"MCP_K8S_DEFAULT_MEMORY": "<MCP_K8S_DEFAULT_MEMORY>",
"MCP_K8S_SIDECAR_IMAGE": "<MCP_K8S_SIDECAR_IMAGE>",
"MCP_K8S_CLONE_IMAGE": "<MCP_K8S_CLONE_IMAGE>",
"MCP_K8S_CLONE_SECRET": "<MCP_K8S_CLONE_SECRET>",
"MCP_K8S_CACHE_PVC": "<MCP_K8S_CACHE_PVC>",
"MCP_K8S_CACHE_MOUNT_PATH": "<MCP_K8S_CACHE_MOUNT_PATH>",
"MCP_K8S_JOB_EXTRA_ENV": "<MCP_K8S_JOB_EXTRA_ENV>",
"MCP_K8S_AUTH_TOKEN": "<MCP_K8S_AUTH_TOKEN>"
}
}
}
}
启动命令docker run -i --rm -e MCP_K8S_ALLOWED_IMAGES -e MCP_K8S_KUBECONFIG -e MCP_K8S_NAMESPACE -e MCP_K8S_TRANSPORT -e MCP_K8S_DEFAULT_TIMEOUT_S -e MCP_K8S_MAX_TIMEOUT_S -e MCP_K8S_MAX_OUTPUT_BYTES -e MCP_K8S_MAX_ARTIFACT_BYTES -e MCP_K8S_MAX_CONCURRENT -e MCP_K8S_DEFAULT_CPU -e MCP_K8S_DEFAULT_MEMORY -e MCP_K8S_SIDECAR_IMAGE -e MCP_K8S_CLONE_IMAGE -e MCP_K8S_CLONE_SECRET -e MCP_K8S_CACHE_PVC -e MCP_K8S_CACHE_MOUNT_PATH -e MCP_K8S_JOB_EXTRA_ENV -e MCP_K8S_AUTH_TOKEN docker.io/idconstruct/mcp-k8s-ephemeral-job:v0.7.1
需要配置的环境变量
MCP_K8S_ALLOWED_IMAGESStrict image allowlist (CSV). Empty means every call is rejected, so this must be set.
MCP_K8S_KUBECONFIGPath to the kubeconfig inside the container. Empty = use in-cluster credentials.
MCP_K8S_NAMESPACENamespace the ephemeral pods are created in. Needs a Role/RoleBinding for jobs and pods.
MCP_K8S_TRANSPORTMCP transport: stdio | http | sse. Must be 'stdio' for direct docker/stdio use.
MCP_K8S_DEFAULT_TIMEOUT_SDefault wall-clock timeout per job, seconds.
MCP_K8S_MAX_TIMEOUT_SMaximum wall-clock timeout a caller may request, seconds.
MCP_K8S_MAX_OUTPUT_BYTESCap on combined stdout/stderr before truncation.
MCP_K8S_MAX_ARTIFACT_BYTESCap on the total size of returned artifacts.
MCP_K8S_MAX_CONCURRENTMaximum ephemeral pods running at the same time.
MCP_K8S_DEFAULT_CPUPod CPU request; limits come from the caller or the namespace LimitRange.
MCP_K8S_DEFAULT_MEMORYPod memory request; limits come from the caller or the namespace LimitRange.
MCP_K8S_SIDECAR_IMAGEHelper image used to inject input files and collect artifacts.
MCP_K8S_CLONE_IMAGEImage carrying git for the clone init container. Empty disables the clone field.
MCP_K8S_CLONE_SECRET密钥Secret with git tokens, mounted only on the cloner. Empty disables the clone field.
MCP_K8S_CACHE_PVCExisting PVC mounted into every job pod as a shared cache. Empty = no cache.
MCP_K8S_CACHE_MOUNT_PATHWhere the cache PVC is mounted, e.g. /go/pkg/mod. Empty = no cache.
MCP_K8S_JOB_EXTRA_ENVJSON object of env vars added to every job pod; caller keys win on collision.
MCP_K8S_AUTH_TOKEN密钥Optional X-MCP-AUTH token required on every request (http/sse transports only).

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocidocker.io/idconstruct/mcp-k8s-ephemeral-job:v0.7.1

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

mcp-k8s-ephemeral-job

English | Русский

Version MCP Registry Docker Pulls Docker Image Version Build Go Version Go Report Card License: MIT Issues Last Commit

面向公众的开源 MCP 服务(Go,MIT),可使用调用方选择的镜像启动一个临时 Kubernetes Job/Pod,在其中运行命令,返回 exit_code / stdout / 制品,并删除 Pod。服务会直接在代码中构建 Pod 清单——调用方只需传递参数,无需提供原始 YAML。

它是 mcp-exec(“手术刀”)的“手术室”搭档:mcp-exec 能在毫秒内于受限且无网络的沙箱中运行单个 Python 文件;而这个服务会启动一个完整 Pod,使用你选择的工具链/镜像,支持受控网络(克隆仓库、拉取依赖)、长时间任务和导出文件制品。两者互为补充。

支持三种传输方式——stdio / HTTP / SSE——无论使用哪种方式,工具集都完全相同(官方 modelcontextprotocol/go-sdk)。

工具

run_job — 运行并等待

输入:{ image (required), command (required), files?, env?, limits?, timeout_s?, workdir?, clone? } 输出:{ exit_code, stdout, stderr, duration_ms, status, artifacts, truncated }

  • status 的取值为 succeeded / failed / timeout / error。非零 exit_code 或 timeout 属于正常结果,不会被视为工具错误。只有输入无效(镜像/命令为空、镜像不在允许列表中、文件路径无效)才会导致工具调用错误。
  • stdout 包含容器的合并后 stdout+stderr——Kubernetes 会在 Pod 日志中合并这两个流。stderr 为保留字段,始终为空,因此将来添加流分离功能仍能保持向后兼容。
  • 制品(工作目录中的文件)会以 base64 格式内联返回,并受大小上限限制。超过上限时不会静默丢失数据:相应的 truncated 标志会被设为 true。
  • 服务以确定性方式构建清单——调用方无需提供原始 YAML。
submit_job / fetch_job — 在后台运行

submit_job 接受与 run_job 相同的参数,但会立即返回一个 job_token; fetch_job 稍后收集结果。这样,Agent 就可以启动长时间运行的任务(完整的测试套件、 构建),同时继续工作,而不必在一次同步调用中空等整个运行时间。

  • 任务运行期间,fetch_job 会返回 status=running;传入 wait_s(≤120)即可进行 长轮询,无需频繁轮询。任务完成后,它会立即返回,而不会等满整个等待时间。
  • 结果会保留 60 分钟,且可以多次获取。
  • 参数会在提交时验证,因此镜像有问题时,提交操作会失败,调用方仍可先修正问题。
  • 任务句柄保存在内存中(该服务按设计采用单副本):重启会丢弃待处理的令牌,调用方只需重新提交。
克隆仓库

使用 clone: { repo_url, ref, subdir? } 时,init 容器会在命令运行前将仓库检出到工作目录。 调用方无需处理凭据:服务会持有一个密钥,其中每个 Git 主机对应一个令牌;该密钥 仅挂载到克隆容器,之后会在 .git/config 中屏蔽令牌,主容器永远无法看到它。只有在 操作员配置了 MCP_K8S_CLONE_IMAGE + MCP_K8S_CLONE_SECRET 时,才接受 clone 字段。

安全模型(不变量)

每次运行都会创建一个全新的临时 Pod,之后将其删除(无论成功、失败还是超时)。服务的 RBAC 限定在命名空间范围内(使用 Role/RoleBinding,绝不使用 ClusterRole)——在 单个命名空间中授予 create/delete jobs,pods 以及 pods/log、pods/exec 权限。生成的 Pod 以 cap-drop=ALL、no-privilege-escalation 和 seccomp RuntimeDefault 运行。影响范围仅限于 该命名空间:LimitRange(每个 Pod 的默认值和上限)+ ResourceQuota(命名空间上限)+ 墙钟超时(→终止)+ TTL/所有者引用垃圾回收 + 并发上限。镜像必须通过严格的允许列表 (MCP_K8S_ALLOWED_IMAGES;为空表示不运行任何内容)。调用方数据(command / files / 输出 / 构件)绝不会持久化,也不会完整记录日志——只记录元数据。

run_job 是最强大的功能(它会创建 Pod)。将其嵌入 Agent 时,应通过该 Agent 的工具策略 限制访问(仅限受信任的角色)。

网络说明:Pod 的网络不会禁用(克隆仓库/拉取依赖项需要网络)。 出口流量由命名空间 NetworkPolicy(允许列表)控制,这是部署配置的一部分,并非代码内置 的限制。安全不变量是临时性 + 删除,而不是禁用网络。

资源:服务的 MCP_K8S_DEFAULT_CPU/MEMORY 是 Pod 的请求值(调度器的预留值)。 仅当调用方传入 limits 时才会设置限制;否则,上限由命名空间的 LimitRange 决定。 传入 limits.memory 也会相应提高内存请求,使其与限制相同,因为内存不可压缩,Pod 必须 调度到实际有足够内存的节点上。

运行

已在 MCP Registry 中发布,名称为 io.github.inhuman/mcp-k8s-ephemeral-job;镜像托管在 Docker Hub,名称为 idconstruct/mcp-k8s-ephemeral-job。

docker run --rm -i \
  -v "$HOME/.kube:/kube:ro" \
  -e MCP_K8S_KUBECONFIG=/kube/config \
  -e MCP_K8S_NAMESPACE=ephemeral-dev \
  -e MCP_K8S_ALLOWED_IMAGES=busybox:1.36,python:3.12-slim \
  idconstruct/mcp-k8s-ephemeral-job:latest

从源代码运行,连接开发集群,使用 stdio:

go build -o mcp-k8s-ephemeral-job ./cmd/mcp-k8s-ephemeral-job
export MCP_K8S_KUBECONFIG=$HOME/.kube/config
export MCP_K8S_NAMESPACE=ephemeral-dev
export MCP_K8S_ALLOWED_IMAGES=busybox:1.36,python:3.12-slim
./mcp-k8s-ephemeral-job

在生产环境中,服务以 Deployment 的形式在集群内运行,并配有自己的 ServiceAccount,以及 临时命名空间中的 Role/RoleBinding、ResourceQuota/LimitRange(可选的出口流量 NetworkPolicy),通常使用 http 传输方式。

调用示例(run_job)
{
  "image": "python:3.12-slim",
  "command": ["python", "gen.py"],
  "files": [{ "path": "gen.py", "content_b64": "<base64 of a script writing out.png>" }],
  "limits": { "cpu": "500m", "memory": "256Mi" },
  "timeout_s": 30
}

返回 exit_code、捕获的输出,以及内嵌在 artifacts 中的 out.png。之后 Pod 即被删除(kubectl get jobs,pods -n $NS 返回空)。

可选身份验证(HTTP/SSE)

设置 MCP_K8S_AUTH_TOKEN,要求每个 HTTP/SSE 请求都携带匹配的 X-MCP-AUTH 标头 (以恒定时间进行比较;否则返回 401)。令牌为空时会禁用身份验证。不适用于 stdio。

配置

环境变量用途默认值
MCP_K8S_TRANSPORTstdio | http | ssestdio
MCP_K8S_ADDRhttp/sse 的监听地址:8080
MCP_K8S_NAMESPACE临时 Pod 的创建命名空间mcp-ephemeral
MCP_K8S_DEFAULT_TIMEOUT_S默认墙钟超时时间(秒)60
MCP_K8S_MAX_TIMEOUT_S超时时间上限(秒)600
MCP_K8S_MAX_OUTPUT_BYTESstdout 和 stderr 的合计上限1048576
MCP_K8S_MAX_ARTIFACT_BYTES工件总大小上限10485760
MCP_K8S_DEFAULT_CPUPod CPU 请求量(调度预留;限制取自调用方的 limits 或命名空间的 LimitRange)1
MCP_K8S_DEFAULT_MEMORYPod 内存请求量(见上文)512Mi
MCP_K8S_MAX_CONCURRENT临时 Pod 的最大并发数(超出时排队或报错)10
MCP_K8S_ALLOWED_IMAGES严格的镜像允许列表(CSV);为空 = 全部拒绝``
MCP_K8S_SIDECAR_IMAGE用于收集工件的辅助 sidecar 镜像(固定版本)busybox:1.36
MCP_K8S_CLONE_IMAGE含 git 的镜像,用于 clone init 容器;为空 = clone 不可用``
MCP_K8S_CLONE_SECRET存放每个 git 主机一个令牌的 secret(键 = 主机);仅挂载到克隆容器``
MCP_K8S_CACHE_PVC挂载到每个作业 Pod 的现有 PVC,作为共享缓存;为空 = 不使用缓存``
MCP_K8S_CACHE_MOUNT_PATH缓存 PVC 的挂载位置,例如 /go/pkg/mod``
MCP_K8S_JOB_EXTRA_ENV添加到每个作业 Pod 的 JSON 对象 {"KEY":"value"};调用方的键优先``
MCP_K8S_KUBECONFIGkubeconfig 的路径;为空 = 集群内配置``
MCP_K8S_AUTH_TOKEN若设置,http/sse 需要 X-MCP-AUTH 标头(恒定时间比较);为空 = 关闭``

必须同时设置两个缓存变量才能挂载缓存。PVC 本身需在带外配置(helm/manifest);服务仅通过名称引用它,如果启动时发现它不存在,就会立即失败。

尚未实现

用于传递过大而无法内嵌的工件的 PVC / 对象存储、多集群支持,以及将其他 MCP 服务代理到 Pod 中。

许可证

MIT。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。