広告

AIエージェントが私のクラスターを壊せないように、読み取り専用のkubectlを作った

Dev.to / 2026/3/29

💬 オピニオンDeveloper Stack & InfrastructureTools & Practical Usage

要点

  • 著者は、AI(Claude)にステージングのKubernetesクラスターへのアクセスを与えたことで、kubectl execやシークレットの取得を通じて、読み取りと情報流出に近い行動をしようとする“ニアミス”が起きかけた経験を語っている。
  • 著者はkubectl-roを作成した。これはkubectlのクライアントサイドラッパーで、kubectlの実行前に「変更(状態変更)を伴う」kubectlコマンドをすべてブロックしながら、getやlogsのような読み取り専用操作は許可する。
  • このツールは、基本的なシークレットのメタデータ(例:名前や型)が見える場合があっても、シークレット値そのものの抽出を防ぐことで、シークレット漏えいのリスクをさらに軽減する。
  • kubectl-roはMCPサーバーとしても動かせ(kubectl-ro serve)、AIエージェントが呼び出せる一連の読み取り専用ツールを公開する。MCPモードではシークレット値は自動的に秘匿(マスク)される。
  • 記事では、RBACは引き続き使用すべきだと主張しつつ、kubectl-roを、クラスターに変更を加えずにAIとクラスター統合を安全に進めるための“シートベルト”として位置づけている。

先月、私は Claude に当社のステージング・クラスターの1つへのアクセスを許可しました。数分もしないうちに、ポッドへ kubectl exec を試みて kubectl get secret -o yaml を実行しました。何か悪いことが起きたわけではありませんが、こう考えさせられました。もしそれが本番(production)だったらどうなっていたのだろう?

そこで私は kubectl-ro を作りました。

それができること

これは kubectl の薄いラッパーで、読み取り専用のコマンドだけを許可します。使い方は kubectl とまったく同じです:

kubectl-ro get pods -n kube-system        # 動作する
kubectl-ro logs deployment/my-app          # 動作する
kubectl-ro delete pod nginx                # だめ
# ✘ BLOCKED: 'delete' はミューテーション(変更)コマンド

それだけです。もしそのコマンドがクラスターの何かを変更する可能性がある場合、kubectl に渡される前にブロックされます。

なぜRBACではなくこれなのか?

RBAC は絶対に使うべきです。ですが RBAC はサーバー側です。クラスター管理者によるセットアップ、サービスアカウント、ロールバインディングが必要になります。kubectl-ro はクライアント側です。インストールして、AIエージェントにそれを指すだけで終わりです。クラスターの変更は不要です。

たとえば、エアバッグの代わりではなくシートベルトのようなものだと思ってください。

さらにシークレットも保護します

ここが私が最も驚いた点でした。「読み取り専用」の kubectl でも機密データが漏れることがあります:

kubectl get secret db-creds -o yaml    # パスワードをbase64で出力する
kubectl describe secret db-creds       # 同じ内容、別の形式

kubectl-ro はこれらをブロックします。シークレットを一覧表示(名前と種類)することはできますが、値を取り出すことはできません。MCP モードでは、シークレットの値は [REDACTED] に自動的に置き換えられます。

MCPサーバーとしても動作します

ここは私が特にワクワクしているところです。kubectl-ro serve を実行すると、20 個の読み取り専用ツールを備えた MCPサーバー になり、あらゆるAIエージェントがそれを利用できます:

{
  "mcpServers": {
    "kubectl-ro": {
      "command": "kubectl-ro",
      "args": [ "serve" ]
    }
  }
}

これであなたのAIは list_podsget_pod_logslist_deploymentsget_events ができるようになります。AIが見てほしいものだけを見られて、触れるべきでないものには触れません。

ポリシーはどのように機能するか

設定ファイルはありません。ポリシーは意図的にバイナリに埋め込まれています。誤って設定を間違えることはありません。

ロジックはシンプルです:

  • ミューテーション(変更)コマンド(delete、apply、create、exec、scale、drain...)→ 常にブロック
  • 読み取りコマンド(get、describe、logs、top、events...)→ シークレットのチェック付きで許可
  • 不明なコマンド → デフォルトでブロック(フェイルセーフ)

さらに、制御文字を含む引数も拒否します。これは、LLMが奇妙なバイト列を幻覚として生成することで起きる一種のプロンプトインジェクション攻撃を防ぎます。

すべてのアクションがログに記録される

すべてが ~/.kubectl-ro/audit.log に出力されます:

{"timestamp":"2026-03-29T13:04:36Z","action":"get pods","result":"allowed"}
{
"timestamp":"2026-03-29T13:04:36Z",
"action":"delete pod x",
"result":"blocked",
"reason":"'delete' はミューテーション(変更)コマンド"}

なので、もし何かおかしなことが起きたら、何が試みられたのかをそのまま確認できます。

まず試してみる

go install github.com/soyvural/kubectl-ro@latest

または リリースページ からバイナリを取得してください。

何も実行せずにポリシーをテストできます:

kubectl-ro --check get pods           # 出力: OK
kubectl-ro --check delete pod nginx   # 出力: BLOCKED

PATH に入れれば kubectl プラグインとしても動作します:kubectl ro get pods

リポジトリは github.com/soyvural/kubectl-ro です。MIT ライセンスで、Go で書かれており、外部の実行時依存関係はゼロです。

AIエージェントにあなたのクラスターへのアクセスを許可している場合、安全面をどのように扱っているのかぜひ聞かせてください。あなたの方針は何ですか?

広告