TL

Admission Controlとポリシー実行(Webhook/CEL)

危険な設定をクラスタに入る前に止めたい。API サーバーの admission webhook と CEL・OPA/Gatekeeper・Kyverno が、どの順序でリクエストを検証・改変するかを原理から解説。

応用KubernetesAdmission ControlポリシーCELセキュリティ最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.admission は認証・認可の後、etcd 保存の直前に走る。mutating(改変)が先、validating(検証)が後で、その間にスキーマ検証が挟まり、validating の後はオブジェクトを変えられない。
  • 2.外部 webhook は API サーバーが HTTP で呼ぶ同期処理。failurePolicy・timeout・matchConditions の設計を誤ると、全 API 操作が詰まる。
  • 3.ポリシー実行は CEL(API サーバー内蔵)、OPA/Gatekeeper(Rego)、Kyverno(YAML)の3系統。webhook 不要の CEL が最も軽く、複雑な判定ほど外部エンジンが要る。

admission control とは何か

Kubernetes の API サーバーは、クライアントから来たリクエスト(Pod を作る、Deployment を更新する等)を、そのまま etcd に書き込むわけではありません。書き込みの 直前 に、リクエストを横取りして検査・改変する関門があります。これが admission control(受け入れ制御) です。

ここで重要なのは「いつ」走るかです。API サーバーの処理は固定された順序を持ちます。

  1. 認証(Authentication):誰からのリクエストか確認する。
  2. 認可(Authorization):その人にこの操作の権限があるか判定する(RBAC など)。
  3. mutating admission:リクエストの 内容 を改変する(後述)。
  4. スキーマ検証:改変後のオブジェクトが OpenAPI スキーマに沿うか検証する。
  5. validating admission:内容を検査して可否を返す(後述)。これを通れば etcd に保存される。

認可は「操作してよいか(誰が何をできるか)」を見るのに対し、admission は「その内容が妥当か(この Pod は特権コンテナを使っていないか、ラベルが付いているか)」を見ます。RBAC では表現できない、オブジェクトの中身に踏み込んだルール強制がここで可能になります。

admission は read を見ない

admission control が走るのは、状態を変える書き込み系の操作(create / update / delete / connect)だけです。get / list / watch といった読み取りリクエストは admission を通りません。ポリシーで「閲覧を禁止」したい場合は admission ではなく認可(RBAC)の領域になります。

mutating と validating:2段構えとその順序

admission には2種類のフェーズがあり、順序が決まっている ことが設計の根幹です。

  • mutating(変更)admission:先に走る。リクエスト中のオブジェクトを 書き換えられる(デフォルト値の注入、サイドカーの追加、ラベルの付与など)。
  • validating(検証)admission:後に走る。オブジェクトを 見て可否だけを返す。受理(allow)か拒否(deny)かで、内容は変えない。

なぜ mutating が先なのか。validating は「最終的に保存される姿」を検査する必要があるからです。もし validating の後に mutating が改変したら、検証を通り抜けたオブジェクトが検証後に書き換わり、検証が無意味になります。だから順序は 必ず mutating → validating で固定され、validating フェーズを通過したオブジェクトはもう改変されません。

API サーバー内部では、この2フェーズの間に 再エンコード/再検証 が挟まります。全 mutating プラグインが適用された結果のオブジェクトが、validating に渡される確定形になります。

mutating webhook の順序は保証されない

複数の mutating webhook がある場合、それらの 実行順序は保証されません。webhook A がラベルを足し、webhook B がそのラベルを前提に動く、という依存を組むと壊れます。さらに、ある webhook の出力が別の webhook の入力になるため、相互作用でオブジェクトが意図せぬ形になることがあります。API サーバーは安定化のため mutating を最大で複数回(reinvocation)呼ぶ設定も持ちますが、冪等(何度適用しても同じ結果)に作るのが鉄則です。

webhook の仕組み:API サーバーが外部を呼ぶ

