Kubernetes Ephemeral Job について
Kubernetes Ephemeral Job は、Agent や自動化処理向けに、一時的な Kubernetes Job でコマンドを実行し、状態、出力、ファイル成果物を返す MCP サーバーです。同期実行とバックグラウンド実行に対応し、実行後に Pod を削除します。呼び出し側の YAML ではなく、サーバーがマニフェストを生成します。
主な機能
- 01一時的な Kubernetes Pod でコマンド実行
- 02同期実行とバックグラウンド実行
- 03終了コード、出力、成果物の返却
- 04リポジトリのクローンとリソース制限
- 05実行後の Pod 削除
活用シーン
- 01指定イメージでビルドやテストを実行
- 02長時間ジョブを開始して後で結果を取得
- 03リポジトリをクローンしてコードを検査
- 04ジョブ結果から生成ファイルを収集
MCP 対応
MCP サーバーとして run_job、submit_job、fetch_job ツールを提供し、stdio、HTTP、SSE でクライアントから利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
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.1MCP_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 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
mcp-k8s-ephemeral-job
英語 | ロシア語
公開 OSS の MCP サーバー(Go、MIT)です。呼び出し側が選択したイメージから一時的な Kubernetes Job/podを起動し、その中でコマンドを実行して、exit_code/stdout/アーティファクトを返した後、pod を削除します。サーバーはコード内で pod マニフェストを構築するため、呼び出し側が渡すのはパラメーターのみで、YAML を直接渡すことはありません。
mcp-exec(「メス」)に対する「手術室」のような位置付けです。mcp-exec がロックダウンされたネットワークなしのサンドボックスで単一の Python ファイルをミリ秒単位で実行するのに対し、こちらは選択したツールチェーン/イメージを備えた完全な podを起動し、制御されたネットワーク(リポジトリのクローン、依存関係の取得)、長時間のタスク、ファイルのアーティファクト出力に対応します。両者は互いを補完します。
stdio/HTTP/SSEの3種類のトランスポートで動作し、どのトランスポートでも同じツールセットを利用できます(公式の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は通常の結果であり、ツールエラーではありません。無効な入力(image/command が空、image が許可リストにない、不正なファイルパス)の場合のみ、ツール呼び出しエラーになります。stdoutにはコンテナーの標準出力と標準エラー出力を結合した内容が含まれます。Kubernetes は pod のログで2つのストリームを統合します。stderrは将来のストリーム分離を後方互換性のある形で実現できるよう予約されており、常に空です。- アーティファクト(作業ディレクトリ内のファイル)は、サイズ上限の範囲内でインライン(base64)で返されます。上限を超えた場合もデータが黙って失われることはなく、対応する
truncatedフラグが設定されます。 - マニフェストはサーバーによって決定的に構築されます。呼び出し側から生の YAML を渡すことはありません。
submit_job / fetch_job — バックグラウンドで実行
submit_job は run_job と同じ引数を受け取りますが、job_token をすぐに返します。fetch_job で後から結果を取得します。これにより、エージェントは時間のかかるジョブ(テスト一式やビルドなど)を開始したあと、同期呼び出しが完了するまで待機することなく作業を続けられます。
- ジョブの実行中は、
fetch_jobはstatus=runningを返します。頻繁にポーリングする代わりに、wait_s(≤120)を渡してロングポーリングできます。指定した待機時間が終わるまで待つのではなく、ジョブが完了するとすぐに応答します。 - 結果は60分間保持され、複数回取得できます。
- 引数は送信時に検証されるため、無効なイメージを指定すると送信が失敗し、呼び出し元はその時点で修正できます。
- ハンドルはメモリ上に保持されます(設計上、サーバーは単一レプリカです)。再起動すると保留中のトークンは失われるため、呼び出し元は単に再送信します。
リポジトリのクローン
clone: { repo_url, ref, subdir? } を指定すると、コマンドの実行前に init コンテナーがリポジトリを作業ディレクトリにチェックアウトします。呼び出し元が認証情報を扱うことはありません。サーバーは Git ホストごとに1つのトークンを含むシークレットを保持し、これをクローン処理を行うコンテナーにのみマウントします。その後、.git/config 内のトークンはマスクされるため、メインコンテナーからは見えません。clone フィールドは、オペレーターが MCP_K8S_CLONE_IMAGE と MCP_K8S_CLONE_SECRET を設定している場合にのみ使用できます。
セキュリティモデル(不変条件)
実行ごとに新しい一時 Podを作成し、その後(成功/失敗/タイムアウト時に)削除します。サーバーの RBAC は名前空間スコープです(ClusterRole ではなく、Role/RoleBinding を使用)。権限は1つの名前空間内での create/delete jobs,pods と pods/log、pods/exec に限られます。起動する Pod は cap-drop=ALL、no-privilege-escalation、seccomp RuntimeDefault で実行されます。影響範囲はその1つの名前空間です。LimitRange(Pod ごとのデフォルト値と最大値)+ResourceQuota(名前空間の上限)+ウォールクロックタイムアウト(→強制終了)+TTL/オーナー参照による GC +同時実行数の上限を適用します。イメージは厳格な許可リスト(MCP_K8S_ALLOWED_IMAGES。空の場合は何も実行できません)を通過する必要があります。呼び出し元のデータ(command/files/出力/アーティファクト)は永続化されず、全内容がログに記録されることもありません。メタデータのみが記録されます。
run_jobは最も強力な機能です(Pod を作成します)。エージェントに組み込む場合は、そのエージェントのツールポリシーで制限してください(信頼されたロールのみ)。
ネットワークに関する注意: 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
本番環境では通常、http トランスポートを使用し、サーバーを独自の ServiceAccount とともに Deployment としてクラスター内で実行します。エフェメラル名前空間には Role/RoleBinding と ResourceQuota/LimitRange(および必要に応じてエグレス用の NetworkPolicy)を設定します。
呼び出し例(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_TRANSPORT | stdio | http | sse | stdio |
MCP_K8S_ADDR | http/sse のリッスンアドレス | :8080 |
MCP_K8S_NAMESPACE | 一時 Pod の起動先ネームスペース | mcp-ephemeral |
MCP_K8S_DEFAULT_TIMEOUT_S | デフォルトの実時間タイムアウト(秒) | 60 |
MCP_K8S_MAX_TIMEOUT_S | タイムアウトの上限 | 600 |
MCP_K8S_MAX_OUTPUT_BYTES | stdout と stderr の合計上限 | 1048576 |
MCP_K8S_MAX_ARTIFACT_BYTES | アーティファクトの合計サイズ上限 | 10485760 |
MCP_K8S_DEFAULT_CPU | Pod の CPU リクエスト(スケジューリング用の予約。制限は呼び出し元の limits またはネームスペースの LimitRange によって決まります) | 1 |
MCP_K8S_DEFAULT_MEMORY | Pod のメモリリクエスト(上記を参照) | 512Mi |
MCP_K8S_MAX_CONCURRENT | 同時に実行できる一時 Pod の最大数(超過時はキューに入れるか、エラーになります) | 10 |
MCP_K8S_ALLOWED_IMAGES | 厳格なイメージ許可リスト(CSV)。空の場合はすべて拒否 | `` |
MCP_K8S_SIDECAR_IMAGE | アーティファクト収集用のヘルパーサイドカーイメージ(固定) | busybox:1.36 |
MCP_K8S_CLONE_IMAGE | clone init コンテナ用の git を含むイメージ。空の場合、clone は利用できません | `` |
MCP_K8S_CLONE_SECRET | git ホストごとに 1 つのトークンを保持するシークレット(キー = ホスト)。クローン用コンテナにのみマウントされます | `` |
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_KUBECONFIG | kubeconfig へのパス。空の場合、クラスター内の設定が使われます | `` |
MCP_K8S_AUTH_TOKEN | 設定すると、http/sse で X-MCP-AUTH ヘッダーが必須になります(時間一定比較)。空の場合、無効です | `` |
キャッシュをマウントするには、両方のキャッシュ変数を設定する必要があります。PVC 自体は別途(helm/manifest で)プロビジョニングします。サーバーは名前で PVC を参照するだけで、PVC が見つからない場合は起動時に即座に失敗します。
未実装
インラインで返すには大きすぎるアーティファクトのための PVC/オブジェクトストレージ経由の配信、マルチクラスター対応、および Pod 内での他の MCP サーバーのプロキシ処理。
ライセンス
MIT。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。