0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Crossplane の抽象 API:XRD、XR、Composition で Platform API を組み立てる

0
Posted at

初めに

前回の記事では、Crossplane の動作を API Server、Reconcile、status の流れで整理しました。

kubectl apply した YAML は Kubernetes API Server に保存され、Crossplane や Provider の controller がそれを継続的に見て、外部クラウドの状態と合わせていく、という話でした。

今回は、その上に 利用者向けの抽象 API をどう作るかを整理します。

中心になるのは、次の三つです。

XRD
XR
Composition

OCI Object Storage Bucket のような Managed Resource をそのまま利用者に見せることもできます。

ただし、Platform API として使いやすくするなら、利用者には OCI の全 field ではなく、利用者が本当に判断すべき項目だけを見せたい場面があります。

そのための部品が、XRD、XR、Composition です。


この記事のゴール

この記事のゴールは、次の関係を自分の言葉で説明できるようになることです。

XRD
  -> 利用者向け API の型とスキーマを定義する

XR
  -> 利用者が作成する要求そのもの

Composition
  -> XR から Managed Resource などを作るレシピ

全体像は、次のように見ると分かりやすいです。

利用者
  |
  v
Composite Resource (XR)
  |
  v
Composition
  |
  v
Managed Resource
  |
  v
Provider
  |
  v
OCI Resource

ここで大事なのは、Composition が直接 OCI API を呼ぶわけではない、という点です。

Composition は、XR の内容から Kubernetes resource 群を作るためのレシピです。

その結果として作られた Managed Resource を、Provider が OCI API と状態合わせします。


なぜ抽象 API が必要なのか

Managed Resource を直接使うと、OCI の設定項目をかなり細かく扱えます。

これは強力ですが、利用者にとって常に分かりやすいとは限りません。

たとえば、開発チームが欲しいものは、次のような要求かもしれません。

team-a 用の bucket がほしい
標準の命名規則に従ってほしい
標準の tag を付けてほしい
必要な IAM や Secret の扱いは platform 側で決めてほしい

一方で、OCI 側の実装には、Object Storage Bucket、namespace、compartment、region、IAM policy、tag、Secret などが関係します。

この差をそのまま利用者に渡すと、利用者 API ではなく、クラウド実装の field 一覧になってしまいます。

Platform API の考え方では、利用者に見せる API と、platform 側で責任を持つ実装を分けます。

利用者が見る API
  -> team, tier, region など

platform 側の実装
  -> bucket 名、tag、IAM、ProviderConfig、Secret、Managed Resource

XRD、XR、Composition は、この分離を Crossplane 上で表現するための基本部品です。


XRD、XR、Composition を一文で整理する

まずは、三つの役割を短く整理します。

部品 役割
XRD 新しい Composite Resource API の型、名前、version、scope、schema を定義する
XR XRD で定義された API を使って、利用者が作成する要求
Composition XR の要求から、Managed Resource などの実装 resource を作るレシピ

もう少し具体的に言うと、XRD は API の設計図、XR はその API を使った一つの注文、Composition はその注文を実装へ変換する作り方です。

XRD
  AppBucket という API を作る

XR
  team-a 用に AppBucket を一つ要求する

Composition
  AppBucket から OCI Bucket 用の Managed Resource を作る

この三つを分けて考えると、Crossplane の抽象化がかなり読みやすくなります。


XRD は利用者向け API の型とスキーマを定義する

XRD は CompositeResourceDefinition の略です。

Crossplane の公式ドキュメントでは、XRD は custom API の schema を定義し、ユーザーはその schema に基づいて Composite Resource を作成すると説明されています。

Kubernetes の CustomResourceDefinition に近いですが、Crossplane では Composite Resource 用の API を作るために使います。

たとえば、OCI Bucket を直接見せるのではなく、利用者向けに AppBucket という API を作りたいとします。

概念的には、次のような XRD になります。

apiVersion: apiextensions.crossplane.io/v2
kind: CompositeResourceDefinition
metadata:
  name: appbuckets.platform.example.org
spec:
  group: platform.example.org
  names:
    kind: AppBucket
    plural: appbuckets
  scope: Namespaced
  versions:
  - name: v1alpha1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              team:
                type: string
              tier:
                type: string
                enum:
                - standard
                - premium
              region:
                type: string
            required:
            - team
            - tier
            - region

この例では、利用者に teamtierregion だけを入力してもらう API にしています。

OCI の bucket 名、tag、細かい policy、ProviderConfig の参照などは、ここでは利用者に直接見せていません。

XRD を読むときは、まず次の点を見ると分かりやすいです。

