10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Kyvernoで特定条件にマッチするKuberentesリソースにMutationポリシーを適用する

Last updated at Posted at 2022-07-04

Kyvernoとは?

Kyvernoは、Validation(検証機能)とMutation(ミューテーション = 追加、更新、削除)機能を備えたKubernetesポリシーエンジンです。いわゆるPolicy-as-code(PaC)ソリューションの1つです。もともとNirmataからのオープンソースプロジェクトであり、後にCNCFに寄贈されているようです。

追記 2022/7/13: KyvernoはCNCF incubating Projectになりました - Kyverno moves to the CNCF Incubator

Kuberentesにおける代表的なPolicy as Code (PaC)ソリューションの紹介

ちなみに、2022 InfoQ Trends Report によると、Policy as Code (PaC)は Early Adoptersとして報告されています。参考までにKyverno以外で有名なPolicy as Code (PaC)ソリューションを2つ紹介します。

Pod Security Policies (PSP)

Kubernetesのポリシー機能といえば、 Pod Security Policies (PSP)があります。 PSPはPodとその属性に対して一連のValidation機能を提供します。その名前のとおり、Podに対する機能であり、Podの作成や更新に対して制御はできるが、Mutation機能は提供しません。残念ながらPSPはKubernetes v1.21でdeprecatedとなり、v1.25で削除の予定となっています。

Open Policy Agent (OPA) / Gatekeeper

Open Policy Agent (以下、OPA)は汎用的なポリシーエンジン機能を提供するOSSで、Regoと呼ばれるカスタム言語を介してKubernetesだけでなく、さまざまなプラットフォームで汎用的な利用が可能です。これもPolicy-as-code(PaC)ソリューションの1つです。Gatekeeperは、Kubernetesに特化したOPAの実装ソリューションであり、リクエストのValidation(検証機能)と、最近ではMutation(ミューテーション = 追加、更新、削除)機能も提供します。

KyvernoとOPA/Gatekeeperの機能比較

Kubernetes Policy Comparison: OPA/Gatekeeper vs Kyverno記事に分かりやすい機能比較テーブルがあったのでそれを貼り付けておきます。

スクリーンショット 2022-07-04 5.30.31.png
(Source: Kubernetes Policy Comparison: OPA/Gatekeeper vs Kyverno)

事前準備

それではようやく本題であるKyvernoを活用して特定条件にマッチするKuberentesリソースにポリシーを適用する試験を行っていきます。 まずは、デプロイ先となるk8sクラスタとkyvernoのインストールを行います。

KINDでKubernetesクラスタ作成

k8sクラスタをkind (Kubernetes in Docker)でローカルに構築します。
まずは、次のようなcontrol planeノード x 1、 workerノード x 1のk8sクラスタのためのkindクラスタ構成ファイル(cluster.yaml)を作成します。

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4 
nodes:
- role: control-plane
- role: worker

次に、kind cliコマンドで、k8s v1.21.10のノードイメージでk8sクラスタを作成します。

K8S_NODE_IMAGE=v1.21.10
kind create cluster --name my-kind-cluster \
--image=kindest/node:${K8S_NODE_IMAGE} \
--config cluster.yaml

クラスタ構築が完了したら念の為にクラスタにアクセスしてみます。

kubectl get node
NAME                            STATUS   ROLES    AGE   VERSION
my-kind-cluster-control-plane   Ready    master   37m   v1.21.10
my-kind-cluster-worker          Ready    <none>   37m   v1.21.10

kyvernoのインストール

QuickStartに従い下記のように作成したクラスタにkyvernoをインストールします。なお、他にもHelm chartからのインストールも可能です。詳しくはQuickStartください。

kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/main/config/install.yaml

kyvernoで特定ネームスペース作成されるPodにラベルを追加する

いよいよ本題の試験を行います。kyvernoのk8sリソースのMutateルール機能をつかって特定ネームスペース作成されるPodにラベルを追加してみます。
なお、mutateルールは、指定する条件にマッチするリソースを変更するために使用でき、以下のRFC 6902 JSONパッチ、もしくはStrategic mergeパッチのいづれかの方式が利用可能です。

  • patchesStrategicMerge
    • Strategic Merge PatchというKubernetes独自のマージの方法
    • 追加、置き換え、削除が可能。patchesJson6902よりはシンプルに記述が可能
  • patchesJson6902
    •  JSONPatch - RFC 6902 formatフォーマットでマージ記述が可能。
    •  patchesStrategicMergeと比べて細やかな指定が可能。追加、置き換え、削除が可能

また、補足情報として、ポリシーとルールの関係を説明します。

  • ポリシーはルールの集合である。
  • 各ルールは match宣言と、オプショナルでexclude宣言と,validate, mutate, generate, もしくはverifyImages宣言のいづれか1つで構成される
  • ポリシーは、クラスター全体のリソース(kind: ClusterPolicy)またはネームスペースごとのソース(kind: Policy)として定義できる。

