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

ポリシーをコードで

既定値を埋めてくれる変形ポリシーを書く

TT Labで続きを見る

目標

抜けている値を埋めてくれるミューテーションポリシーを3つの方式で書き、すでに指定された値には触れないことを、自分で確認します。最後に、何がどう変わったかの照合レポートを作ります。

なぜ重要なのか

ブロックするだけのポリシーは、問題をユーザーに押し付けます。リミットのないPodをすべて拒否すると、ルールは守られますが、チームごとに「いくつ入れればよいですか」という質問が生まれます。ミューテーションポリシーは、組織のデフォルト値を代わりに埋めることで、ルールを守りながら、誰もブロックしません。ただし、ここには越えてはいけない線があります。ユーザーが明示した値は絶対に上書きしないことです。チームがcpu: 500mと書いたのに、ポリシーが黙って変えてしまうと、そのチームは自分のマニフェストを信じられなくなり、その時からポリシーは、信頼ではなく恐怖の対象になります。そのため、追加アンカー+()は構文の飾りではなく、契約です。なお、この環境にはアドミッションWebhookが動いていないため、ミューテーションはkyverno CLIでローカルに評価して、結果のマニフェストを確認します。

ステップ

  1. /root/policy/mutate/add-team-label.yamlにkind: ClusterPolicyを作成してください。spec.backgroundを明示し、spec.rules[0].mutate.patchStrategicMerge.metadata.labelsの下に+(team): unassignedを入れてください。ルール名はadd-default-team、マッチはpol-labネームスペースのPodです。
  2. /root/policy/mutate/add-defaults.yamlに2つ目のポリシーを作成し、+(...)の追加アンカーで、コンテナのresources.limitsに、cpuとmemoryのデフォルト値を埋めるルールを書いてください。そして、/root/policy/mutate/out/anchors.md(150バイト以上)に、条件アンカー()、追加アンカー+()、そして=()またはX()の違いを整理してください。
  3. 同じadd-defaults.yamlに、mutate.patchesJson6902を使うルールをもう1つ入れてください。op: addとpath: /spec/containers/0/imagePullPolicy、value: IfNotPresentの形です。そして、/root/policy/mutate/out/json6902-note.txtに、この方式が配列・インデックスを扱うときになぜ必要なのかを書いてください。
  4. add-defaults.yamlに、mutate.foreachルールを入れてください。list: "request.object.spec.containers"でコンテナのリストを受け取り、内部でelement変数で現在の項目を指す必要があります。
  5. 2つのポリシーを/opt/lab/fixtures/policy/resources/bad-pod.yamlに適用して、ミューテーションされたPodマニフェストを/root/policy/mutate/out/mutated.yamlに保存してください。そのファイルには、metadata.labels.team、spec.containers[0].resources.limits.memory、spec.containers[0].imagePullPolicyの3つの値が、すべて埋まっている必要があります。
  6. 同じ2つのポリシーを/opt/lab/fixtures/policy/resources/good-pod.yamlに適用して、/root/policy/mutate/out/preserved.yamlに保存してください。このPodには、もともとteam: platformラベルとcpu: 500mの制限があり、ミューテーションの後もそのままである必要があります。
  7. /root/policy/mutate/mutate-existing.yamlを作成してください。spec.mutateExistingOnPolicyUpdate: trueを置き、ルールのmutate.targetsにkind: Pod、namespace: pol-labを書いて、トリガーではないリソースを修正するようにしてください。そして、/root/policy/mutate/out/existing-note.txtに、この動作がバックグラウンドで動くため、追加のRBAC権限が必要であることを書いてください。
  8. /root/policy/mutate/out/mutate-report.jsonを作成してください。最上位のmutations配列に3件以上を入れ、各項目は、field・before・after・ruleの4つのキーを持つ必要があります。beforeとafterが同じ項目は入れないでください。fieldにteamが含まれる項目のafterの値は、ステップ5で作ったmutated.yamlのmetadata.labels.teamの値と、正確に同じである必要があります。

参考

ラベルを追加するミューテーションポリシーを作る

