Kubernetesへの機能追加にかかわった話と、そこから得た知見

はじめに

こんにちは、Necoプロジェクトsatと申します。

みなさんはKubernetesに機能が追加されるまでの流れをご存知でしょうか。githubに存在するプロジェクトであれば典型的にはfeature request用のissueが立てられて、それをもとにPRが作られてレビューを経たのちにマージという流れです。しかしKubernetesはたくさんのプロジェクトから構成される非常に複雑なシステムなので、このような単純なやりかたが難しいのです。KubernetesではそのかわりにKubernetes Enhancement Proposal(以下KEPと表記)というしくみを使って新機能を開発するというスタイルをとっています。

本記事はKEPについて簡単に説明した後に、Kubernetesの機能開発が進んでいく具体的な流れについて、NecoプロジェクトがレビューにかかわったKEPを通して紹介します。

KEPとは

Kubernetesに新機能を追加しようとした場合、まずは所定の形式に沿ってkubernetes/enhancementsというプロジェクトへのPRという形でKEPを発行します。まずは機能追加の要否やデザインの良し悪しについて関係者のレビューを受けて、レビューが通れば晴れて実装可能な状態となります。

KEPの役割はこれで終わりません。みなさんはKubernetesがリリースされるたびに「〇〇機能がbetaからGAになった」などの文言を見ることがあると思いますが、各機能のalpha,beta,GAという成熟度もKEPを介して更新されます。

kubernetes/enhancementsを見ると現在Kubernetesにどんな機能が提案されているのか、それぞれの開発状況はどうなっているのか、などの情報が得られるので、興味のあるかたはフォローしてみるとよいでしょう。

本記事ではKEPそのものについてのしくみについてはこれ以上述べませんが、以下の記事、およびそこから参照されるドキュメントが参考になるので、ご興味のある方はごらんください。

qiita.com

KEPにかかわるようになったきっかけ

NecoプロジェクトはTopoLVMというローカルストレージ用のCSIドライバを作っています。TopoLVMはNeco専用の特殊なものではなく、Kubernetesでローカルストレージを扱いたい人であればだれでも恩恵を受けられるものだったので、あるときKubernetesのslackの中でストレージについての話題を扱うsig-storageというチャネルで紹介をしました。これに対してpmem-csiという不揮発性メモリ用のCSIドライバの開発者であるPatrick Ohlyさんというかたが興味を持ってくれたのがすべての始まりです。

彼が注目したのはTopoLVMが持つ、ノードのストレージ空き容量を考慮してPodをスケジューリングするという機能です。この機能については以下記事の"TopoLVMの特徴"という節をごらんください。

blog.cybozu.io

我々がsig-storageでTopoLVMを紹介したとき、偶然にもpmem-csiではちょうど同様の機能を開発中だったのです。

github.com

さらに彼はこの機能をドライバ独自のものではなくKubernetesの標準的な機能として実装したいと考えていたため、以下のKEPを発行していました。

github.com

このような事情から、上記KEPに対して、この機能についての知見を持っている我々のコメントが求められたというわけです。

どのようなKEPか

本KEPの目的は、次のようなことをKubernetesの標準機能として提供することです。

  • 各ストレージシステムが空き容量についての情報をAPIサーバに見える形で提供する
  • スケジューラは上記の情報を参考にして、可能な限りボリュームの割り当てに成功するよう考慮してPodをスケジュールする(さもなくばPodはスケジュールできない状態になる)

本KEPはTopoLVMやpmem-csiなどのノードローカルストレージだけではなく、クラウドサービスにおけるゾーンローカルストレージなど、より多くの種類のストレージシステムに対応できるようになっています。

我々にコメントが依頼された時点でのKEPは次のようなものでした。

  • 以下2種類のボリュームについて考慮する
  • 各ストレージシステムの空き容量を管理するためのCSIStoragePoolというKubernetesのリソースを追加する
  • ephemeral volumeのサイズ情報を標準化する
  • 上記の情報を使ってPodをスケジュールするようスケジューラを拡張する

Ephemeral volumeはなじみのない機能かもしれないので簡単に説明しておきます。KubernetesにおいてCSIドライバが提供するボリュームは通常永続化されており、Persistent VolumeとPersistent Volume Claimという2つのリソースによって管理されています。そしてボリュームのライフライクルはPodとは独立しています。しかし、Podと同じライフライクルを持つボリュームが欲しいというユースケースがあります。Ephemeral Volumeはこのようなときのために使うものであり、Podの生成と同時に作成され、かつ、Podの終了と共に削除されます。

次節から本KEPに対して具体的にどのようなコメントがあって、かつ、それがどのようにKEPに反映されたかについて記載します。

我々によるコメント

前節において述べたKEPに対して我々からいくつかのコメントをしました。そのうちの主だった3つについてここでは紹介します。

User Storiesが弱い

