Tanzu Mission Controlで学ぶOpen Policy Agent Part-4

この記事はTanzu Mission Controlで学ぶ Open Policy Agentシリーズです。

シリーズ

第一回 : 概要
第二回 : TMCのOpen Policy Agentを遊んでみる
第三回 : TMCのOpen Policy Agentを解剖する
第四回 : TMCからOPAポリシーを自作する < いまここ

はじめに

前回までで、TMCでOPAがどのように利用できるかを紹介させていただきました。

TMCには、これにさらにCustomPolicyとよばれ、OPAポリシーを自作し、TMCのUIから管理する機能を提供します。

このシリーズの最後には、この機能を紹介し、締め括りたいと思います。

シナリオ - StorageClassをつかったPV作成を拒否

今回は以下のシナリオを想定します。

Kubernetesは通常、PersistentVolumeを作る場合、開発者はPersistentVolumeClaimを定義し、管理者側でPersistentVolumeを定義するような流れになります。

これがStaticなVolumeのアサインです。本来はこうすることで、開発者側に勝手にストレージを作られないようにするのが目的でした。

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#static

ところが、この流れをバイパスして、PersistentVolumeClaimの時点でボリュームを動的につくる方法として、StorageClassとよばれる方法があります。

これがDynamicなVolumeのアサインです。これは便利な反面、いくらでも不正なストレージ要求を行えてしまう問題があります。

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#dynamic https://kubernetes.io/docs/concepts/storage/storage-classes/

一応Quotaによって制限もできますが、それはNamespace単位での設定のため、設定がもれてしまうリスクがあります。

https://kubernetes.io/docs/tasks/administer-cluster/limit-storage-consumption/

というわけでこれをOPAで守ろうとしてみます。

OPAポリシーの作成

まず、OPAポリシーを作る必要があります。

この回を参考にOPAに食わせるインプット情報を取り出します。 今回は、以下のようなPVC作成時のルールを定義します。以下のYamlにあるstorageClassName: defaultが定義されていたら作成を許可しない、というルールにします。

 1kind: PersistentVolumeClaim
 2apiVersion: v1
 3metadata:
 4  name: myclaim2
 5spec:
 6  accessModes:
 7  -  ReadWriteOnce
 8  resources:
 9    requests:
10      storage: 1Gi
11  storageClassName: default

インプット情報が取得できたら、Playgroundで、このポリシーを作ってみます。 出来上がったのが以下。

https://play.openpolicyagent.org/p/4cKZIuijl2

これは、非常に単純で、StorageClassNameがInputにある場合、拒否するというものです。

TMCにOPAルールをTemplatesとして登録

このOPAのルールをTMCに定義します。 TMCの左ペインの[Templates]を選択し、[Create Templates]を選択します。 [Provide Yaml]ですが、これは前回説明したConstraintTemplatesを定義するための箇所です。 今回のシナリオでは以下のように記載します。

画面ショットの中のYamlは以下の通りです。

 1apiVersion: templates.gatekeeper.sh/v1beta1
 2kind: ConstraintTemplate
 3metadata:
 4  name: custom-deny-storageclass
 5spec:
 6  crd:
 7    spec:
 8      names:
 9        kind: custom-deny-storageclass
10  targets:
11    - target: admission.k8s.gatekeeper.sh
12      rego: |
13        package denystorageclass
14
15        violation[{"msg": msg, "details": {}}] {
16          sc = input.review.object.spec.storageClassName
17          msg := "Creating PVC with storageClass is not allowed"
18        }        

上にあるよう、rego以下には前手順でつくりあげたOPAポリシーをコピペします。 それ以外の箇所はほぼテンプレですが、ポイントとなるのが、metadata.namespec.crd.spec.names.kindの値に他のルールと重複しないものを定義します。

Customポリシーの定義

上記のTemplateを登録したあとは[Assignments] > [Custom] そして、ルールを適用したいクラスターを選択します。

さきほどつくったTemplateを選択し、名前も与えます。

次にTargetResourceには、どのリソースに対してルールを定義するかを選択します。 今回はPersistentVolumeClaimを選択します。さらに、“Exclude specific namespaces"には、このルールを例外とするNamespaceを任意に設定可能です。今回は、allowstorageclass=trueを追加します。

この状態でCreate Policyを実行します。以上です。

試してみる

適用したクラスターで早速ポリシーを違反したPVCを作ってみます。 すると以下のようにうまくルールが適用され、作成が拒否されました。

1% kubectl create -f pvc.yaml
2Error from server ([denied by tmc.cgp.deny-storageclass] Creating PVC with storageClass is not allowed): error when creating "pvc.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [denied by tmc.cgp.deny-storageclass] Creating PVC with storageClass is not allowed

さらにNamespaceの例外ルールも試してみます。 まずNamespaceを作成し、allowstorageclass=trueのラベルを追加します。

1% kubectl create ns test
2namespace/test created
3% kubectl label namespace test allowstorageclass=true
4namespace/test labeled

すると、このNamespaceでは問題なく、PVCがつくれます。

1% kubectl create -f pvc.yaml -n test
2persistentvolumeclaim/myclaim2 created
3% kubectl get pvc -n test
4NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
5myclaim2   Bound    pvc-2116cbbd-7fb8-45b7-92cc-cfe43bbc899c   1Gi        RWO            default        6s

期待通りですね。

まとめ

第四回では、TMCを使い自作OPAポリシーを自作する方法を紹介しました。 すごくシンプルにできることがわかりました。 またこのシリーズでは、TMCを使いOPAをより深く理解できるようになりました。