👮

Kyvernoで作成したポリシーを"実環境のリソースでリハーサル(dry-run)"する

2023/02/15に公開

目的

Kyverno で作成したポリシーが、既にデプロイされているリソースにどう影響するかを事前にリハーサル(dry-run)する方法を紹介します。

Kyverno とは何か

Kyverno は Kubernetes のポリシーエンジンで Cloud Native Computiong Foundation の Incubating プロジェクトです。

Kyverno の特徴や、使い方については分かり易い記事がたくさんあるのでそちらにお任せして、本記事ではポリシーの dry-run についての How To を書こうと思います。
※ 以下のスライドで、使い方網羅的に分かりやすくまとめられております。
https://speakerdeck.com/ry/cndt2022-kyverno

Kyverno の dry-run

Kyverno で提供されている Kyverno CLI を用いることで、ポリシー適用前にリソースへの動作検証を行うことができます。
dry-run の対象は、実環境にデプロイされているリソース、静的なマニフェストファイルいずれも可能です。
https://kyverno.io/docs/kyverno-cli

Kyverno CLI のインストール

いくつかインストール方法が用意されておりますが、本記事では Krew を使いインストールし検証を行いました。

$ kubectl krew install kyverno

$ kubectl kyverno version
Version: 1.9.0
Time: 2023-02-01T09:34:42Z
Git commit ID: a1534cc2f581bbc93c15fa5ac42fe5c59f03d66a

バイナリファイルも配布されています。kustomize を使ったマニフェストファイルへの動作検証を行う場合はこちらの Kyverno CLI を使うことが推奨されています。

git clone https://github.com/kyverno/kyverno
cd kyverno
make build-cli
mv ./cmd/cli/kubectl-kyverno/kyverno /usr/local/bin/kyverno

dry-run の方法

Kyverno CLI を使った dry-run は以下のコマンドで簡単に実行できます。
動作検証を行う対象(実環境のリソース or マニフェストファイル)や適用範囲などを限定して実行することができます。

$ kubectl kyverno <Policy> -r <Resource> --cluster -n <Namespace>
No. Policy Resource Cluster Namespace 対象
policy.yaml yaml false マニフェストファイル
policy.yaml リソース名 true 実環境:リソース指定
policy.yaml true 実環境:クラスタ全体
policy.yaml リソース名 true namespace名 実環境:リソースとnamespace指定
policy.yaml true namespace名 実環境:namespace指定
  • ① マニフェストファイルへの動作検証
    マニフェストファイルに対してポリシーの動作検証をしたい場合は以下です。
    $ kubectl kyverno policy.yaml --resource resource.yaml
    
  • ② 実環境のリソースに対して、リソース指定して動作検証
    ポリシーで指定している rule.match.any.resources.kind[] リソースの名前を指定します。例えばポリシーの対象が Pod で、test という Pod に対して動作検証をしたい場合は以下です。
    $ kyverno apply policy.yaml -r test --cluster
    
  • ③ 実環境のリソース(クラスタ全体)に対して動作検証
    kubectl の current-context のクラスタのリソースを対象に動作検証を行います。
    $ kyverno apply policy.yaml --cluster
    
  • ④ 実環境のリソースに対して、リソースとnamespaceを指定して動作検証
    ② に対して、さらに namespace を指定して動作検証を行います。
    $ kyverno apply policy.yaml -r test --cluster -n default
    
  • ⑤ 実環境のリソースに対して、namespace を指定して動作検証
    ポリシーで指定している rule.match.any.resources.kind[]リソースを namespace を絞って動作検証を行います。
    この場合、ポリシー内でrule.[match or exclude].any.resources.namespaces[] の指定はできません。
    $ kyverno apply policy.yaml --cluster -n default
    

dry-run してみる

以下のような適当なポリシーを用意します。
app.kubernetes.io/name ラベルが付与されていない Pod をデプロイさせないポリシーです。

require-labels.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce
  background: true
  rules:
  - name: check-for-labels
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "label 'app.kubernetes.io/name' is required"
      pattern:
        metadata:
          labels:
            app.kubernetes.io/name: "?*"

上記 require-labels ポリシーに従う Pod と反する Pod をデプロイします。

# ポリシーに従う Pod
$ kubectl run nginx-labeled --image=nginx --labels app.kubernetes.io/name=nginx -n default
pod/nginx-labeled created

# ポリシーに反する Pod
$ kubectl run nginx-non-labeled --image=nginx -n default
pod/nginx-non-labeled created

$ kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
nginx-labeled       2/2     Running   0          57s
nginx-non-labeled   2/2     Running   0          71s

この環境で require-labels ポリシー を dry-run してみます。

$ kubectl kyverno apply require-labels.yaml --cluster -n default

Applying 1 policy rule to 2 resources...

policy require-labels -> resource playground/Pod/nginx-non-labeled failed: 
1. check-for-labels: validation error: label 'app.kubernetes.io/name' is required. rule check-for-labels failed at path /metadata/labels/app.kubernetes.io/name/ 

pass: 1, fail: 1, warn: 0, error: 0, skip: 4 

結果を見ると、ポリシーに従う Pod は pass, ポリシーに反する Pod は fail となっていることがわかります。
このように、require-labels ポリシーを適用した際の既存リソースへの動作検証ができます🥳

skip: 4 となっている部分は、kyverno の Auto-Gen ルールに対する結果となります。
Kubernetes では Pod を直接作成することは少なく、Deployment や DaemonSet などの上位リソースから間接的に生成されます。
従って、Kyverno では Pod を resource.kind[] に指定した場合、その上位リソースを検証範囲としたルールが自動生成される便利な仕様となっています。
今回のポリシーでは、resource.kind[] に Pod を指定しているため Auto-Gen ルールが追加適用されたが、一致するリソースがないため skip としてカウントされています。

最後に

Kyverno で作ったポリシーを dry-run する方法についてまとめました。
Kyverno CLI を使ってポリシーの実環境へのリハーサルを行うことで、既存リソースへの影響を把握した上で、安全にポリシー適用を行うことができます。

Discussion