スクリーンショット 2022-07-04 6.16.36.png
(Source: https://kyverno.io/docs/kyverno-policies/)

ClusterPolicyポリシーをデプロイ(patchesStrategicMerge)

ここでは、matchmutate宣言で構成されるルールを含むClusterPolicyリソースを作成します。また、パッチ方式にはpatchesStrategicMergeを指定します。
次のように、set-label-policyという名前のClusterPolicyリソースをクラスタにデプロイします。 このClusterPolicyリソースにはネームスペースtestns1に作成されるPodに、foo=barというラベルを追加するルールを定義しています。

kubectl apply -f - << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: "set-label-policy"
spec:
  rules:
    - name: "set-label"
      match:
        any:
        - resources:
            kinds:
            - Pod
            namespaces:
            - testns1
      mutate:
        patchStrategicMerge:
          metadata:
            labels:
              foo: bar
EOF

サンプルPodをデプロイしポリシーが適用されることを確認する

まずは、テストで利用するネームスペース(testns1testns2)を作成します。

create namespaces

kubectl apply -f - << EOF
apiVersion: v1
kind: Namespace
metadata:
  name: testns1
---
apiVersion: v1
kind: Namespace
metadata:
  name: testns2
EOF

次に、サンプルアプリケーションのマニフェストをapp.yamlに出力します。

cat << EOF > app.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
        ports:
        - containerPort: 80
EOF

testns1testns2の両ネームスペースにサンプルアプリケーションをデプロイします。

kubectl apply -f app.yaml -n testns1
kubectl apply -f app.yaml -n testns2

最後に、下記のように両ネームスペースにデプロイされたPodのラベルをチェックします。

kubectl get po -n testns1 --show-labels

NAME                       READY   STATUS    RESTARTS   AGE     LABELS
httpbin-6fdcdc89fc-b9wl6   1/1     Running   0          8m56s   app=httpbin,foo=bar,pod-template-hash=6fdcdc89fc

kubectl get po -n testns2 --show-labels

NAME                       READY   STATUS    RESTARTS   AGE     LABELS
httpbin-75bc8bcf78-p7m4l   1/1     Running   0          9m58s   app=httpbin,pod-template-hash=75bc8bcf78

無事、ClusterPolicyset-label-policyのルールが適用され、testns1に作成されたPodにfoo=barというラベルを追加されていることがわかります。

patchesJson6902パッチ方式のClusterPolicyポリシー

参考までに、上述しているClusterPolicyポリシーと同じ振る舞いをpatchesJson6902パッチ方式で定義すると次のようになります。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: "set-label-policy"
spec:
  rules:
    - name: "set-label"
      match:
        any:
        - resources:
            kinds:
            - Pod
            namespaces:
            - testns1
      mutate:
        patchesJson6902: |-
          - path: "/metadata/labels/foo"
            op: add
            value: "bar"

その他補足情報

Policy制御のためのオプション

Policyにはルールとは別に下記のPolicyの振る舞いを制御するオプションの設定が可能です。

  • validationFailureAction: Validationポリシールールを追加した場合、その失敗により、Admission Reviewリクエストをブロック(enforce)するか、Admission Reviewリクエストを許可(audit)して、ポリシーレポートでポリシーの失敗を報告するかを制御する。 デフォルトはaudit
  • validationFailureActionOverrides: ネームスペースごとにClusterPolicy属性として指定するvalidationFailureAction。 特定ネームスペースに指定されたvalidationFailureActionをオーバーライドする。
  • background: バックグランドのスキャンにより既存のリソースに対してもポリシー適用するかどうかを指定.デフォルトはtrue
  • schemaValidation: Policyのvalidationチェックを適用するかどうかを制御。 デフォルトはtrue。KyvernoはPolicyのスキーマのValidationを試み、そのリソースのOpenAPIスキーマ定義を満たしていると判断できない場合は失敗する。 ValidationまたはMutationのPolicyが該当。 スキーマのValidationをスキップするにはfalseに設定する
  • failurePolicy: defines the API server behavior if the webhook fails to respond. Allowed values are “Ignore” or “Fail”. Defaults to “Fail”. Webhookが応答失敗した場合のAPIサーバーの挙動を定義。 Ignore or Failを指定可能。 デフォルトはFail
  • webhookTimeoutSeconds: このPolicy適用のタイムアウトを秒単位で指定。 デフォルトのタイムアウトは10秒(値:1〜30秒)

(Source: Policy Settings)

特に個人的に重要だと思ったオプションとして、backgroundがあります。これをtrueにすると、既存のリソースに対してもポリシーの適用ができます。また、validationFailureActionやfailurePolicyも忘れず見ておきたいオプションかと思います。

10
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?