repl.info

CRDについてのメモ

Kubernetesのカスタムリソースについてのメモ。基本的には公式ドキュメントの Custom Resources にいろいろと説明が書かれているのでここを読めばよい。カスタムリソース自体は構造化されたデータをKubernetes上に保存・取得できる機能といえる。これにカスタムコントローラを組み合わせることで、Deploymentのようなビルトインリソースと同じような宣言的APIを用いた状態管理を実現できるようになる。データ保存だけなら必ずしもカスタムコントローラーは必要ではないというのが最初分かっていなかった。

軽く試す。使用バージョンは以下の通り:

  • Kubernetes v1.12.3
  • minikube v0.32.0

検証用環境はminikubeで起動:

$ minikube start --memory=8192 --cpus=4 \

    --kubernetes-version=v1.12.3 \

    --vm-driver=hyperkit \

    --bootstrapper=kubeadm

kubernetes/sample-controller を参考にしつつ、CRD用のマニフェストを作成する。グループやバージョンがリソースへアクセスする際のAPIとなる(/apis/<group>/<version>)。リソースのkindや単数形、複数形なども定義できる。

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: foos.samplecontroller.k8s.io

spec:

  group: samplecontroller.k8s.io

  version: v1alpha

  scope: Namespaced

  names:

    plural: foos

    singular: foo

    kind: Foo

    shortNames:

      - foo

このマニフェストを適用すると、以下のようにcrdリソースとして見えるようになる:

$ kubectl get crd

NAME AGE

foos.samplecontroller.k8s.io 34m

Fooリソースを作ってみる。以下のようなマニフェストを用意し、 kubectl applyする:

---

apiVersion: samplecontroller.k8s.io/v1alpha

kind: Foo

metadata:

  name: foo-001

spec:

  deploymentName: deploy-foo-001

  replicas: 1

---

apiVersion: samplecontroller.k8s.io/v1alpha

kind: Foo

metadata:

  name: foo-002

spec:

  deploymentName: deploy-foo-002

  replicas: 1

  hoge: huga

Fooリソースが作成されていることがわかる:

$ kubectl get foos

NAME AGE

foo-001 50s

foo-002 50s

リソースの詳細を見ると、マニフェストで指定したspecが確認できる:

$ kubectl describe foo foo-001

Name: foo-001

Namespace: default

Labels: <none>

Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"samplecontroller.k8s.io/v1alpha","kind":"Foo","metadata":{"annotations":{},"name":"foo-001","namespace":"default"},"spec":{"deploymentNa...

API Version: samplecontroller.k8s.io/v1alpha

Kind: Foo

Metadata:

  Creation Timestamp: 2019-01-02T03:42:45Z

  Generation: 1

  Resource Version: 3649

  Self Link: /apis/samplecontroller.k8s.io/v1alpha/namespaces/default/foos/foo-001

  UID: 77506f4f-0e40-11e9-95ac-263ada282756

Spec:

  Deployment Name: deploy-foo-001

  Replicas: 1

Events: <none>

リソース毎にspecが異なることも確認できる:

$ kubectl describe foo foo-002

Name: foo-002

Namespace: default

Labels: <none>

Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"samplecontroller.k8s.io/v1alpha","kind":"Foo","metadata":{"annotations":{},"name":"foo-002","namespace":"default"},"spec":{"deploymentNa...

API Version: samplecontroller.k8s.io/v1alpha

Kind: Foo

Metadata:

  Creation Timestamp: 2019-01-02T03:42:45Z

  Generation: 1

  Resource Version: 93582

  Self Link: /apis/samplecontroller.k8s.io/v1alpha/namespaces/default/foos/foo-002

  UID: 775194f8-0e40-11e9-95ac-263ada282756

Spec:

  Deployment Name: deploy-foo-002

  Hoge: huga

  Replicas: 1

Events: <none>

CRDでバリデーションを行うこともできる(OpenAPIv3.0を使うようだ)。kubernetes/sample-controller を見つつ、replicasのバリデーションを設定してみる:

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: foos.samplecontroller.k8s.io

spec:

  group: samplecontroller.k8s.io

  version: v1alpha

  scope: Namespaced

  names:

    plural: foos

    singular: foo

    kind: Foo

    shortNames:

      - foo

  validation:

    openAPIV3Schema:

      properties:

        spec:

          properties:

            replicas:

              type: integer

              minimum: 1

              maximum: 10

これで、replicasの最小値と最大値が設定される。replicasが10より大きいマニフェストを用意して適用してみる:

---

apiVersion: samplecontroller.k8s.io/v1alpha

kind: Foo

metadata:

  name: foo-003

spec:

  deploymentName: deploy-foo-003

  replicas: 20

バリデーションに引っかかり、作成に失敗することが確認できた。

$ kubectl apply -f ./foo-invalid.yaml

The Foo "foo-003" is invalid: []: Invalid value: map[string]interface {}{"apiVersion":"samplecontroller.k8s.io/v1alpha", "kind":"Foo", "metadata":map[string]interface {}{"name":"foo-003", "namespace":"default", "creationTimestamp":"2019-01-03T01:05:13Z", "annotations":map[string]interface {}{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"samplecontroller.k8s.io/v1alpha\",\"kind\":\"Foo\",\"metadata\":{\"annotations\":{},\"name\":\"foo-003\",\"namespace\":\"default\"},\"spec\":{\"deploymentName\":\"deploy-foo-003\",\"replicas\":20}}\n"}, "generation":1, "uid":"a02a984d-0ef3-11e9-95ac-263ada282756"}, "spec":map[string]interface {}{"replicas":20, "deploymentName":"deploy-foo-003"}}: validation failure list:

spec.replicas in body should be less than or equal to 10

API Aggregationというものもあるようだが、そちらはまた今度。

参考: