本セッションの登壇者
セッション動画
このセッションでは、Kubernetesの仕組みやそもそも論みたいなところから、デモをまじえてお話ししていきます。
手元に立てたクラスタのデモをお見せします。まず、いくつかコマンドを打つとエラーになります。Kubernetesを触ったことのある方はお気付きだと思いますが、このエラーの出方は非常に奇妙です。なぜなら、PodやDeploymentが何も登録されていない場合であれば、「No resources found(リソースが見つからない)」と言ってくるはずだからです。今回のエラーメッセージは「サーバにそんなリソースタイプが存在しない」なので、接続先の正体は普通のKuberentesではないようです。

ここで、バージョンを見るとその正体が分かります。サーババージョンは1.28.1ですが、+kcp
と入っていますね。接続先はこのkcpで、KubernetesのAPIサーバーのようなふりをしながら、Pod、Deployment、Nodeといった実体を持つリソースについては何も知らないという、いわば特殊なクラスタです。今日はこのkcpについてお話しします。

Kubernetes の本質
Deploymentを作成した時、表から見るとkubectl
をすることでデプロイが行われ、図の下側に書いたノードにコンテナが立つ仕組みになっています。

中で何が行われているかをおさらいしておきましょう。内部的には、複数のControllerが担当のリソースを監視してアクションしています。

たとえば、DeploymentController
はDeploymentをウォッチしていて、DeploymentができたらReplicaSet
を作る。ReplicaSetController
はReplicaSet
ができたらPod
を作る。Kubelet
はPod
ができたらコンテナを立てる。そしてデフォルトのControllerはcontroller-manager
の中に含まれている、というのが基本的なKubernetesの仕組みです。たとえば、途中でコンテナが1つ足りなくなった、つまりKubeletがPodを見て3つあるはずなのに実際には2つしかない場合は、1個追加で立てようとします。

いわば各Controllerが自分の担当の「何か」を監視して、差分があればリアクティブに「何か」するというのが、Kubernetesの基本的な大原則、一番抽象的な形で語った時の動きの仕組みです。

このことをReconciliation Loopと言います。Reconciliationとはもめごとの仲裁、調停をするという意味です。現状と理想的な状態の間に差が生まれた時に、それを合わせにいく動作がループ的に回っているというのが、Kubernetesの基本的な構造です。

プラットフォームを作るためのプラットフォーム
これはコンテナに限った話ではありません。同じ考え方はコンテナ以外にも応用できて、CustomResourceDefinition(CRD)と呼ばれます。KubernetesはCRDによる拡張の仕組みを持っていて、DeploymentやReplicaSetやPod以外にも、自分で好きなリソースとCRUD APIを定義してAPIを増やせる仕組みになっています。自前のリソース用のカスタムコントローラーが自前のリソースを継続的に監視していて、何かあれば対応するアクションを行うという仕組みです。この仕組みはとても広く使われていて、Kubernetes-nativeなOSSのデファクトスタンダードになっています。cert-managerであれば、ロードバランサができた時に対応する証明書をLet's Encryptからもらってきて設定する、Vitessであれば、データベースのインスタンスを管理するというところで、リソースを監視しつつ、継続的にアクションをとる仕組みが生かされているわけです。

このことから、KubernetesはPlatform of Platforms、つまり「プラットフォームを作るためのプラットフォーム」という呼ばれ方をすることがあります。

Controllerの置きどころが悩ましい
では、これをケーススタディで具体的に見てみましょう。すごく単純化していますが、写真を共有するサービスを展開する例です。すでにいろいろなアプリが載っている社内共通基盤のKubernetesクラスタが存在し、アプリ側もある程度Kubernetes-nativeな書き方の知見はあるとします。プライベートクラウドにある共通基盤のS3互換ストレージを使います。

社内チームの責務の構造は図のとおりです。インフラチームがクラスタの管理、アプリチームが写真共有アプリ本体の開発、ストレージチームが内製のストレージサービスの開発と、インスタンスを振り出したり払い出したりするリソース管理をします。書籍『チームトポロジー』の用語で言うと、上から順にPlatform チーム、Stream Aligned チーム、Complicated Subsystemチームという役割に相当します。

そこで、ストレージのBucketの払い出しをCustomResourceDefinition(CRD)にしたら、kubectlでできるのではないかということで、ここをセルフサービス化していきます。

難しいのはControllerの置き方です。権限と責務を分割する際に一番分離度が高いControllerの管理方法としては、アプリごとにクラスタを分けるという手があります。しかし、それをやるとクラスタ数が線形に増えていくので、たいていはインフラチームが死にます。もう少し穏当な方法だと、KubernetesはNamespaceで分割する機能を持っているので、Namespaceでチームごとに分けて、Controllerはアプリ側に置けます。ただ、そうするとアプリ側がControllerの運用をやることになるのでアプリチームが死ぬ。では、Namespaceを分けて、Controllerはストレージチームが管理することにすると、Controllerのバージョンアップなどの際に全アプリと調整する必要が出てきて、調整コストでストレージチームが死ぬ。

結論としては、誰かが死にます。
こういった問題意識のもとに現れたのが、今回紹介するkcpです。

kcpは2023年9月にCNCFで3段階ある一番下の成熟度のSandboxに入りました。最初のデモでお見せしたように、kcpはKubernetesのAPIサーバーのように振る舞う「何か」です。

またkcpについては先日のKubeCon EU 2024でも発表されました。

APIプラットフォームのためのフレームワーク
kcpの目指すものは、APIプラットフォームを作るためのフレームワークです。CRUD APIの管理だけに特化したAPIサーバーだと考えることができ、Pod やVolume、Nodeなどのいわゆるコンピューティングの実体を持つリソースは定義されていません。逆に何があるのかというと、責務を分離できる設計になっています。大きくは2つ機能があって、階層構造のワークスペースが定義できることが一つ、もう一つは、APIを提供する側と使用する側で分離して、別々のリソースを割り当てることができる仕組みになっています。

図解するとこのようになります。複数チームで1つのクラスタをインフラチームが管理し、ツリー構造に root があって、app があって、その下にチャットアプリと写真共有アプリがあって、rootの直下にストレージとDBチームがあるとします。kcpが提供するのは赤で表示された部分です。占有領域で囲われたところにデプロイされたリソースは原則不可視になります。

デモで見てみます。kubectlのプラグインとして機能が提供されていて、workspace
というサブコマンドを入力すると今rootにいることが分かります。たとえば、kubectl workspace create app
と入力するとapp
が作成されます。同様にphoto
も作成します。戻ってrootにstorage
を作成します。このようにツリー構造を定義できます。

実際に定義されたものはこのようになります。ここから storage の中で適当なconfigmapを作ったとすると、使う側のphoto Workspaceからはconfigmapは見えません。

提供する側と使う側の分離についてですが、kcpには APIResourceSchema、APIExport、APIBinding の3つがあります。たとえばBucket作成APIを定義する側のストレージチームがstorage WorkspaceにAPIResourceSchemaの定義を置き、APIExportによってそれを参照します。使う側はAPIBindingを定義してAPIExportを参照し、最終的にkubectlでBucketが作成できるようになるという仕組みになっています。おもしろいのはAPIResourceSchemaとAPIExportが分かれていることによって、複数バージョンのControllerをデプロイすることができるので、APIの実体とゲートウェイみたいな形でバージョンの管理ができることです。今は実装されていませんが、後々ブルーグリーンやローリングアップデートなども定義される予定です。

まとめです。Kubernetesはコンテナに留まらない基盤になっています。実際の操作方法としては、CustomResourceに対するReconciliationを行います。ただ、これをやると、特に今回の例のようにインフラ・アプリ以外に共通サービスチームがある時などにControlerの置き所に困ります。この問題を解決するために、kcpはAPIプラットフォームの構築に特化していて、APIを公開する側と使用する側で、リソース的にもバージョン的にも分離できる仕組みを提供しています。

この仕組みによって、kcpはただのプラットフォームのためのプラットフォームから一歩進んで、APIのためのプラットフォームを目指しているプロダクトである、というのが今回のお話でした。ありがとうございました。