組み込みの admission プラグイン(NamespaceLifecycle など)はコンパイル済みでカーネルに固定ですが、ユーザーが独自ルールを足す主流の手段が admission webhook です。ValidatingWebhookConfiguration / MutatingWebhookConfiguration というリソースで登録します。

動作はシンプルで、しかし危険です。マッチするリクエストが来ると、API サーバーが webhook サーバーに対して同期的に HTTPS POST を送ります。ボディは AdmissionReview オブジェクト(対象リソース・操作種別・ユーザー情報を含む)。webhook は許可/拒否(mutating なら JSON Patch 付き)を AdmissionReview で返します。

この「API サーバーが外部 HTTP を待つ」という構造が、設計上の最大の注意点を生みます。

設定項目意味誤ると起きること
failurePolicywebhook 応答失敗時に Fail(拒否)か Ignore(許可)かFail にして webhook が落ちると、対象 API 操作が全滅する
timeoutSeconds応答を待つ上限(最大30秒)長すぎると API のレイテンシ悪化、短すぎると誤拒否
rulesどの resource/operation を捕まえるか広すぎると無関係なリクエストまで webhook を呼ぶ
matchConditionsCEL で対象をさらに絞る前段フィルタ未設定だと webhook サーバー側に負荷が集中する
sideEffectswebhook が外部状態を変えるか宣言誤申告すると dry-run が正しく動かない
webhook はクラスタを止めうる

failurePolicy: Fail の webhook が、自分自身の動作に必要なリソース(例:kube-system の Pod)まで捕まえる設定だと、webhook サーバーがダウンしたとき復旧用の Pod すら作れず、クラスタが自己ロックします。回避策は (1) 自分の namespace を namespaceSelector で除外、(2) objectSelector で対象を限定、(3) 重要 namespace を matchConditions で素通しさせる、など。webhook を入れる=API サーバーの可用性に依存先を増やす、と意識してください。

CEL:webhook なしでポリシーを書く

webhook は柔軟ですが、外部サーバーの運用・証明書・可用性という重荷を伴います。これを避けるために、API サーバーに CEL(Common Expression Language) が組み込まれました。ValidatingAdmissionPolicy(および mutating 版)として、外部プロセスなしに API サーバー内でポリシーを評価します。

CEL は安全な式言語で、ループや任意 I/O を持たず、評価コストに上限がある(チューリング完全ではない)よう設計されています。これにより API サーバー内で安全に同期評価でき、webhook のような外部呼び出し・ネットワーク往復・障害点がありません。

# webhook 不要。API サーバー内で CEL を評価
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: replica-limit
spec:
  matchConstraints:
    resourceRules:
      - apiGroups:   ["apps"]
        apiVersions: ["v1"]
        operations:  ["CREATE", "UPDATE"]
        resources:   ["deployments"]
  validations:
    - expression: "object.spec.replicas <= 5"   # replicas が 5 以下のみ許可
      message: "replicas は 5 以下にしてください"

CEL は軽量で障害点が増えない一方、表現力に限界があります。外部データ参照(「この Image は脆弱性スキャンを通ったか」を別 DB に問い合わせる等)や複雑なロジックは苦手で、そこは依然 webhook +外部エンジンの出番です。判断軸は「API サーバー内で完結する単純な不変条件は CEL、外部知識や複雑な合成判断は webhook」です。

OPA/Gatekeeper・Kyverno:ポリシーエンジンの3系統

実務では、生の webhook を自作するより ポリシーエンジン を webhook の背後に置くのが一般的です。代表が OPA/Gatekeeper と Kyverno で、CEL を加えた3系統を比べると性格がはっきりします。

