powered by TechFeed
表示モード
Deep Dive

KubernetesでAIエージェントを安全に動かす — 誰もレビューしていないLLM生成コードを本番で実行するリスクをどう封じるか

11月5日、Nirmataが「How to sandbox AI agents on Kubernetes」と題した記事を公開した。LLMが生成したコードをそのまま実行するAIエージェントは、誰もレビューしていないコードを動かすという点で、従来のコンテナワークロードとは性質が根本的に異なる。コンテナエスケープ、テナント間のネットワーク攻撃、Kubernetes APIの悪用——こうしたリスクは「起きるかもしれない」ではなく、審査なしに任意コードが実行される以上、設計上の前提として扱うべきだ。本記事では、Kubernetes SIG Appsのプロジェクトである**Agent Sandbox**を軸に、Pod隔離・egress制限・RuntimeClassの設定まで踏み込んだ手順を解説している。

11月5日、Nirmataが「How to sandbox AI agents on Kubernetes」と題した記事を公開した。LLMが生成したコードをそのまま実行するAIエージェントは、誰もレビューしていないコードを動かすという点で、従来のコンテナワークロードとは性質が根本的に異なる。コンテナエスケープ、テナント間のネットワーク攻撃、Kubernetes APIの悪用——こうしたリスクは「起きるかもしれない」ではなく、審査なしに任意コードが実行される以上、設計上の前提として扱うべきだ。本記事では、Kubernetes SIG Appsのプロジェクトである**Agent Sandbox**を軸に、Pod隔離・egress制限・RuntimeClassの設定まで踏み込んだ手順を解説している。


まず脅威を整理する

Agent Sandboxの脅威モデルが定義するリスクと対策は以下の通りだ。

リスク 対策 設定箇所
コンテナエスケープ gVisor / Kata Containers等のセキュアランタイム RuntimeClass
コンテナ内での権限昇格 非rootユーザー、privilege escalation無効、全capability削除 securityContext
テナント間ネットワーク攻撃 デフォルトdeny egress NetworkPolicy
Kubernetes API悪用 サービスアカウントトークン非マウント automountServiceAccountToken: false
リソース枯渇 CPU・メモリのrequests/limits resources
不正なサンドボックス作成 Sandboxリソースへのアクセス制限 RBAC

Agent Sandboxのインストール

Agent SandboxはSandboxというCRD(カスタムリソース定義)を追加し、単一のステートフルPodにステーブルなIDと永続ストレージを提供する。Agent Sandbox自体は隔離機能を持たない。隔離はRuntime・NetworkPolicy・securityContextの組み合わせで実現する点に注意が必要だ。

Kubernetes 1.25以降が必要で、CRDのCELバリデーションが安定した1.29以降が推奨される。元記事執筆時点の最新バージョンはv1.0.2だ。なお、2026年11月時点でAgent SandboxはKubernetes SIG Appsのサブプロジェクトとして開発が進んでいるが、本番採用を検討する場合はGitHubリポジトリでGAステータスや最新リリースノートを必ず確認した上で判断してほしい。

export VERSION="v1.0.2"
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/${VERSION}/sandbox-with-extensions.yaml
kubectl get crd sandboxes.agents.x-k8s.io
kubectl get deploy agent-sandbox-controller -n agent-sandbox-system
kubectl create namespace agents

GitOps運用を考慮し、バージョンはv1.0.2のように必ずピン留めすることが推奨されている。


Podセキュリティコンテキストの強化(最も重要な設定)

SandboxはpodTemplateをフルで受け取る。Pod Security Standardsのrestrictedプロファイルに準拠した設定が求められる。

KubernetesはデフォルトでallowPrivilegeEscalationがtrueになっているため、明示的にfalseを指定する必要がある。

apiVersion: agents.x-k8s.io/v1beta1
kind: Sandbox
metadata:
  name: agent-hardened
  namespace: agents
spec:
  podTemplate:
    spec:
      automountServiceAccountToken: false
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: agent
        image: registry.k8s.io/e2e-test-images/agnhost:2.45
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        resources:
          requests:
            cpu: "250m"
            memory: "256Mi"
          limits:
            cpu: "1"
            memory: "1Gi"

Namespaceにpod-security.kubernetes.io/enforce: restrictedラベルを付けておくと、Podアドミッションがバックストップとして機能し、マニフェストに設定漏れがあってもPod作成時に弾かれる。

apiVersion: v1
kind: Namespace
metadata:
  name: agents
  labels:
    pod-security.kubernetes.io/enforce: restricted

egressをデフォルトdenyにする

NetworkPolicyが存在しない状態のPodはegress非隔離——つまり全通信が許可されている。以下のポリシーをSandboxより先に適用することが必須だ。ネットワークプラグインがNetworkPolicyを処理する前にPodが起動すると、保護されていない状態で起動する可能性があるためだ。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: agents
spec:
  podSelector: {}
  policyTypes:
  - Egress

このポリシーはDNSも遮断するため、クラスターのDNSサービスへのegressを許可する別のNetworkPolicyを追加した上で、エージェントが必要とする宛先だけをホワイトリスト登録する必要がある。


RuntimeClassで非信頼コードを強力に隔離

gVisorやKata Containersを使うと、カーネルレベルの隔離が加わる。containerdまたはCRI-O側にハンドラー設定が必要で、RuntimeClassが存在しないかハンドラーが動作しない場合、PodはFailed状態になる。

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: agent-isolated
handler: myconfiguration  # ※ノードに設定済みのランタイムハンドラー名に置き換える(例:gvisor、kata等)
spec:
  podTemplate:
    spec:
      runtimeClassName: agent-isolated
方式 追加される隔離 用途
セキュリティコンテキストのみ Pod設定・NetworkPolicy・limitsのみ レビュー済みコードを動かすエージェント
gVisor / Kata Containers カーネル・ネットワーク隔離 非信頼コード・LLM生成コード

KyvernoによるAdmission制御

誰がSandboxを作成しても設定を強制するには、アドミッションコントロールが適切なレイヤーだ。Kyvernoポリシーライブラリには全コンテナにALL capabilityのdropを要求するClusterPolicyが用意されている。サンプルはAuditモードで動作するため、まず開発クラスターで試してからEnforceに切り替えるのが安全だ。

RBACとAdmission制御は両方使うのが原則だ。RBACはSandboxリソースを誰が作れるかを制御し、Admission制御はリソースの中身を検査する。


SandboxCRD削除時の注意

アンインストール前には必ず以下で残存リソースを確認すること。CRDを削除すると、全Namespace上の対応するカスタムリソースがカスケード削除される。

kubectl get sandboxes -A
kubectl get sandboxclaims -A

最低限押さえるべきポイント

ここまでの手順は多岐にわたるが、「まず何をすべきか」を整理すると以下の3点に集約される。

  1. securityContextの徹底:allowPrivilegeEscalation: false・capabilities.drop: ALL・非rootユーザーの3点は必須で、Namespace側のPod Security Standardsラベルでバックストップをかける
  2. egressのデフォルトdeny:NetworkPolicyをSandboxより先に適用し、必要な宛先だけを明示的に許可する。DNSも遮断対象になるため忘れずに追加する
  3. LLM生成コードにはRuntimeClassを:gVisorやKata Containersによるカーネルレベルの隔離は、securityContextだけでは防げないコンテナエスケープへの有効な追加防御層となる

RBACとAdmission制御(Kyverno等)は、これらを「誰が設定しても」強制するための仕組みとして、チーム運用に入った段階で合わせて整備したい。


詳細はHow to sandbox AI agents on Kubernetesを参照していただきたい。