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

KCA — Kyverno認定アソシエイト

注入・生成の規則と権限を立てる

TT Labで続きを見る

目標

mutateの2つの方式とgenerateの2つの方式をマニフェストとして書き、generateが実際に動作するために必要なRBACをクラスターに直接立てて、権限まで検証します。

なぜ重要なのか

generateルールは、Kyvernoで最も静かに失敗する機能です。admissionは成功するのでkubectlは何のエラーも出さず、リソースだけができません。原因はたいてい2つで、matchされていないか、backgroundコントローラーに権限がないかです。このラボで権限を自分で作り、auth can-iで確認してみると、あとで現場で生成物が見えないときに、ポリシーのYAMLを探し回る代わりに、UpdateRequestと権限を先に見るようになります。サイドカー注入にリソースリミットを一緒に入れる習慣も、同じ種類の予防措置です。

ステップ

  1. /root/kca-mutate/ディレクトリを作成し、mutate-labels.yamlにkindとしてClusterPolicy、metadata.nameとしてkca-add-team-labelを書いてください。ルールadd-managed-byを作り、matchのkindsにDeploymentを入れ、mutate.patchStrategicMergeでmetadata.labelsのkca.io/managed-byにkyvernoを入れるようにしてください。
  2. 同じファイルにルールinject-sidecarを追加してください。match.any[0].resources.selector.matchLabelsのkca.io/injectで対象を選び、mutate.patchStrategicMerge.spec.template.spec.containers[0]にname log-collector、image、そしてresources.limitsのmemoryとcpuをすべて入れてください。
  3. /root/kca-mutate/mutate-json6902.yamlにkindとしてClusterPolicyを書き、spec.rules[0].mutate.patchesJson6902でアノテーションkca.io/ownerを追加するadd操作を書いてください。パスは/metadata/annotations/の下で、キーのスラッシュをエスケープする必要があります。
  4. /root/kca-mutate/generate-netpol.yamlにkindとしてClusterPolicy、metadata.nameとしてkca-generate-default-denyを書いてください。matchのkindsはNamespace、generate.apiVersionはnetworking.k8s.io/v1、kindはNetworkPolicy、nameはdefault-deny、namespaceは新しいネームスペースの名前を受け取る変数、synchronizeはtrueにし、generate.data.spec.policyTypesにはIngressとEgressを入れてください。
  5. /root/kca-mutate/generate-clone.yamlにkindとしてClusterPolicy、metadata.nameとしてkca-clone-baselineを書いてください。generate.kindはConfigMap、nameはkca-baseline、clone.namespaceはkca-shared、clone.nameはkca-baseline-config、synchronizeはtrueにし、dataは書かないでください。
  6. クラスターにネームスペースkca-sharedを作成し、その中にRole kca-clone-readerを実際に作成してください。コアグループのconfigmapsにget、list、watchだけを許可し、deleteは入れないでください。
  7. クラスターにネームスペースkyvernoとその中のServiceAccount kyverno-background-controllerを作成し、kca-sharedにRoleBinding kca-clone-readerを実際に作成して、Role kca-clone-readerをそのServiceAccountに結び付けてください。
  8. kca-sharedにConfigMap kca-baseline-configを実際に作成してください。データはlog-level=infoとretention=7dの2つです。そのあとkubectl auth can-iで、該当のServiceAccountがこのネームスペースのconfigmapsを読み取れて、secretsは読み取れないことを確認してください。

参考

patchStrategicMergeでラベルを注入する

/root/kca-mutate/ディレクトリを作成し、mutate-labels.yamlにkindとしてClusterPolicy、metadata.nameとしてkca-add-team-labelを書いてください。ルールadd-managed-byを作り、matchのkindsにDeploymentを入れ、mutate.patchStrategicMergeでmetadata.labelsのkca.io/managed-byにkyvernoを入れるようにしてください。

mutateブロックの中にオブジェクトの形をそのまま描くと、その部分だけがマージされます。ラベルのキーにドットとスラッシュがある場合は、YAMLで引用符で囲んでください。

サイドカー注入とリソースリミット

同じファイルにルールinject-sidecarを追加してください。match.any[0].resources.selector.matchLabelsのkca.io/injectで対象を選び、mutate.patchStrategicMerge.spec.template.spec.containers[0]にname log-collector、image、そしてresources.limitsのmemoryとcpuをすべて入れてください。

注入するコンテナには、リソースリミットを必ず入れる必要があります。mutateがvalidateより先に動くという事実が、ここでなぜ重要なのかを思い出してください。そして、すべてのワークロードではなく、ラベルで選んだものにだけ注入されるようにしてください。

JSON Patchでアノテーションを追加する

/root/kca-mutate/mutate-json6902.yamlにkindとしてClusterPolicyを書き、spec.rules[0].mutate.patchesJson6902でアノテーションkca.io/ownerを追加するadd操作を書いてください。パスは/metadata/annotations/の下で、キーのスラッシュをエスケープする必要があります。

JSON Pointerは、スラッシュでパスを区切ります。キー名そのものにスラッシュが入る場合は特別なエスケープが必要で、その表記を知らないと、パスがまったく違う場所を指してしまいます。

ネームスペースごとにdefault-denyを生成する

/root/kca-mutate/generate-netpol.yamlにkindとしてClusterPolicy、metadata.nameとしてkca-generate-default-denyを書いてください。matchのkindsはNamespace、generate.apiVersionはnetworking.k8s.io/v1、kindはNetworkPolicy、nameはdefault-deny、namespaceは新しいネームスペースの名前を受け取る変数、synchronizeはtrueにし、generate.data.spec.policyTypesにはIngressとEgressを入れてください。

generateでは、何を(apiVersion/kind)、どんな名前で、どのネームスペースに作るかをすべて書く必要があります。対象のネームスペースは、今作られたそのネームスペースなので、変数で受け取ります。

cloneで複製する

/root/kca-mutate/generate-clone.yamlにkindとしてClusterPolicy、metadata.nameとしてkca-clone-baselineを書いてください。generate.kindはConfigMap、nameはkca-baseline、clone.namespaceはkca-shared、clone.nameはkca-baseline-config、synchronizeはtrueにし、dataは書かないでください。

cloneは、元のネームスペースと名前を指定します。dataと一緒には使えないこと、そして元の変更に追従させるにはどのフィールドが必要かを確認してください。

複製元を読み取るRoleを作成する

クラスターにネームスペースkca-sharedを作成し、その中にRole kca-clone-readerを実際に作成してください。コアグループのconfigmapsにget、list、watchだけを許可し、deleteは入れないでください。

ここからは実際のクラスターです。読み取りだけが必要なので、動詞は3つあれば十分で、コアグループのリソースのapiGroupsは空文字列です。

backgroundコントローラーにバインドする

クラスターにネームスペースkyvernoとその中のServiceAccount kyverno-background-controllerを作成し、kca-sharedにRoleBinding kca-clone-readerを実際に作成して、Role kca-clone-readerをそのServiceAccountに結び付けてください。

対象は、kyvernoネームスペースのServiceAccountです。そのネームスペースとServiceAccountも、このラボ環境にはないので、一緒に作成する必要があります。

元のConfigMapと権限の検証

kca-sharedにConfigMap kca-baseline-configを実際に作成してください。データはlog-level=infoとretention=7dの2つです。そのあとkubectl auth can-iで、該当のServiceAccountがこのネームスペースのconfigmapsを読み取れて、secretsは読み取れないことを確認してください。

複製元が実際にあってはじめて、cloneが成立します。そして、kubectl auth can-iに--asでServiceAccountになりすますと、権限が正しく付いているかを手で確認できます。