
ある検証用のマルチテナントクラスタで、テナントAのPodからテナントBのSecretsが読めてしまうという事故が起きた。原因を追うと、どちらのテナントのNamespaceにも「k3s vs k8s」の比較記事でよく語られるような特別な設定ミスはなかった。あったのは、Namespace作成時に自動生成されるdefaultServiceAccountのトークンが、何も考えずにPodへ自動マウントされ続けていたという、ただそれだけの状態だった。
1. 検証クラスタで起きた「隣のテナントのSecretが読めた」という事故
経緯はこうだ。複数チームが同じK3sクラスタを共有する検証環境で、チームごとにNamespaceを分けて「隔離できている」とみなしていた。しかしRoleBindingの一部がClusterRoleに紐づくClusterRoleBindingとして広めに設定されており、あるPodのdefaultServiceAccountトークンを使ってAPIサーバーに問い合わせると、本来アクセスできないはずの別Namespaceのリソースが列挙できてしまった。
攻撃者がまず侵入後に探すのは、まさにこの種の「使われていないのに存在する」認証情報だ。多くのPodには実際にはKubernetes APIを呼ぶ処理など存在しないにもかかわらず、トークンだけは律儀にマウントされている。この種の横展開(lateral movement)のパターンは、MITRE ATT&CKの観点からも繰り返し指摘されている(Red Hatの解説記事)。マネージドなK8s基盤であれば、こうした放置資産の存在そのものに運用者が気づきやすい設計にしやすい。Kuboのようにクラスタの構成をCaptain UIの可視化された管理画面で把握できる環境は、この種の「気づかれない穴」を減らす選択肢になる。
2. k3s vs k8sで比較しても、"defaultのServiceAccount"は同じ罠を持っている

ここが見落とされやすい点だ。「k3s vs k8s」という比較軸で語られるのは、たいていCNIの選択肢やコントロールプレーンの構成、CI/CDとの相性といった運用面の違いであり、RBACの仕組みそのものには差がない。Role・ClusterRole・RoleBinding・ClusterRoleBindingという4つのオブジェクトはk3sでもバニラのKubernetesでも完全に同一だ。
ではk3sとk8sで何が違うのか。Kubernetesは各Namespaceにdefaultという名前のServiceAccountを自動生成し、Podの仕様で明示的に指定しない限り、このServiceAccountのAPI認証トークンが/var/run/secrets/kubernetes.io/serviceaccount/tokenに自動マウントされる。これはKubernetes公式ドキュメントに明記されている既定動作であり、k3sでも素のKubernetesでも変わらない。
さらに厄介なのが優先順位の罠だ。ServiceAccount側でautomountServiceAccountToken: falseを設定していても、Pod の.specでtrueを指定すると、そちらが優先される。「ServiceAccountで塞いだはずなのに、特定のPodだけ穴が開いていた」という事故は、この優先順位を知らないと再現性高く起こる。
一方でk3sには独自の事情もある。k3sは/etc/rancher/k3s/k3s.yamlに強力な管理者kubeconfigを同梱した状態でブートストラップされる。検証・ホームラボ用途ではこれが便利に働くが、同じ感覚のままマルチテナントの本番運用へ持ち上げると、RBACを意識せず管理者権限で触り始めた経験がそのまま"緩いRoleBinding"として残ってしまう。実際、k3s公式のCIS Hardening Guideでも、NetworkPolicyやPod Security Standardsはデフォルトでは適用されず、各Namespaceへの明示的な設定が必須だと明記されている。「k3sは軽量だから後回しでいい」という思い込みが、ここでも同じ落とし穴につながる。
3. 他人事ではない。CVE-2026-61549が示す"serviceAccountNameの外部指定"の危険

