Kubernetes 1.30 から GA になった ValidatingAdmissionPolicy を使うと、リソースへの操作に対して validation をかけることができます。ここでは、特定のアノテーションがついている PVC に対して削除が実行されようとしたときにそれを弾くことで、PVC の誤削除を防ぐようにしてみます。
まず以下のような ValidatingAdmissionPolicy リソースを作ります:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: prevent-deletion.admission.ket.anqou.net
namespace: admission
spec:
matchConstraints:
resourceRules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- DELETE
resources:
- persistentvolumeclaims
validations:
- expression: |
!("admission.ket.anqou.net/prevent-deletion" in variables.annots) ||
variables.annots["admission.ket.anqou.net/prevent-deletion"] != "true"
message:
all pvcs annotated with "admission.ket.anqou.net/prevent-deletion" must
not be deleted
variables:
- expression:
"has(oldObject.metadata.annotations) ? oldObject.metadata.annotations
: {}"
name: annots
failurePolicy: Fail
.spec.matchConstraints
を使い、どのリソースに対するどういった操作に干渉したいかを書きます。ここでは persistentvolumeclaims
に対する DELETE
を対象にします。
.spec.validations
に validation を書きます。記述言語として CEL が採用されています。ここでは admission.ket.anqou.net/prevent-deletion: true
という annotation がついていないことを記述しています。なお、式中では variables.annots
という変数を使っています。この変数の定義は .spec.variables
に書いています。
.spec.failurePolicy
で、validation が失敗したときの挙動を決定できます。Fail
にしておくと、操作(今回なら DELETE)を失敗させます。
さて、上記のように作った ValidatingAdmissionPolicy を有効化するためには ValidatingAdmissionPolicyBinding リソースを作り、どの namespace に対して有効化するかを決める必要があります。今回はすべての namespace に存在する PVC に対して動いてほしいので、以下のような ValidatingAdmissionPolicyBinding を作ります:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: prevent-deletion.admission.ket.anqou.net
namespace: admission
spec:
policyName: prevent-deletion.admission.ket.anqou.net
validationActions:
- Deny
実際に使ってみます。Minikube v1.34.0 を使って Kubernetes v1.30.5 の環境を作り、上 2 つのリソースを apply します。その後 PVC を作り、それに admission.ket.anqou.net/prevent-deletion
annotation をつけた上で、削除を試みると、失敗することが分かります:
$ cat <<EOS | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
admission.ket.anqou.net/prevent-deletion: "true"
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: topolvm-provisioner
EOS
persistentvolumeclaim/test-pvc created
$ kubectl delete pvc test-pvc
The persistentvolumeclaims "test-pvc" is invalid: : ValidatingAdmissionPolicy 'prevent-deletion.admission.ket.anqou.net' with binding 'prevent-deletion.admission.ket.anqou.net' denied request: all pvcs annotated with "admission.ket.anqou.net/prevent-deletion" must not be deleted