/root/policy/mutate/add-team-label.yamlにkind: ClusterPolicyを作成してください。spec.backgroundを明示し、spec.rules[0].mutate.patchStrategicMerge.metadata.labelsの下に+(team): unassignedを入れてください。ルール名はadd-default-team、マッチはpol-labネームスペースのPodです。

ミューテーションは、mutateの下に書きます。マップにフィールドを追加するには、オブジェクトと同じ形で書く方式が、最も読みやすいです。すでに値があるPodもすぐに扱うことになるので、上書きしない表記を最初から使ってください。

追加アンカーでリソースのデフォルト値を埋める

/root/policy/mutate/add-defaults.yamlに2つ目のポリシーを作成し、+(...)の追加アンカーで、コンテナのresources.limitsに、cpuとmemoryのデフォルト値を埋めるルールを書いてください。そして、/root/policy/mutate/out/anchors.md(150バイト以上)に、条件アンカー()、追加アンカー+()、そして=()またはX()の違いを整理してください。

「なければ入れ、あれば置いておく」という意味のアンカーが、別にあります。3種類のアンカーの違いをドキュメントに整理して、はじめて通過します。

JSONパッチで配列の項目を修正する

同じadd-defaults.yamlに、mutate.patchesJson6902を使うルールをもう1つ入れてください。op: addとpath: /spec/containers/0/imagePullPolicy、value: IfNotPresentの形です。そして、/root/policy/mutate/out/json6902-note.txtに、この方式が配列・インデックスを扱うときになぜ必要なのかを書いてください。

Strategic Mergeでは、「何番目のコンテナ」をピンポイントで指すのが難しいです。op・path・valueの3つで位置を指定する方式があります。

コンテナのリストを回るルールを書く

add-defaults.yamlに、mutate.foreachルールを入れてください。list: "request.object.spec.containers"でコンテナのリストを受け取り、内部でelement変数で現在の項目を指す必要があります。

コンテナの数がわからないときは、インデックスを使えません。リストを受け取るキーと、現在の項目を指す変数の名前を、確認してください。

ポリシーを実行して、ミューテーション結果を保存する

2つのポリシーを/opt/lab/fixtures/policy/resources/bad-pod.yamlに適用して、ミューテーションされたPodマニフェストを/root/policy/mutate/out/mutated.yamlに保存してください。そのファイルには、metadata.labels.team、spec.containers[0].resources.limits.memory、spec.containers[0].imagePullPolicyの3つの値が、すべて埋まっている必要があります。

2つのポリシーファイルを、一度に渡せます。保存するのは、実行の要約ではなく、ミューテーションされたPodのマニフェストです。

すでにある値が保存されるか確認する

同じ2つのポリシーを/opt/lab/fixtures/policy/resources/good-pod.yamlに適用して、/root/policy/mutate/out/preserved.yamlに保存してください。このPodには、もともとteam: platformラベルとcpu: 500mの制限があり、ミューテーションの後もそのままである必要があります。

同じポリシーを、値が埋まっているPodに対して実行します。元の値が変わっていたなら、アンカーを使わなかったか、間違って使ったということです。

すでに存在するリソースを修正するポリシーを書く

/root/policy/mutate/mutate-existing.yamlを作成してください。spec.mutateExistingOnPolicyUpdate: trueを置き、ルールのmutate.targetsにkind: Pod、namespace: pol-labを書いて、トリガーではないリソースを修正するようにしてください。そして、/root/policy/mutate/out/existing-note.txtに、この動作がバックグラウンドで動くため、追加のRBAC権限が必要であることを書いてください。

トリガーではなく別のリソースを修正するには、対象を別に書く必要があります。ポリシーを修正したときに、既存のリソースも手直しするかどうかを決めるスイッチもあります。

ミューテーション前後の照合レポートを作る

/root/policy/mutate/out/mutate-report.jsonを作成してください。最上位のmutations配列に3件以上を入れ、各項目は、field・before・after・ruleの4つのキーを持つ必要があります。beforeとafterが同じ項目は入れないでください。fieldにteamが含まれる項目のafterの値は、ステップ5で作ったmutated.yamlのmetadata.labels.teamの値と、正確に同じである必要があります。

フィールドごとに、前後の値と、どのルールが行ったかを入れます。値が変わっていない項目はミューテーションではないので、入れてはいけません。