観点CEL(内蔵)OPA / GatekeeperKyverno
配置API サーバー内蔵(webhook 不要)validating webhook の背後に常駐validating/mutating webhook の背後に常駐
記述言語CEL 式Rego(専用宣言型言語)Kubernetes YAML(CRD)
得意領域単純な不変条件の検証複雑な論理・横断的ルールK8s 特化、mutate/generate も得意
学習コスト低(式のみ)高(Rego の習得が必要)中(YAML で書ける)
外部障害点なしwebhook サーバーがあるwebhook サーバーがある
  • OPA/Gatekeeper:汎用ポリシーエンジン OPA を Kubernetes 用に包んだもの。ルールは Rego で書き、ConstraintTemplate(ルールの型)と Constraint(適用パラメータ)に分離する設計です。Kubernetes 以外でも使える汎用性が強みですが、Rego の学習コストが高めです。
  • Kyverno:Kubernetes 専用に作られ、ポリシーを YAML(CRD) で書きます。新言語を学ばずに済み、検証(validate)だけでなく 改変(mutate)生成(generate:namespace 作成時に既定の NetworkPolicy を自動生成等) も同じ枠組みで書けるのが特徴です。

3つとも本質は同じ「admission のタイミングでオブジェクトを検査・改変する」仕組みで、違いは どこで評価するか(内蔵か外部か)と 何で書くか(CEL/Rego/YAML)です。

試験・面接での頻出ポイント

「mutating と validating はどちらが先か」「admission は認可の前か後か」は頻出です。覚え方は 認証 → 認可 → mutating → validating → 保存 の一本道。admission は書き込み系のみに作用し、読み取りには効きません。CEL を webhook と対比して「外部障害点を持たない内蔵評価」と説明できると上級者向けの加点になります。

配置上の設計指針

admission を入れる際は、可用性とのトレードオフを常に意識します。

  1. まず CEL を検討:API サーバー内で完結する単純なルール(ラベル必須、replicas 上限、特権コンテナ禁止)は CEL で書き、外部依存を増やさない。
  2. webhook は対象を絞るmatchConditions(CEL 前段フィルタ)・namespaceSelectorobjectSelector で、本当に必要なリクエストだけを捕まえる。捕まえる範囲が広いほど API 全体のレイテンシと障害リスクが増えます。
  3. failurePolicy を意図的に選ぶ:セキュリティ強制系(特権 Pod 拒否など)は Fail(webhook が落ちたら拒否=安全側)、補助的なラベル付与などは Ignore(落ちても素通し)と、ルールの性質で使い分けます。
  4. 冪等に作る:mutating は順序保証がなく再呼び出しもあるため、何度適用しても同じ結果になるよう設計します。

admission はサービスメッシュのサイドカー自動注入(/devops/service-mesh/)の正体でもあり、デプロイ戦略(/devops/deployment-strategies/)の安全ガードや、CI/CD(/devops/ci-cd/)でクラスタ手前で弾けない実行時ポリシーの最後の砦としても機能します。「クラスタに入る前」に強制できるからこそ、構成のドリフトを設計段階で封じられるのが admission control の価値です。

まとめ

  • admission は 認証・認可の後、etcd 保存の直前 に走り、書き込み系操作の 内容 を検査・改変する関門。
  • フェーズは mutating(改変が先)→ validating(検証が後) で固定。validating 通過後はオブジェクトを変えられない。
  • webhook は API サーバーが同期 HTTP で外部を呼ぶ ため、failurePolicy・timeout・対象範囲の設計を誤るとクラスタごと詰まる。
  • ポリシー実行は CEL(内蔵・軽量)/OPA・Gatekeeper(Rego)/Kyverno(YAML) の3系統。単純な不変条件は CEL、複雑・外部依存の判断は webhook +エンジンで使い分ける。

DevOps/インフラ Article

Admission Controlとポリシー実行(Webhook/CEL)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

Kubernetes

比較で見る軸

難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 5

導入後に効く点

外部 webhook は API サーバーが HTTP で呼ぶ同期処理。failurePolicy・timeout・matchConditions の設計を誤ると、全 API 操作が詰まる。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
DevOps/インフラ
タグ数
5

判断チェックリスト

  • 自社の用途が「Kubernetes / Admission Control」に近いか確認する。
  • 強みである「admission は認証・認可の後、etcd 保存の直前に走る。mutating(改変)が先、validating(検証)が後で、その間にスキーマ検証が挟まり、validating の後はオブジェクトを変えられない。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

KubernetesAdmission ControlポリシーCELセキュリティKubernetesAdmission Controlポリシー