oomichi / try-kubernetes

12 stars 5 forks source link

CRD vs. API extension #71

Closed oomichi closed 4 years ago

oomichi commented 5 years ago

CRD (Custome Resource Definition) と API extension の違いを把握する。 -> 同じっぽい

CRD の追加方法を把握する。

oomichi commented 5 years ago

CRD: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/

Custom Resources は API extensions であり、 Custom Resources をクラスタに追加する方法は2つある。

Custom Resourcees

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 Controllers

Custom Resources とは構造化されたデータをAPI として格納、検索できるようにするものである。 対応する controller と組み合わせることで本当の意味での declarative API となる。 Declarative API はあなた自身のリソースとその好ましい状態を定義するものであり、実際の状態を好ましい状態にマッチさせるためのものである。 ここでController が構造化データをユーザが指定した好ましい状態のレコードとして処理し、それに対応したアクションをとることになる。 Custom Controller はユーザ自身でクラスタ上にデプロイ、アップデートするController であり、クラスタライフサイクルとは独立したものとなる。Custom Controllers はいかなる Kind のリソースに対しても動作できるが、特にCustom Resourceに対して動作することが効果的である。 Operator パターンはそのような組合せの一例である。それは開発者に特定アプリケーションに関する知識を API extension としてコード化することを可能にする。

https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#should-i-add-a-custom-resource-to-my-kubernetes-cluster から再開

oomichi commented 5 years ago

Operators from https://coreos.com/blog/introducing-operators.html

(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 を作成する。

  1. Operator を deployment としてインストールする
    kubectl create -f https://coreos.com/operators/etcd/latest/deployment.yaml
  2. Operators は新しい3rd party のタイプとしてKubernetes にインストールされる。ユーザは新しいアプリケーションをこのタイプを使って作成する。
  3. Operators は built-in kubernetes primitives たとえば Services や ReplicaSetsなどを使って、よくテストされよく理解されたコードを活用する。
  4. Operators は互換性を保ち、前バージョンの Resource として作成されたものを持ち越せるようにしている。
  5. Operators は Operators の停止、削除による影響をアプリケーションインスタンスに与えないように設計されている。
  6. Operators はユーザに希望するバージョンを指定可能にする。アップグレードの際にも。ソフトウェアのアップグレードを行わないことは、運用上のバグとセキュリティ問題の一般的な原因であり、Operatorsはこの運用負担の軽減を行うものである。
  7. Operators はChaos Monkeyによってテストされることが必須である。Pod、設定、ネットワークの潜在的な問題を顕在化するために。

Operators が実装されているアプリケーションのリスト: https://commons.openshift.org/sig/operators.html

oomichi commented 5 years ago

CRD を Tekton を例に理解する。

  1. https://storage.googleapis.com/tekton-releases/latest/release.yaml から Tekton の正式リリースの YAML をゲット
  2. Tekton 向け CRD の内容は以下の通り これで GET /apis/tekton.dev/v1alpha1/clustertasks の API が作れる。
    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
  3. 上記 YAML を実行する
    $ kubectl create -f release.yaml
  4. CRD が作られていることを確認する
    $ 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
  5. clustertasks.tekton.dev の詳細を確認
    $ 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>
  6. kubectl コマンドで操作できることを確認
    $ 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 が作れるのは便利

oomichi commented 5 years ago

CRD Controllers の作り方を知る

https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#custom-controllers

https://github.com/kubernetes/sample-controller/blob/master/controller.go を読みながらのほうが理解しやすそう。 AddEventHandler() で以下のREST APIに対するオペレーションに対応する処理を登録しているっぽい

あっているっぽい 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 プロトタイプを作ってみたほうが良さそう。