「ServiceAccountの指定を外部入力に任せると何が起きるか」を示す実例が、2026年に公表されたCI/CDツールWoodpeckerのKubernetesバックエンドの脆弱性だ。パイプラインYAMLのbackend_options.kubernetes.serviceAccountNameフィールドが、検証なしにそのままPod仕様へ渡されていた。
その結果、該当リポジトリへのpushアクセス権さえあれば、誰でもパイプラインNamespace内の任意のServiceAccountを指定できてしまった。もし特権的なServiceAccountがそのNamespaceに存在すれば、攻撃者のパイプラインPodがそのトークンを取得し、Secretsの読み取り・クラスタリソースの列挙・cluster-admin権限への昇格まで到達しうる。GitHub Security Advisory(GHSA-qf34-295c-26v8)はCVSSスコア8.2(High)と評価しており、詳細な技術解説によれば影響範囲はv3.16.0未満の全バージョンに及ぶ。修正版ではServiceAccountNameAllowFromStepというゲート機能が追加され、デフォルトでは無効化・明示的な環境変数設定がない限り機能しないようになった。
CI/CDパイプラインに限らず、「ServiceAccount名をどこかの入力値から決める」設計は、defaultのServiceAccountの罠と同じ根を持つ。GitOpsパイプラインをKuboのようにArgoCD/Fluxとの標準統合で運用する場合も、ServiceAccountの割り当てルールをテンプレート側で固定し、パイプライン定義から自由に指定させない設計にしておく価値がここにある。
4. この手口は実際に増えている(脅威統計が示す現実)

「一部の特殊な構成でしか起きない」と思われがちだが、実際のデータは逆を示している。Palo Alto Networks Unit42の脅威レポートによれば、Kubernetesのトークン窃取を含む脅威アクターの活動は前年比で282%増加し、クラウド環境の22%でServiceAccountトークン窃取を疑う活動が検出されている。Kubernetes関連のアラート件数も、2024年の約12万件から2025年には約47万件へと3.8倍近くに急増したと報告されている。
これらの数値が示すのは、「defaultのServiceAccountを放置する」という構成ミスが、攻撃者にとって珍しくない標的になっているという現実だ。マルチテナント環境ではなおさら、1つのNamespaceの甘さが他のテナントにまで波及しうる。
5. マルチテナント環境を守る4層の対策

RBAC単体での対策は不十分だ。マルチテナント環境を現実的に守るには、少なくとも次の4層を組み合わせる必要がある。
- automountServiceAccountTokenの明示的な無効化: ServiceAccountとPod両方で設定し、Pod側が優先される仕様を踏まえて漏れがないか確認する
- NetworkPolicyのデフォルト全拒否: 「まず全通信を遮断し、必要な経路だけ明示的に許可する」というアプローチがテナント間通信の遮断に有効
- ResourceQuota / LimitRangeによるリソース分離: テナントごとにCPU・メモリの合計requestと上限limitを明示し、一方のテナントが他方の性能を圧迫しないようにする
- ポリシーエンジンによる自動強制: Kyvernoのようなポリシーエンジンを使えば、新規Namespace作成時に生成される
defaultServiceAccountへautomountServiceAccountToken: falseを自動パッチでき、設定漏れを構造的に防げる
これらの組み合わせは、マルチテナント分離のベストプラクティスを解説する記事でも、RBAC・NetworkPolicy・ResourceQuotaの3点セットが「実用的な分離」の最低条件として挙げられている。Kyvernoの自動ミューテートポリシーのようにクラスタ全体へ一貫して適用できる仕組みを使えば、Pod単位の設定漏れというヒューマンエラーをなくせる。
Kubo Cloudのようなマネージド環境では、Captain UIという可視化された管理画面でクラスタの状態をブラックボックスにせず把握できるため、こうした「設定したつもり」のギャップに気づきやすくなる。金融・医療のようにデータ主権要件が厳しい業種では、Kubo On-Premiseのように自社管理のまま同等のマルチテナント設計を適用できる選択肢も有効だ。
まとめ
k3sとKubernetesを比較するとき、議論はCNIやコントロールプレーンの構成に偏りがちだが、RBACとServiceAccountの既定動作に関しては両者に差がない。defaultのServiceAccountをそのまま使い続けることが、検証環境から本番のマルチテナント運用へ移行した瞬間にリスクへ変わる。CVE-2026-61549のような実例や、前年比282%という脅威統計が示すように、これは理論上の懸念ではなく現実に増えている攻撃面だ。
automountの無効化・NetworkPolicy・ResourceQuota・ポリシーエンジンによる自動強制という4層を、Podを作るたびに人力で確認するのではなく、基盤側にテンプレート化しておくこと。KuboはK3sベースの本格的なKubernetesでありながら、そうしたマルチテナント設計を最初から組み込める環境として、この種の"気づかれない穴"を減らす選択肢になる。まずは自分のクラスタのdefaultServiceAccountが今どうなっているか、確認するところから始めてみてほしい。お問い合わせから相談することもできる。