TT Lab
はじめる
学ぶ 学習パス コース

ポリシーをコードで

AuditからEnforceまで — ポリシーを実際に点ける順序

TT Labで続きを見る

一言でいうと

ポリシーは、書くことよりもオンにすることのほうが難しく、オンにする順序は、常に観測 → 例外の整理 → 強制の3つの段階です。

なぜ必要なのか

ポリシーを1つうまく書いて、すぐにEnforceに上げたチームに起きることは、たいてい同じです。デプロイが次々とブロックされ、Slackに問い合わせが溜まり、数時間後に誰かが「とりあえずポリシーを下げてください」と言い出します。ポリシーは下げられ、二度と上がりません。失敗の原因は、ポリシーの質ではありません。すでに動いているものたちが、そのルールを守っているかどうか、誰も知らなかったことです。

クラスターには、新しくデプロイされるワークロードだけがあるわけではありません。2年前に上がったバッチジョブ、ベンダーがくれたHelmチャート、どこかのチームが一時的に起動して忘れたPodが、一緒に暮らしています。新しいルールがこれらのうちいくつに引っかかるかは、ルールをかけてみる前にはわかりません。そのため、ポリシーエンジンには、ブロックせずに数えてみるモードが必ずあります。

どう動くのか

核心は、2つの仕組みです。

1つ目は、AuditとEnforceです。

モード 違反リクエスト 残るもの
Audit 通過させる レポートにfailとして記録される
Enforce 拒否する レポートにも残り、ユーザーもすぐに気づく

Auditは、「ポリシーがオンになっていない状態」ではなく、「強制だけをオフにした状態」です。判定はそのまま行われ、結果が溜まります。そのため、Auditで数日置いておけば、「このルールをオンにすると、いくつがブロックされるのか」という質問に、数字で答えられます。強制レベルがルール単位(validate.failureAction)に下りてきてからは、1つのポリシーの中で、検証済みのルールだけをEnforceに上げ、新しいルールはAuditで載せることができます。

2つ目は、バックグラウンドスキャンとPolicyReportです。

アドミッションの段階は、これから入ってくるものだけを見ます。すでにクラスターの中にあるオブジェクトは、誰も再び検査しません。そのため、spec.background: trueのポリシーは、バックグラウンドコントローラーが定期的に既存のリソースを走査して、同じルールで判定します。その結果が、レポートとして溜まります。

レポートには、results配列にリソースごとの判定(policy, rule, result, message)が入り、summaryにpass・fail・warn・error・skipの集計が入ります。このsummary.failが、導入作業の進捗の指標です。ポリシーをオンにした日に47だったものが、2週間後に3になったなら、その3が、残った例外の候補です。

3つ目は、PolicyExceptionです。

残ったものの中には、本当に直せないものがあります。ベンダーのイメージなのでリミットを入れられない、ノードのエージェントなので特権が必要、といったものです。このとき、ポリシーを元に戻す代わりに、例外をドキュメントとして残します。例外には、3重の範囲があります。

  1. spec.exceptions[].policyName: どのポリシーに対する例外か
  2. spec.exceptions[].ruleNames: そのポリシーのどのルールだけが免除か
  3. spec.match: どのリソースにだけ適用されるか(kinds、namespaces、そしてnames)

3重すべてを絞ることが重要です。ruleNamesを省略してポリシー全体を免除すると、そのリソースは、今後そのポリシーに追加されるすべてのルールからも外れます。namesなしでネームスペースだけを書くと、その中で新しく作られるワークロードまで、永久にルールの外に置かれます。例外は、ポリシーをオフにするスイッチではなく、負債の一覧でなければなりません。一覧が長くなれば目に見え、目に見えれば減らせます。例外ごとに、有効期限や担当チームをアノテーションとして付けておけば、一覧がひとりでに管理されます。

この3つの仕組みを順番に使うと、導入の手順が出てきます。

1) 정책을 Audit 으로 배포 + background: true
2) 며칠~몇 주 리포트의 summary.fail 을 관찰
3) 고칠 수 있는 것은 팀과 함께 고친다 (fail 이 줄어드는 것을 본다)
4) 못 고치는 것만 좁은 PolicyException 으로 남긴다
5) fail 이 예외 건수까지 내려오면 그 규칙을 Enforce 로 올린다
6) 예외 목록을 주기적으로 다시 본다

このコードブロックの韓国語は、6つの手順を順に、ポリシーをAuditとしてデプロイしてbackground: trueにする、数日から数週間、レポートのsummary.failを観察する、直せるものはチームと一緒に直す(failが減るのを見る)、直せないものだけを狭いPolicyExceptionとして残す、failが例外の件数まで下がったらそのルールをEnforceに上げる、例外の一覧を定期的に見直す、と述べています。

現場での姿

1つ目は、Auditをオンにしたまま誰も見ない場合です。レポートは溜まりますが、ダッシュボードもアラートもなければ、ただCRDのオブジェクトが増えるだけです。Auditは観測であって、観測の結果を読んでくれる人ではありません。ポリシーをAuditでデプロイする瞬間に、「誰がいつこの数字を見るのか」も、一緒に決めなければなりません。

2つ目は、レポートが溜まってクラスターを圧迫する場合です。リソースが多いクラスターで、すべてにマッチするポリシーをbackgroundでオンにすると、レポートのオブジェクトが大量に作られます。レポートコントローラーが、集計の速度に追いつけなくなると、ラグが始まります。マッチ範囲を絞ることが、ここでも答えです。

3つ目は、例外が黙って永続化する場合です。「次のスプリントで直します」で作った例外が、2年目も残っているクラスターは、よくあります。例外に有効期限と担当者を書いておき、四半期ごとに一覧を見渡す手順を作る必要があります。例外を作ることよりも、例外を消す手順を作るほうが、難しく、重要です。

4つ目は、この環境の正直な限界です。ここでは、バックグラウンドコントローラーが動かないため、クラスターにPolicyReportが自然に溜まることはありません。その代わり、kyverno apply --policy-reportで、同じ形式のレポートをローカルで作れ、そのsummaryのpass/failの数値が、実際のレポートのものと同じ意味を持ちます。pol-validateのラボで作ったレポートが、まさにそれでした。

次の確認で見ること

続くラボで、この文章の最後の2つの段落を、手で作ります。担当者と有効期限と根拠を書いた例外台帳を作り、期限切れの例外を見つけてブロックする検査ツールを書き、例外が実際にポリシーの適用範囲を絞っているか確認したうえで、違反を1か所に集めて、「今Enforceに上げてもよいか」を数字で答えるレポートを作ります。例外を作ることよりも、例外を消す手順を作ることのほうが難しいと、そこで身をもって知ることになります。ラボの後のクイズでは、/root/policy/validate/exception.yamlのpolicyName・ruleNames・リソースのnamesの3重が、例外の範囲をどう絞るのか、有効期限・担当者とともに、負債の一覧として管理する理由を確認します。