Closed oomichi closed 4 years ago
CRD: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
Custom Resources は API extensions であり、 Custom Resources をクラスタに追加する方法は2つある。
Resource は特定の Kind のAPI Objectsの集めたものである。たとえば、ビルトインの pods リソースは Pod Objects の集まりである。 Custm Resource は Kubernetes API extension であり、全てのKubernetesクラスタで有効になっていなければならない、というものではない。言い換えれば、特定の Kubernetes クラスタのカスタムとして現れるものである。 Custom Resource はDynamic Registrationによって、現れたり消えたり出来るものであり、クラスタ管理者は Custom Resourceをアップデートできる。一度、Custom Resourceがインストールされると、ユーザは kubectl コマンドを使って Object を作成したり、アクセスできる。pods のようなビルトインリソースと同様に。
Custom Resources とは構造化されたデータをAPI として格納、検索できるようにするものである。 対応する controller と組み合わせることで本当の意味での declarative API となる。 Declarative API はあなた自身のリソースとその好ましい状態を定義するものであり、実際の状態を好ましい状態にマッチさせるためのものである。 ここでController が構造化データをユーザが指定した好ましい状態のレコードとして処理し、それに対応したアクションをとることになる。 Custom Controller はユーザ自身でクラスタ上にデプロイ、アップデートするController であり、クラスタライフサイクルとは独立したものとなる。Custom Controllers はいかなる Kind のリソースに対しても動作できるが、特にCustom Resourceに対して動作することが効果的である。 Operator パターンはそのような組合せの一例である。それは開発者に特定アプリケーションに関する知識を API extension としてコード化することを可能にする。
(KubeCon NA 2018の基調講演で CoreOS の人が話していたやつ) SRE とはソフトウェアを書くことによってアプリケーションを運用する人々のことをさす。 彼らはどのように特定領域のソフトウェアが開発されるのかを知っているエンジニアであり、開発者である。 ソフトウェアの Resulting piece はアプリケーションの運用知識をプログラム化することである。
我々のチームはKubernetesコミュニティにおいてこのコンセプトを設計・実装することに働きかけている。 我々はこれを新しいソフトウェアのクラス Operators と命名した。Operator はアプリケーション固有の Controller であり、Kubernetes API を拡張するものだ。複雑なステートフルアプリケーションの実態を作成、設定管理するためのものだ。 それは基本的な Kubernetes の Resource の上に拡張されるものであり、アプリケーション固有の知識を自動化された一般タスクとしてハンドリングするためのものだ。
Stateless は簡単だが、Stateful はハードだ。 KubernetesはWebアプリ、モバイルバックエンド、APIサービスなどを管理、スケールさせることは比較的簡単だ。なぜか?それらのアプリケーションは基本的にStateless であり、基本的なKubernetes APIs たとえば Deployments などはスケール、失敗からの復旧などが追加の知識不要で実現可能だからだ。 大きな挑戦は DB、Caches、Monitoring systems のようなStateful アプリケーションを管理することだ。 それらのシステムではスケール、アップグレード、再設定を行う際にアプリケーション固有の知識を要求する。 我々はこのアプリケーション固有の運用知識をソフトウェアとしてコード化し、パワフルなKubernetes の抽象化によってアプリケーションを正しく管理したいと思っている。 Operatorはソフトウェアであり、これら特定領域の知識をコード化し、3rd party Resource としてKubernetes APIを拡張するものだ。これによってユーザはアプリケーションの作成、管理、設定を正しく行えるように出来る。
Operatorのコンセプトを動作するコードとしてデモするため、2つの確かなサンプルを Open Source プロジェクトとして公開する。 1つは etcd Operator、もうひとつは Prometheus Operator だ。それぞれ etcd クラスタ、Prometheus モニタリングインスタンスを作成、管理、設定するためのものだ。
OperatorはKubernetes の基本的なResource、Controllerのコンセプトの上に成り立っている。そして知識もしくは設定のセットを追加するものだ。Operator が一般的なアプリケーションのタスクとして実行可能になるように。 たとえば、etcd クラスタを手動でスケールするとき、ユーザは複数のステップを実行しなければならない。
1. 新しい etcd メンバーのために DNS ネームを作成
2. 新しい etcd インスタンスを起動
3. etcdctl member add コマンドの実行
というようなものだ。これを行う代わりに、etcd Operator はユーザは単に etcd クラスタのサイズを初期値1から変更すればよいだけだ。 もちろん、etcd クラスタを構成する etcd インスタンスの一つがなくなった場合も Kubernetes が Pod 同様に必要な復旧作業を自動的に行ってくれる。
どのように Operator を作るか。 API extension としてリソースを設定し、Controller loop を作成する。
kubectl create -f https://coreos.com/operators/etcd/latest/deployment.yaml
Operators が実装されているアプリケーションのリスト: https://commons.openshift.org/sig/operators.html
CRD を Tekton を例に理解する。
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: clustertasks.tekton.dev
spec:
group: tekton.dev
names:
categories:
- all
- tekton-pipelines
kind: ClusterTask
plural: clustertasks
scope: Cluster
subresources:
status: {}
version: v1alpha1
$ kubectl create -f release.yaml
$ kubectl get crd
NAME CREATED AT
clustertasks.tekton.dev 2019-05-29T22:49:58Z
images.caching.internal.knative.dev 2019-05-29T22:49:58Z
pipelineresources.tekton.dev 2019-05-29T22:49:58Z
pipelineruns.tekton.dev 2019-05-29T22:49:58Z
pipelines.tekton.dev 2019-05-29T22:49:58Z
taskruns.tekton.dev 2019-05-29T22:49:58Z
tasks.tekton.dev 2019-05-29T22:49:58Z
$ kubectl describe crd clustertasks.tekton.dev
Name: clustertasks.tekton.dev
Namespace:
Labels: <none>
Annotations: <none>
API Version: apiextensions.k8s.io/v1beta1
Kind: CustomResourceDefinition
Metadata:
Creation Timestamp: 2019-05-29T22:49:58Z
Generation: 1
Resource Version: 2020386
Self Link: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/clustertasks.tekton.dev
UID: 158fc444-8264-11e9-a717-fa163e6f5d61
Spec:
Conversion:
Strategy: None
Group: tekton.dev
Names:
Categories:
all
tekton-pipelines
Kind: ClusterTask
List Kind: ClusterTaskList
Plural: clustertasks
Singular: clustertask
Scope: Cluster
Subresources:
Status:
Version: v1alpha1
Versions:
Name: v1alpha1
Served: true
Storage: true
Status:
Accepted Names:
Categories:
all
tekton-pipelines
Kind: ClusterTask
List Kind: ClusterTaskList
Plural: clustertasks
Singular: clustertask
Conditions:
Last Transition Time: 2019-05-29T22:49:58Z
Message: no conflicts found
Reason: NoConflicts
Status: True
Type: NamesAccepted
Last Transition Time: <nil>
Message: the initial names have been accepted
Reason: InitialNamesAccepted
Status: True
Type: Established
Stored Versions:
v1alpha1
Events: <none>
$ kubectl -v=8 get ClusterTask
I0529 22:59:00.173782 26609 loader.go:359] Config loaded from file /home/ubuntu/admin.conf
I0529 22:59:00.183857 26609 round_trippers.go:416] GET https://192.168.1.123:6443/apis/tekton.dev/v1alpha1/clustertasks?limit=500
I0529 22:59:00.183874 26609 round_trippers.go:423] Request Headers:
I0529 22:59:00.183880 26609 round_trippers.go:426] Accept: application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json
I0529 22:59:00.183886 26609 round_trippers.go:426] User-Agent: kubectl/v1.14.1 (linux/amd64) kubernetes/b739410
I0529 22:59:00.211979 26609 round_trippers.go:441] Response Status: 200 OK in 28 milliseconds
I0529 22:59:00.212010 26609 round_trippers.go:444] Response Headers:
I0529 22:59:00.212017 26609 round_trippers.go:447] Content-Type: application/json
I0529 22:59:00.212020 26609 round_trippers.go:447] Content-Length: 1073
I0529 22:59:00.212025 26609 round_trippers.go:447] Date: Wed, 29 May 2019 22:59:00 GMT
I0529 22:59:00.212055 26609 request.go:942] Response Body: {"kind":"Table","apiVersion":"meta.k8s.io/v1beta1","metadata":{"selfLink":"/apis/tekton.dev/v1alpha1/clustertasks","resourceVersion":"2021123"},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names","priority":0},{"name":"Age","type":"date","format":"","description":"CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-co [truncated 49 chars]
No resources found.
これだけで API が作れるのは便利
https://github.com/kubernetes/sample-controller/blob/master/controller.go を読みながらのほうが理解しやすそう。
AddEventHandler()
で以下のREST APIに対するオペレーションに対応する処理を登録しているっぽい
AddFunc: controller.handleObject
UpdateFunc: func(old, new interface{}) { ...
DeleteFunc: controller.handleObject,
あっているっぽい ResourceEventHandlerFuncs の説明
183 // ResourceEventHandlerFuncs is an adaptor to let you easily specify as many or
184 // as few of the notification functions as you want while still implementing
185 // ResourceEventHandler.
186 type ResourceEventHandlerFuncs struct {
187 AddFunc func(obj interface{})
188 UpdateFunc func(oldObj, newObj interface{})
189 DeleteFunc func(obj interface{})
190 }
後はサンプルを元に CRD プロトタイプを作ってみたほうが良さそう。
CRD (Custome Resource Definition) と API extension の違いを把握する。 -> 同じっぽい
CRD の追加方法を把握する。