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というものもあるようだが、そちらはまた今度。

参考:

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *