Closed11

Kubernetes 1.25でbetaになったCommon Expression Language (CEL)を試してみる

zoetrozoetro

カスタムリソースの構造体にマーカーをつけていきます。
フィールドにマーカーをつけるとそのフィールドのみがバリデーションの対象となりますが、構造体にマーカーをつけると複数のフィールドにまたがるバリデーションも書くことができるようです。

// SampleSpec defines the desired state of Sample
// +kubebuilder:validation:XValidation:rule="self.minReplicas <= self.replicas",message="replicas must be larger than minReplicas."
type SampleSpec struct {
	// +optional
	// +kubebuilder:validation:XValidation:rule="self >= 1 && self <= 5",message="must be 1 to 5"
	Replicas *int32 `json:"replicas,omitempty"`

	// +optional
	// +kubebuilder:validation:XValidation:rule="self >= 1 && self <= 5",message="must be 1 to 5"
	MinReplicas *int32 `json:"minReplicas,omitempty"`
}
zoetrozoetro

最新版のkindを使って、Kubernetes 1.25のクラスタを立ち上げます。

❯ kind version
kind v0.16.0 go1.19.1 linux/amd64

❯ kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.25.2) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/
zoetrozoetro

make manifestsを実行してCRDを生成してみます。
CRDの中に以下のような記述があれば成功です。

          spec:
            description: SampleSpec defines the desired state of Sample
            properties:
              image:
                type: string
              minReplicas:
                format: int32
                type: integer
                x-kubernetes-validations:
                - message: must be 1 to 5
                  rule: self >= 1 && self <= 5
              replicas:
                format: int32
                type: integer
                x-kubernetes-validations:
                - message: must be 1 to 5
                  rule: self >= 1 && self <= 5
            required:
            - image
            type: object
            x-kubernetes-validations:
            - message: replicas should larger than minReplicas.
              rule: self.minReplicas <= self.replicas
zoetrozoetro

生成されたCRDをKubernetesクラスタにmake installで適用します。

zoetrozoetro

もし、CELの記述に間違いがあったりすると、このタイミングでエラーになります。
ちゃんとフィールドの型もチェックしてくれるみたいですね。賢い。

❯ make install
test -s /tmp/sample/bin/controller-gen || GOBIN=/tmp/sample/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.9.2
/tmp/sample/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
/tmp/sample/bin/kustomize build config/crd | kubectl apply -f -
The CustomResourceDefinition "samples.test.zoetrope.github.io" is invalid: spec.validation.openAPIV3Schema.properties[spec].properties[replicas].x-kubernetes-validations[0].rule: Invalid value: apiextensions.ValidationRule{Rule:"self.replicas > 0 && self.replicas <= 5", Message:"must be 1 to 5"}: compilation failed: ERROR: <input>:1:5: type 'primitive:INT64' does not support field selection
 | self.replicas > 0 && self.replicas <= 5
 | ....^
ERROR: <input>:1:26: type 'primitive:INT64' does not support field selection
 | self.replicas > 0 && self.replicas <= 5
 | .........................^
make: *** [Makefile:91: install] Error 1
zoetrozoetro

サンプルのマニフェスト(sample.yaml)を用意します。

apiVersion: test.zoetrope.github.io/v1
kind: Sample
metadata:
  name: my-sample
spec:
  replicas: 1
  minReplicas: 10 
zoetrozoetro

このサンプルを適用してみると、ばっちりバリデーションできました!

❯ kubectl apply -f sample.yaml
The Sample "my-sample" is invalid:
* spec: Invalid value: "object": replicas should larger than minReplicas.
* spec.minReplicas: Invalid value: "integer": must be 1 to 5

でも、値を表示すべきところに型が表示されてしまってるような…?

と思ったけど、値が大きすぎたり秘密情報が含まれてる場合があったりするので、あえて型を出してるみたいですね。
https://github.com/kubernetes/enhancements/issues/2876#issuecomment-1211000400

このスクラップは2022/09/29にクローズされました