ポリシーを書いたことと、ポリシーが守られることは違う
一言でいうと
Kyvernoは、止めることが存在理由ですが、止める部分がない環境では、ポリシーを書いたという事実のほかには何も確認できません。
なぜ本物のアドミッションでなければならないのか
初期のポリシー作成ラボのCRDだけがロードされた環境では、保存の成功と、実際のポリシー実行を区別する必要があります。このモジュールとWebhook障害のラボでは、コントローラーが実行されている本物のVMで、正常なリクエストと違反するリクエストを比べます。
Kyvernoはアドミッションコントローラーです。止めることが存在理由なのに、止める部分がない環境で学んだことになってしまいます。
3つの動作はタイミングが違います
| 動作 | いつ | 何を |
|---|---|---|
mutate |
アドミッション、validateより先 | リクエストを書き換えます |
validate |
アドミッション | 拒否するか、通過させます |
generate |
アドミッションのあと、別のコントローラーが | 別のオブジェクトを作ります |
この順序を知っていれば、ポリシーを組み合わせられます。「なければ入れる」(mutate)と「必ずなければならない」(validate)を一緒に置くと、ユーザーは何もしなくても通過します。
そして、generateがアドミッションの外にあることは、2つのことを生みます。別の権限が必要で、すぐには作られません。権限がなければ、ポリシーは問題ないのに何も作られず、エラーはKyvernoのログの中にしかありません。
最も危険なのは静かな失敗
KyvernoのPodがRunningでも、Webhook設定がなければ何も起きません。 ポリシーはそのまま存在し、エラーもありません。ポリシーを書き終えたのに1つも適用されていない状態が、正常のように見えます。
そのため、ポリシーを書いたあとは、必ず止まるかどうかを直接テストする必要があります。
ポリシー1つがクラスターをロックしてしまうことがあります
ポリシーの適用対象に入ったシステムPodが要求条件に違反すると、再作成が拒否されることがあります。だからといって、すべてのポリシーがシステムを止めるわけでも、既存のPodがすぐに終了するわけでも、ポリシーの削除まで常に止められるわけでもありません。実際のリクエストの種類・対象の範囲・復旧の経路を確認する必要があります。
ポリシーをデプロイする順序
新しいポリシーは、違反の状況を収集し、チームが修正する時間を確保してから強制します。
1. Audit + 보고서 적용 대상의 위반을 수집한다
2. 수정·예외·복구 시험 정상 요청과 위반 요청을 모두 시험한다
3. Enforce + 관찰 위반 요청을 거부하고 영향을 관찰한다
このラボのKyverno ClusterPolicyはAudit → Enforceです。Warnは、このフィールドの3番目の値ではありません。Auditの違反をレスポンスの警告として知らせるには、spec.emitWarningを一緒に設定します。ほかのポリシーエンジンのモード名を、このAPIにそのまま入れないでください。
違反の一覧から、修正する項目と承認された例外を区別し、適用範囲ごとに切り替えます。既存のPodが動き続けているというだけで、次のデプロイも通ると判断してはいけません。
# Kyverno — 지금 걸리는 것들
kubectl get policyreport -A -o json | jq -r '
.items[].results[] | select(.result=="fail") |
"\(.policy): \(.resources[0].namespace)/\(.resources[0].name)"' | sort | uniq -c
自分自身をロックしないために
ポリシーがシステムコンポーネントの復旧リクエストを拒否すると、障害を大きくすることがあります。次は、ラベルのルールに置ける例外の部分的な例です。すべてのシステムセキュリティポリシーに無条件で適用するリストでも、Webhook呼び出しを除外する設定でもありません。
spec:
rules:
- name: require-nonroot
match:
any:
- resources: {kinds: [Pod]}
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, gatekeeper-system]
登録されたWebhookの呼び出しが失敗したとき、failurePolicy: Failはそのリクエストを拒否し、IgnoreはそのWebhookをスキップして残りの処理を続けます。正常な応答として明示されたポリシー違反の拒否は、Ignoreでも有効です。ポリシーオブジェクトが削除されるわけでも、ほかのポリシーの検査まで無視されるわけでもありません。
ポリシールールのexcludeは、エンジンの内部で適用されます。APIサーバーの実際の呼び出し範囲は、WebhookConfigurationのrules・namespaceSelector・objectSelectorなどで確認します。エンジンの障害時に自己復旧のリクエストを除外するには、この呼び出し段階まで見る必要があります。検証を省略するリスクと可用性を比べ、承認された復旧経路をテストしてください。
Webhookの登録がない状態と、登録はあるが応答しない状態も違います。続く障害ラボでは、2つの状態を別々に作り、リクエストの結果と実際の登録を比べます。
書き換え(mutate)が検証より先です
アドミッションの順序は決まっています。
변형 웹훅 → 스키마 검증 → 검증 웹훅 → etcd 저장
そのため、「デフォルト値を埋めるポリシー」と「そのフィールドを要求するポリシー」を一緒に置くと、自動的に通過します。ユーザーが書かなくても、書き換えが埋めて、検証が確認します。
ただし、書き換えはユーザーに知らせずに変更するという点を忘れてはいけません。kubectl get -o yamlで保存された結果が、自分が書いたものと違うと混乱します。書き換えのポリシーは、何を変えるのかをドキュメントに書き、できればアノテーションで痕跡を残します。
実務で本当に大切なこと
ポリシーをデプロイしたあとは、正常なオブジェクトと違反するオブジェクトの両方をテストします。 コントローラーがRunningだというだけでは、Webhookの登録とリクエスト処理は保証されません。作成コマンドの終了コードだけでなく、拒否メッセージと保存されたかどうかも確認します。
ポリシーの範囲を広げるときは、システムの復旧をテストします。 ルールの例外とWebhook呼び出しの除外を区別し、実際のシステムワークロードが要求条件を満たしているかを確認します。運用中のクラスター全体に障害実験を適用してはいけません。
generateが動作しないときは、対象の一致とバックグラウンドコントローラーの権限を一緒に見ます。 ログのForbiddenは権限調査の根拠になりますが、出力がないという事実だけで原因を確定することはできません。
次のラボで、これらを本物のKyverno上で直接確認します。
公式ドキュメントで確認する
- Kubernetes: Webhookの呼び出し範囲とfailurePolicy
- Kyverno: Audit・Enforce・emitWarningとポリシー設定
- Kyverno: ClusterPolicyのサポート範囲と廃止予定の案内
このラボで固定されているバージョンは、Kyverno 1.19.1です。最新のドキュメントのAPIを既存のVMにそのまま適用せず、インストールされているバージョンのCRDと一緒に確認してください。