KEPには、新機能によって誰がどのようなことをできるようになるかを書くUser Storiesという項目があります。我々がレビューした当時、ここにはpmem-csiについてしか書かれていませんでした。これでは本KEPによって利益を受けるユーザが相当限られてしまうと思った我々は、TopoLVMのようなローカルストレージやネットワーク経由で接続されたストレージなどをここに追加してはどうかと提案しました。

幸いにもこの提案は受け入れられ、User Storiesは充実しました。

空き容量の大きさによる優先順位付け

本KEPでやろうとしていることは十分なストレージ空き容量が存在するノードにPodをスケジュールするという単純な機能だけでした。その一方で、TopoLVMではこれに加えて空き容量が多いノードにPodを優先的にスケジュールするという機能(以下、優先順位付け機能と記載)も備えていました。この機能には、各ノードのストレージが均等に消費されていくため、Podの分散配置やボリューム作成後のノードのリサイズがしやすいといった利点があります。これを踏まえて我々は優先順位付け機能をKEPに盛り込んではどうだろうかと提案しました。

この提案については、彼から「KEPをできるだけ単純なものに保って、その後に次第によくしていきたい」という回答がありました。この意見には我々も異論がなかったので、提案を取り下げました。

ephemeral volumeのサイズに関するもの

現在のephemeral volumeにはサイズを指定する標準的な方法がなく、サイズ指定をする方法はドライバに任されています。しかし本KEPはephemeral volumeも考慮に入れているため、ephemeral volumeのサイズ標準化(以下簡単のため"サイズ標準化"と記載)が前提条件となります。そこでサイズ標準化も同じKEP内でやってしまおう、というのが当時の状況だったのですが、このやりかたには次のような問題がありました。

  • サイズ標準化は、これ自身でKEP発行に値する独立した機能と考えられる
  • ephemeral volumeの仕様が複雑怪奇なため、仮にこのKEPでサイズ標準化しようとすると影響範囲が巨大化する

我々はこれらの問題について指摘した上で、ephemeral volumeについては本KEPではそもそも対象外としてはどうかという提案をしました。

この提案についてはsig-storageのメンテナでもあるMichelle Auさんの意向もあって、サイズ標準化は別KEPとして分離されました。

github.com

ただしephemeral volumeの考慮は削除されずに残りました。つまり本KEPはサイズ標準化用の新たなKEPに依存するようになったということです。

それ以外のコメント

我々のコメントの前後に別の開発者からも次のような様々なコメントがあり、それらに従ってKEPは洗練されていきました。

  • 他のKEPとの重複排除
  • User Storiesの追加
  • CSIStoragePoolのデータ構造の変更
  • その他矛盾の解消

上記のような過程を経て、PR発行から二か月程度後についに本KEPは実装可能段階になりました。これに伴ってテスト計画成熟度を上げる基準ための定義*2がKEPに追加されました。

その後の流れ

この後は実装を粛々と進めるだけ…と思いきや、そうは問屋が卸しません。ソフトウェア開発の経験が豊富なかたほど想像しやすいとおもいますが、設計を終えた後に実装段階で初めて明らかになる問題というものが多々あります。本KEPもその例外ではなく、実装開始時点からさまざまな問題が噴出し、現在は実装を一時中断している状態になっています。

検出された問題をすべてを詳しく説明していてはきりがないので、ここではそのうち重要なものについて軽く触れておきます。

  • ストレージの都合でスケジューラのコア部分に手を入れるのに強い反対が起きたため、TopoLVMも使っているscheduler extenderなどの他の方法による実現方法を探さざるをえなくなった
  • ephemeral volumeの現状の設計がまずいために、これ以上機能追加するよりも設計段階から作り直すほうがよいのではないかということになった(関連する議論)
  • そもそもPodスケジュール時にボリュームの割り当てに失敗するとにスケジューリング不可能になるバグを修正すべきだということになった(関連issue)

興味のあるかたは関連情報を追ってみてください。

おわりに

我々は本件を通して初めてKEPのプロセスにかかわったことによって、次のような知見を得ました。

  • KEPプロセスそのもの。今後我々自身がKEPを発行する際はそれほど手間取らないはず
  • ephemeral volumeの仕様などの本件に関連する技術
  • Kubernetesの機能追加に必要な能力。関係者を説得するための広範な知識、ステークホルダーを巻き込む能力、およびそれを継続させる精神的なタフさなど
  • KEPによるKubernetesの変更は少なくとも数か月、場合によっては一年以上を要するため、なんらかの機能がすぐに必要なのであればKEP以外の方法で実現するのが得策であること

本記事によって我々の知見がみなさまに一部なりとも共有できたのであれば幸いです。

*1:機能名はドキュメントごとに表記の揺れが激しいのですが、ここでは"ephemeral volume"と記載します

*2:これこれの基準を満たせばalphaからbetaになれる、など