Kubernetes の CRD Kubernetes には、pod、deployment、configmap、service など、k8s の内部コンポーネントによって管理される一連の組み込みリソースがあります。これらの組み込みリソースに加えて、k8s では、ユーザーが自由にリソースをカスタマイズできる別の方法、CRD (フルネーム CustomResourceDefinitions) も提供されています。 たとえば、CRD を使用して、mypod、myjob、myanything などのリソースを定義できます。正常に登録されると、これらのカスタム リソースは組み込みリソースと同じように扱われます。具体的には: - kubectl を使用してデプロイメントを追加、削除、変更、クエリするのと同じように、これらの CRD カスタム リソースを操作できます。
- CRD カスタム リソースのデータは、pod などの組み込みリソースと同様に、k8s コントロール プレーンの etcd に保存されます。
CRD は状況によって意味が異なることに注意してください。場合によっては、特定のリソース (k8s の CustomResourceDefinitions) を参照することもあれば、CRD を通じてユーザーが作成したカスタム リソースを参照することもあります。 狭義では、CRD (フルネーム CustomResourceDefinitions) は k8s の特別な組み込みリソースであり、これを使用して他のカスタマイズされたリソースを作成できます。たとえば、CRD を通じて CronTab というリソースを作成できます。 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: # 名称必须匹配<plural>.<group> name: crontabs.stable.example.com spec: # group 名称,用于REST API: /apis/<group>/<version> group: stable.example.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: # 定义属性spec: type: object properties: cronSpec: type: string image: type: string # 作用范围可以是Namespaced 或者Cluster scope: Namespaced names: # 复数名称,使用于URL: /apis/<group>/<version>/<plural> plural: crontabs # 单数名称,可用于CLI singular: crontab # 驼峰单数,用于资源清单kind: CronTab # 名字简写,可用于CLI shortNames: - ct この yaml ファイルを適用すると、カスタム リソース CronTab が k8s に登録されます。現時点では、my-crontab.yaml などのこのカスタム リソースを任意に操作できます。 apiVersion: "stable.example.com/v1" kind: CronTab metadata: name: my-new-cron-object spec: cronSpec: "* * * * */5" image: my-awesome-cron-image kubectl apply -f my-crontab.yaml を実行してカスタマイズされた CronTab を作成し、 kubectl get crontab を実行してカスタマイズされた CronTab リストを照会します。 CRD を通じてリソースをカスタマイズする利点は、カスタム リソースのデータ ストレージについて心配する必要がなく、これらのカスタム リソースを操作するための API インターフェイスを公開するために追加の http サーバーを実装する必要がないことです。これは、k8s がこれらすべてを実行してくれるためです。他の組み込みリソースと同様に、カスタム リソースのみを使用する必要があります。 しかし! CRD だけでは不十分な場合がよくあります。たとえば、上記の例では、kubectl apply -f my-crontab.yaml を実行して、crontab カスタム リソースを作成しました。ただし、この crontab には実行可能なコンテンツが含まれていません (プログラムは実行されません)。多くのシナリオでは、カスタム リソースで何かを実行できるようにする必要があります。このときにオペレーターが必要になります。 オペレーターOperator は実際にはカスタム リソース コントローラーです。その役割は、カスタム リソースの変更を監視し、対象となる操作を実行することです。たとえば、カスタム リソースの作成を監視した後、Operator はカスタム リソースのプロパティを読み取り、特定のプログラムを実行するポッドを作成して、ポッドをカスタム リソース オブジェクトにバインドできます。 では、Operator はどのように存在するのでしょうか?実際のところ、通常のサービスと同じです。デプロイメントまたはステートフル セットにすることができます。 よく言われる Operator パターンは、実際には CRD + カスタム コントローラー モデルです。 キューブビルダープロジェクトを構築するとき、開発者がより簡単に作成、テスト、デプロイできるようにするための一連のツールを提供できる優れたフレームワークが欲しいと思うことがよくあります。 CRD および Operator シナリオには、Kubebuilder と呼ばれるフレームワークがあります。 次に、Kubebuilder を使用して小さなプロジェクトを作成します。このプロジェクトでは、カスタム リソース Foo を作成し、コントローラーでこのリソースの変更を監視して出力します。 1. インストール# download kubebuilder and install locally. curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)" chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
2. テストディレクトリを作成するmkdir kubebuilder-test cd kubebuilder-test
3. プロジェクトを初期化するkubebuilder init --domain mytest.domain --repo mytest.domain/foo
4. CRDを定義する次の形式で CRD を定義するとします。 apiVersion: "mygroup.mytest.domain/v1" kind: Foo metadata: name: xxx spec: image: image msg: message 次に、CRD を作成する必要があります (基本的には API を作成します)。 kubebuilder create api --group mygroup --version v1 --kind Foo 実行後、生成を確認するために y を入力すると、kubebuilder によって次のようなディレクトリとファイルが自動的に作成されます。 - この CRD (および API) は、api/v1/foo_types.go ファイルで定義されています。
- internal/controllers/foo_controller.go ファイルは、CRD のビジネス ロジックを制御します。
自動的に生成されたファイルは単なる基本的なフレームワークなので、必要に応じて変更する必要があります。 a.コード内のCRD構造を変更する まず、api/v1/foo_types.go を変更して CRD の構造を調整します (//+kubebuilder コメントを削除しないように注意してください)。 // FooSpec defines the desired state of Foo type FooSpec struct { Image string `json:"image"` Msg string `json:"msg"` } // FooStatus defines the observed state of Foo type FooStatus struct { PodName string `json:"podName"` } b.コマンドを使用してCRD yamlを自動的に生成する make manifests コマンドを実行すると、kubebuilder は config/crd/bases ディレクトリに mygroup.mytest.domain_foos.yaml ファイルを生成します。このファイルは、CRD を定義する yaml ファイルです。 --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.13.0 name: foos.mygroup.mytest.domain spec: group: mygroup.mytest.domain names: kind: Foo listKind: FooList plural: foos singular: foo scope: Namespaced versions: - name: v1 schema: openAPIV3Schema: description: Foo is the Schema for the foos API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: FooSpec defines the desired state of Foo properties: image: type: string msg: type: string required: - image - msg type: object status: description: FooStatus defines the observed state of Foo properties: podName: type: string required: - podName type: object type: object served: true storage: true subresources: status: {} make manifests コマンドによって実行される具体的な内容は、Makefile ファイルで定義されます。 .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases このことから、kubebuilder は controller-gen ツールを使用して、コード内の特定の形式 (//+kubebuilder:... など) のコメントをスキャンし、CRD yaml ファイルを生成していることがわかります。 5. コントローラーロジックを追加するユーザーが作成したカスタム リソース Foo を監視し、そのプロパティを出力したいとします。 a.コントローラーを変更してビジネスロジックを追加する 次のように、internal/controllers/foo_controller.go ファイルを変更して、独自のビジネス ロジックを追加します。 func (r *FooReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { l := log.FromContext(ctx) // 补充业务逻辑foo := &mygroupv1.Foo{} if err := r.Get(ctx, req.NamespacedName, foo); err != nil { l.Error(err, "unable to fetch Foo") return ctrl.Result{}, client.IgnoreNotFound(err) } // 打印Foo 属性l.Info("Received Foo", "Image", foo.Spec.Image, "Msg", foo.Spec.Msg) return ctrl.Result{}, nil } // SetupWithManager sets up the controller with the Manager. func (r *FooReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&mygroupv1.Foo{}). Complete(r) } b.テストを実施する 注: テストにはローカルまたはリモートの k8s クラスター環境が必要です。デフォルトでは、現在の kubectl と同じ環境が使用されます。 CRD を登録するには、make install を実行します。 Makefile から、実際に次の命令が実行されていることがわかります。 .PHONY: install install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f - コントローラーを実行するには、make run を実行します。 Makefile から、実際に次の命令が実行されていることがわかります。 .PHONY: run run: manifests generate fmt vet ## Run a controller from your host. go run ./cmd/main.go すると、次の出力が表示されます。 ... go fmt ./... go vet ./... go run ./cmd/main.go 2023-12-19T15:14:18+08:00 INFO setup starting manager 2023-12-19T15:14:18+08:00 INFO controller-runtime.metrics Starting metrics server 2023-12-19T15:14:18+08:00 INFO starting server {"kind": "health probe", "addr": "[::]:8081"} 2023-12-19T15:14:18+08:00 INFO controller-runtime.metrics Serving metrics server {"bindAddress": ":8080", "secure": false} 2023-12-19T15:14:18+08:00 INFO Starting EventSource {"controller": "foo", "controllerGroup": "mygroup.mytest.domain", "controllerKind": "Foo", "source": "kind source: *v1.Foo"} 2023-12-19T15:14:18+08:00 INFO Starting Controller {"controller": "foo", "controllerGroup": "mygroup.mytest.domain", "controllerKind": "Foo"} 2023-12-19T15:14:19+08:00 INFO Starting workers {"controller": "foo", "controllerGroup": "mygroup.mytest.domain", "controllerKind": "Foo", "worker count": 1} foo.yaml を送信して試してみましょう: apiVersion: "mygroup.mytest.domain/v1" kind: Foo metadata: name: test-foo spec: image: test-image msg: test-message kubectl apply -f foo.yaml を実行すると、コントローラーの出力に foo が出力されます。 2023-12-19T15:16:00+08:00 INFO Received Foo {"controller": "foo", "controllerGroup": "mygroup.mytest.domain", "controllerKind": "Foo", "Foo": {"name":"test-foo","namespace":"aries"}, "namespace": "aries", "name": "test-foo", "reconcileID": "8dfd629e-3081-4d40-8fc6-bcc3e81bbb39", "Image": "test-image", "Msg": "test-message"} これは kubebuilder を使用する簡単な例です。 要約するKubernetes の CRD および Operator メカニズムは、ユーザーに強力なスケーラビリティを提供します。 CRD を使用すると、ユーザーはリソースをカスタマイズでき、オペレーターはこれらのリソースを管理できます。この拡張メカニズムにより、Kubernetes エコシステムに優れた柔軟性と可塑性が提供され、さまざまなシナリオでより広く使用できるようになります。 参考文献: - https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
- https://kubernetes.io/docs/concepts/extend-kubernetes/operator/
- https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-settings/
- https://book.kubebuilder.io/introduction
|