見る場所 意味
spec.group API group
spec.names.kind 利用者が書く kind
spec.names.plural API resource 名
spec.scope namespace 単位か cluster 単位か
spec.versions[].schema.openAPIV3Schema 入力できる field、型、必須項目、validation

注意点として、XRD の groupnames は気軽に変えるものではありません。

公式ドキュメントでも、XRD の groupnames を変更するには XRD の削除と再作成が必要になると説明されています。

つまり、XRD は単なる YAML ではなく、利用者に公開する API の名前そのものを決める場所です。


scope は Namespaced を基本に考える

Crossplane v2 の XRD では、scope を指定できます。

代表的には、次の二つです。

scope 意味
Namespaced XR は namespace 内に作られる
Cluster XR は cluster scope に作られる

Platform API としてチームや namespace ごとに分離したい場合は、まず Namespaced を基本に考えると分かりやすいです。

Namespaced にすると、利用者は自分の namespace に XR を作り、RBAC も namespace 単位で設計しやすくなります。

一方で、cluster 全体の設定や platform 全体に関わる API であれば、Cluster が合う場合もあります。

また、古い資料や v1 互換の説明では、Composite Resource Claim、つまり XRC が出てくることがあります。

ただし、Crossplane v2 の新しい namespaced XR では、claims は基本的に使いません。

公式の v2 API でも、claimNames は v2 ではサポートされない扱いになっています。

そのため、新しく設計するなら、まずは Namespaced な XR と RBAC で利用者入口を作る、という見方が自然です。


XR は利用者が作成する要求そのもの

XR は Composite Resource の略です。

XRD によって AppBucket という API が作られると、利用者はその API を使って実際の要求を書けるようになります。

たとえば、次のような YAML です。

apiVersion: platform.example.org/v1alpha1
kind: AppBucket
metadata:
  name: demo-bucket
  namespace: team-a
spec:
  team: team-a
  tier: standard
  region: ap-tokyo-1

この YAML は、OCI Bucket の全設定ではありません。

利用者が platform に対して出す、より小さく整理された要求です。

ここで利用者が考えるのは、たとえば次のような内容です。

どの team の bucket か
どの service tier か
どの region に置くか

逆に、次のようなことは platform 側に隠せます。

bucket 名の完全な命名規則
共通 tag
ProviderConfig の名前
Secret の置き場所
OCI IAM の細かい設計
Managed Resource の apiVersion や kind

この分離によって、利用者は cloud provider の細部ではなく、自分のアプリケーションやチームの要求に集中できます。


Composition は XR を実装 resource へ変換するレシピ

Composition は、XR をどのような Kubernetes resource 群へ展開するかを定義します。

Crossplane の公式ドキュメントでは、Composition は一つの Composite Resource の要求から複数の Kubernetes resources を作るための template と説明されています。

ここで最初に混乱しやすい点があります。

XRD は apiextensions.crossplane.io/v2 ですが、Composition は現在も apiextensions.crossplane.io/v1 の API を使います。

これは書き間違いではありません。

概念的には、Composition は次のような形になります。

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: appbucket-oci
spec:
  compositeTypeRef:
    apiVersion: platform.example.org/v1alpha1
    kind: AppBucket
  mode: Pipeline
  pipeline:
  - step: patch-and-transform
    functionRef:
      name: function-patch-and-transform

ここでまず見るべきなのは、compositeTypeRef です。

compositeTypeRef は、この Composition がどの XR の型に対応するかを示します。

上の例では、platform.example.org/v1alpha1AppBucket に対応しています。

次に見るのが mode: Pipelinepipeline です。

現在の Crossplane では、Composition は Function pipeline として処理されます。

各 step が Function を呼び出し、最終的に Crossplane が作成または更新すべき resource 群を組み立てます。

その中に OCI Bucket の Managed Resource が含まれていれば、次の段階で OCI Provider がその Managed Resource を reconcile します。

つまり、流れは次のようになります。

XR
  |
  v
Composition pipeline
  |
  v
Managed Resource YAML
  |
  v
Provider controller
  |
  v
OCI API

Composition は「OCI を直接操作する処理」ではありません。

XR から Managed Resource などを作るためのレシピ、と見ると理解しやすいです。


XRD、XR、Composition、Managed Resource の関係

ここまでをまとめると、役割は次のように分かれます。

XRD
  API の型とスキーマを決める

XR
  利用者の要求を表す

Composition
  要求を実装 resource へ変換する

Managed Resource
  Provider が外部 API と状態合わせする対象

OCI Bucket の例で言うと、次のような分担です。

誰が主に見るか
XRD AppBucket API の schema platform team
XR team-ademo-bucket 要求 利用者、platform team
Composition AppBucket から OCI Bucket MR を作るレシピ platform team
Managed Resource OCI Object Storage Bucket の Kubernetes 表現 platform team、debug 時の運用者
OCI Resource 実際の Object Storage Bucket OCI 管理者、運用者

利用者にとって重要なのは、XR の spec が自分たちの言葉になっていることです。

platform team にとって重要なのは、Composition 側で命名、tag、policy、ProviderConfig、出力の扱いを標準化できることです。


Composite Resource Claim はどう見るか

Crossplane の古い資料や既存環境では、Composite Resource Claim、つまり XRC が出てくることがあります。

XRC は、namespace 側から XR を要求する入口として使われてきた仕組みです。

特に Crossplane v1 系の設計では、namespace に claim を作り、それに対応する XR が作られる、という形がよく出てきます。

ただし、Crossplane v2 では namespaced XR が入ったため、新しく Platform API を設計する場合は、まず XRC ではなく namespaced XR を中心に考えるのが分かりやすいです。

そのため、資料やサンプルを読むときは、次のように切り分けると混乱しにくくなります。

新しく v2 前提で設計する
  -> Namespaced XR を中心に見る

既存の v1 系資料や古い platform design を読む
  -> XRC が出る可能性がある

XRC を完全に忘れてよい、という意味ではありません。

既存環境を読むときには必要になることがあります。

ただし、最初に学ぶ主線としては、XRD、XR、Composition の三つを先に押さえるほうが理解しやすいです。


利用者入口は「誰に、どの粒度の API を見せるか」で決まる

Platform API を設計するときに大事なのは、最初から全部を抽象化しようとしないことです。

たとえば、OCI Bucket を扱う場合でも、利用者に見せる API の粒度はいくつかあります。

Bucket そのものを見せる
  -> OCI の概念に近い

AppBucket として見せる
  -> アプリケーション向けに少し抽象化する

TeamStorage として見せる
  -> bucket 以外の policy や Secret も含めた能力として見せる

どれが正解かは、組織や利用者によって変わります。

開発チームが OCI に詳しく、細かい field を自分で扱いたいなら、Managed Resource に近い API でもよいかもしれません。

一方で、platform team が標準化や安全な初期値を強く管理したいなら、AppBucketTeamStorage のような API のほうが合います。

判断するときは、次の問いが役に立ちます。

利用者は誰か
利用者はどの field を判断すべきか
platform team が標準化したい部分はどこか
namespace と RBAC はどう分けるか
削除や変更の責任は誰が持つか

XRD は API の形を固定します。

だからこそ、YAML を書き始める前に、利用者入口の粒度を決めておくことが重要です。


読む順番は XRD、XR、Composition

Crossplane の抽象 API を読むときは、いきなり Composition の中身から入ると迷いやすいです。

おすすめの順番は、次の通りです。

1. XRD
   どんな API が定義されているかを見る

2. XR
   利用者は何を要求しているかを見る

3. Composition
   その要求をどう実装へ変換しているかを見る

4. Managed Resource
   実際にどんな resource が作られたかを見る

5. status
   READY / SYNCED / atProvider で状態を見る

コマンドとしては、たとえば次のような見方になります。

kubectl get compositeresourcedefinitions.apiextensions.crossplane.io
kubectl get compositions.apiextensions.crossplane.io

kubectl get appbuckets.platform.example.org -n team-a
kubectl describe appbuckets.platform.example.org demo-bucket -n team-a

実際の resource 名は、XRD で定義した groupnamesversions によって変わります。

まず XRD を見て API の名前を確認し、その後で XR と Composition を追うと、全体のつながりを失いにくくなります。


まとめ

今回は、Crossplane で Platform API を作るための基本部品として、XRD、XR、Composition を整理しました。

ポイントは、次の三つです。

XRD は API の型とスキーマを定義する
XR は利用者の要求を表す
Composition は実装 resource へ変換するレシピである

Managed Resource は cloud provider の具体的な resource に近い層です。

一方で、XRD と XR は利用者に見せる API の層です。

Composition は、その二つをつなぎます。

この関係を押さえると、Crossplane を「OCI resource を YAML で作る仕組み」としてだけでなく、「組織向けの Platform API を作る仕組み」として見やすくなります。

次は、Composition の中身、特に Patch and Transform や Composition Functions を使って、XR の入力をどのように Managed Resource へ渡すのかを見ていきます。


参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?