はじめに
Kubernetes Cluster Inventory API(KEP-4322)で導入されたClusterProfileリソースを見ると、properties
やcredentialProviders
といったフィールドがspec
ではなくstatus
に定義されています。この記事では、なぜこのような設計になっているのか、Kubernetesのspec vs statusの設計思想から解説します。
ClusterProfileの例
まず、ClusterProfileがどのような構造になっているか見てみましょう。
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ClusterProfile
metadata:
name: some-cluster-name
namespace: fleet-system
labels:
x-k8s.io/cluster-manager: some-cluster-manager
spec:
displayName: some-cluster
clusterManager:
name: some-cluster-manager
status:
version:
kubernetes: 1.28.0
properties:
- name: clusterset.k8s.io
value: some-clusterset
- name: location
value: apac
conditions:
- type: ControlPlaneHealthy
status: True
lastTransitionTime: "2023-05-08T07:56:55Z"
message: ""
- type: Joined
status: True
lastTransitionTime: "2023-05-08T07:58:55Z"
message: ""
credentialProviders:
- name: google
cluster:
server: https://connectgateway.googleapis.com/v1/projects/123456789/locations/us-central1/gkeMemberships/my-cluster-1
ご覧の通り、properties
、credentialProviders
のフィールドがstatus
セクションに配置されています。
なぜstatusなのか?
Kubernetesのspec vs statusの設計思想
この議論の背景には、Kubernetesの公式な設計ガイドラインがあります。sig-architectureが定めたAPI Conventionsに、spec vs statusの使い分けが明確に記載されています。
Mike Morrisさんによる解説
sig-architectureのspec vs statusについて、Gateway APIのメンテナーであるMike Morrisさんがとてもわかりやすく解説しています。
here's the official guidance on spec vs status, note that spec is described as "desired state", i.e. typically a request from a user, whereas status is used to communicate "actual state", often updated by a controller watching the resource
重要なポイント:
- spec: "desired state"(望ましい状態) = ユーザーからのリクエスト
- status: "actual state"(実際の状態) = コントローラーが更新する現実の状態
ClusterProfile設計者の意図
ClusterInventory APIを提案したqiujian16さんも、他の方がspecに追加のフィールドを設けようとした際に、次のようにコメントしています。
I would think this should be in the status updated by the cluster manager, the user should not own this field, right?
statusに記述する理由の具体例
statusに記述されているフィールドは、ユーザーの希望(spec)ではなく、Cluster Managerが検出・確定して報告する結果(status) です。
credentialProvidersの場合
もしcredentialProviders
がspec
に書いてあったらどうなるでしょうか?
コントローラーは「クラスタを修正し、そのcredentialで認証できるようにする」必要があります。つまり、ユーザーが指定したcredentialに合わせてクラスタ側を変更する、という動作になってしまいます。
しかし実際には、クラスタにアクセスするためのcredentialは既に存在する事実であり、コントローラーがそれを検出して報告するべき情報です。
propertiesの場合
もしproperties
がspec
に書いてあったらどうなるでしょうか?
コントローラーは「その属性をクラスタへ付けてあげる」必要があります。
例えば:
- クラスタのregionは実際には東京に作成されている
- ClusterProfileの
properties
でregion: osaka
と指定する - →コントローラーはそのクラスタを大阪に移動しなければならない!?
これは明らかに不合理です。ClusterProfileはクラスタを変更するためのAPIではなく、クラスタの情報を提供してくれるリソースだからです。
ClusterProfileを管理するCluster Managerは人間が担当できるのか?
回答: Yes
KEP-4322のTerminologyセクションでは、Cluster Managerを次のように定義しています。
Cluster Managerの定義:
- ClusterProfileを最新の状態に保つエンティティ
- メンバクラスタにアクセスして情報を取得し、ClusterProfile APIリソースの状態を更新できる十分な権限を持つべき
この定義から、人間でもシステムでも、これらの条件を満たせればCluster Managerになれると解釈できます。
実用上の課題
ただし、KEPには次のように書かれています:
Cluster Manager: An entity that creates the ClusterProfile API object per member cluster, and keeps their status up-to-date
「常に最新の状態に保つ」というのは手動では大変です。そのため、できればある程度自動化した方が良いでしょう。
例えば:
- クラスタがHealthyかどうかをチェックするスクリプトを定期的に動かす
- 結果を
conditions
に反映する
人間がCluster Managerになるシナリオ
なぜ人間でも良いと考えるのでしょうか?
Cluster APIやEKSなどを使わず、VM上に直接手動で構築されたクラスタの場合、そのクラスタを指すためのリソースが存在しません。
このような場合、ClusterProfileを手書きして登録する、というシナリオが考えられます。
Project Sveltosを使った実装例
例えば、Project SveltosというCDツールを利用すると、YAMLに記述したsubresourceまで通しでapplyすることができ、このようなケースも楽に達成できます。
まとめ
ClusterProfileのproperties
、credentialProviders
などがstatus
に定義されている理由は:
- これらはユーザーが望む状態(desired state)ではなく、実際の状態(actual state)だから
- Cluster Managerが検出・報告する情報であり、ユーザーが指定してクラスタを変更するものではないから
- ClusterProfileはクラスタを変更するAPIではなく、情報を提供するリソースだから
Kubernetesの設計思想である「spec = desired state、status = actual state」という原則に従った設計です。