マルチテナントとKubernetesクラスタの単位について注意したポイント

ここまでKubeVirtの技術について説明しました。ここからはヤフーで評価用にシステム設計を行った際に、注意したポイントなどをお話ししたいと思います。システム設計の検討項目のポイントですが、まずはマルチテナントとKubernetesクラスタの単位についてお話しします。

マルチテナントとKubernetesクラスタの単位ですが、KubeVirtクラスタに限らず、Kubernetes基盤を設計する際にテナンシーの確保をどうするかが、さまざまな設計箇所に影響してくると思います。

aとbに書いているとおり、テナント単位に独立したKubernetesクラスタを払い出すという方式と、1つのKubernetesクラスタを複数のテナントで共有して、Namespaceをテナントに割り当てる方式が考えられます。

ヤフーでは、既存のIaaS基盤はOpenStackのクラスタが200以上立っていて、コントロールプレーンの運用負荷が高いのが1つ課題になっています。そのため、コントロールプレーンを減らして運用負荷を軽減できるのかは1つ重視したポイントです。スライドの一番下に書いてあるように、bのテナント単位にNamespaceを割り当てる、払い出す方法で、問題なく運用できるかを検討しました。

テナントへの払い出しの単位の差のメリット・デメリット

テナントへの払い出しの単位の差について、メリット・デメリットを表にまとめています。まず左側のaの「テナント単位にKubernetesクラスタを払い出し」と書いてある部分を見ていきます。メリットは、Kubernetesの下の層でテナンシーを確保できるため、Kubernetesでテナンシーの考慮が不要という点です。また、なにかクラスタで問題が起きても、障害時の影響範囲を最小化できるのも大きな要素かと思います。

一方でデメリットとしては、コントロールプレーンの運用負荷がどうしても高くなる問題はあります。あとはサーバーの利用効率も低くなってしまう問題もあります。

次に、右側のbのテナント単位にNamespaceを払い出す仕組みについて見ていきます。メリットについては、複数テナントを1クラスタに集約可能なので、運用負荷を大幅に削減できるという話と、サーバーの利用効率が高いという話を書いています。これが今回期待しているポイントです。

一方でデメリットを3点書いています。1点目はKubernetesのコントロールプレーンのテナント間のリソース隔離を検討する必要があります。基本的にはNamespace・リソースの隔離はできていますが、ホストのリソースなどテナントのユーザーがそのままアクセスできるとまずいものもあったりします。これに関しては、Multi-Tenancy SIGで検討している確認項目やチェックツールを利用できると思っています。

2点目はコントロールプレーンのAPIの負荷集中という話を書いています。複数のテナントでコントロールプレーンを共有するので、こういった負荷集中がどうしても起きてしまいます。特に、eventの情報が膨らむ話があったりすると思います。こちらに関しては、記載しているとおり、レートリミットの設定をする仕組みや、保存先を分離する仕組みも使えるかなと思っています。

3点目にVMの性能面の隔離を書いています。複数のテナントでオーバーコミットなどを行い1つのノードを共有していると、高い性能を求めるVMの運用が難しくなります。CPUに関してはKubernetesの機能で対応可能ですが、IOなどはちょっと難しかったりもします。ただ、こちらもKubernetesの機能のPodNodeSelectorを使って、特定のテナント用のノードを用意しておけば、対策としては大丈夫なのかなと思いました。

以上のように、bのテナント単位にNamespaceを払い出す案で問題になりそうなポイントは対処できるので、こちらでマルチテナントを運用可能かなと思いました。

CNIプラグインの選定

次にCNIプラグインの選定についてお話ししたいと思います。KubernetesのネットワークはCNIとServiceなどのリソースで構成されています。システムを設計しようとする際に、このCNIに関する部分がけっこう複雑だなと思いました。CNIはPodの接続方式を提供しますが、その方式によって利用できるアクセラレーションの種類が決まったりします。

そのほかにも、CNIはそもそもの仕様でCNIから別のCNIを呼び出すチェイニングのような仕組みが用意されています。これを活用して、一部のCNIプラグインはほかのプラグインと組み合わせて活用するようなパターンなども提供されています。

そのほか別の観点では、Service type LoadBalancerでMetalLBを使いたいと思ったときに、BGPをMetalLBも使うので、CNIでBGPを使うときは重なってしまい、うまくいかないなどのケースもあります。こういった感じで、1つの要素を重視するとほかの実現が難しくなるような、難しいパズルのような印象を受けました。

プラグインの選定で重視した要件とそれぞれの対策案

プラグインの選定に関してヤフーで重視した要件を説明します。IaaSの環境ということで、2つの要件を重視しました。

1点目はクラスタ外からVMにアクセスするためのIPの固定機能と、L4でのサービス公開機能です。外部システムやネットワーク機能の連携のために、IPを固定する機能がどうしても必要になってきます。また、コンテナ環境とは異なり、HTTP以外のサービスを提供するものも多数あったりします。

2点目は大規模トラフィックへの対応を書いています。100Gbpsレベルのものを想定します。この規模のトラフィックをサーバーのCPUで処理すると、本来VMに使いたいCPUのリソースが、裏側のネットワーク処理のために使われてしまいます。そのため、ハードウェアの機能を使ってオフロードできることが要件となってきます。CNIのプラグインとしては、下に書いてあるものを候補に検討していきました。

最初の要件ですが、3つの方式案を考えました。1つはCalicoの接続方式と言ったほうが伝わりやすいかもしれませんが、BGPでVM・Podのアドレスを外部に経路広告する方式です。当然、BGPを利用できるプラグインに限定されます。また、先に説明したとおり、1つのKubernetesクラスタを複数のテナントで共有する仕組みで設計を考えているので、外部システムとの連携用に使用するIPを、VMのライフサイクルとは別にテナント内で確保し続けたい要件も出てきます。テナント単位のIP予約機能などがあると、これが実現できると考えました。

2点目はLBのIPを利用する方式です。外部LBとNodePortの組み合わせを考えました。LBがDSRでなければ、LBのIPは外部アクセス用のIPとして使えると思っています。ただ、NodePortのデフォルトのレンジが2,700程度までしか外部からのアクセス用にポートを利用できず、さまざまなテナントでサービスを公開していった際に厳しいかなと思いました。ポートのレンジは設定可能ですが、ここを大きくしすぎた際にほかの機能への影響がちょっと測りきれないなと思い、この方式は難しいと判断しました。

3点目、こちらもLBですが、Service type LoadBalancerを活用する方式です。ただ、今回はオンプレの環境で基盤構築を検討しているため、Service type LoadBalancerの実体をどう用意するかもポイントになります。社内の既存のLBとのインテグレーションをやるか、またはMetalLBなどを用意するか考えましたが、Service type LoadBalancerの運用そのものが1つ大きな運用負荷になるので、これを前提としたシステム構成は難しいということで、プロジェクトのリソースの都合上、ちょっと選択できない案となりました。

以上の検討結果から、1点目の案のBGPを使った方式で進むことになりました。プラグインとしてはCalicoかCiliumといった感じです。

次に2点目の要件の大規模トラフィック対応について考えました。先ほど話していたように、100Gbpsレベルのトラフィックを扱うには、ネットワーク処理をハードウェアにオフロードできるかが重要なポイントとなってきます。

既存のIaaSのOpenStackではOVS(Open vSwitch)を利用した仮想ネットワークの提供方法が一般的で、SmartNIC(OVS)と書いている、OVSのオフロード対応のSmartNICのノウハウがチームにありました。そのため、こちらを活用したいと考えていました。

SmartNICのOVSですが、吹き出しに書いてあるように、OVSを利用するCNIのプラグインがあれば透過的にオフロードの機能を利用できる仕組みとなっています。ただ、そもそもOVSベースのCNIのプリグインはかなり限られています。今回見た中ではAntreaであれば対応可能でしたが、AntreaはBGPに対応しておらず、クラスタ外からVMに到達するためのIPの固定の実現が難しくなります。以上の理由から、SmartNIC(OVS)の活用はいったん断念して進める結論になりました。

ここまで検討結果のまとめです。2つあった要件のうち、前者のクラスタ外からVMに到達するためのIPの確保・固定は実現可能で、後者の大規模トラフィック対応は断念というかたちになっています。CalicoとCiliumの2つのプラグインの方法がありましたが、BGPの対応状況や実績、あとIP予約機能を考慮してCalicoを選択することにしました。

ここまで説明したとおり、複数の観点を考えてCNIプラグインを選定する必要があり、通常のPodを利用するコンテナ基盤でもCNIのプラグイン選定は難しいと思いますが、IaaS基盤だと重視するポイントが微妙に異なっていて、ますます難しい印象を受けました。

CNIのプラグイン選定で検討・評価できなかった部分

今回のCNIのプラグイン選定で、検討・評価できなかった部分もまとめておきます。1点目は、先ほどから話している、クラスタ外からVMに到達するためのIPについてです。全体を検討したあとですが、そもそもサービスのClusterIPを使う簡単な方式にすれば、Calicoの独自拡張に頼る必要がなくなり、CNI選定の幅が広がると思いました。

2点目はeBPF対応のSmartNICの活用です。CNIプラグインはOVS対応のものよりeBPF対応のものが多いので、OVS対応のCNIを探すよりは、こちらのほうが選択肢の幅も広がるのかなと思いました。

3点目は、今回検討を断念したService type LoadBalancerです。吹き出しに書いてあるとおり、時間制約が厳しく、CNI選定については十分に検討できなかった箇所が多いと思っています。これらを考慮すると、また違う結論になるのかなと思います。

KubeVirtクラスタのスケーラビリティ

KubeVirtクラスタのスケーラビリティについてもお話しします。KubeVirtクラスタのスケーラビリティが十分か、という検討項目になります。別のスライドでも説明したとおり、コントロールプレーンの数を減らしたい目的があるので、1つのKubeVirtクラスタで扱われるノード数が十分か、確認を行う必要がありました。

クラスタあたりの限界ノード数の見積もりですが、KubeConでSIG Scalabilityの方が発表した参考になるデータがあり、こちらをもとに試算してみました。発表ではPodあたりコンテナ数2つ以下の条件で、1つのKubernetesクラスタあたりノードのPodが110の場合、1,300ノードぐらいが限界。ノードのPodが30ぐらいの場合、5,000ノードぐらいが限界というデータになっています。

これをKubeVirtに当てはめた際に、先ほどお話ししたとおり、KubeVirtではVM単位にvirt-launcherというコンテナが1つ起動して、VM自体はAPIサーバーやkubeletには直接アクセスしない仕組みになっています。そのため、元データのPodあたりのコンテナ数は1と考えてよさそうかなと思いました。

そうすると2倍程度のノード数まで対応できそうなため、1ノードに110VM起動するようなケースで、2,600ノードまでは1クラスタで管理可能なように考えられます。仮にCPUのオーバーコミット率を5倍で考慮しても520ノードまでは管理可能で、OpenStackと比べて同等以上のノード数に対応可能なので、スケーラビリティの観点では問題ない結論に至りました。

利用者向けにケアが必要なポイントと基盤管理者視点の懸念点

最後ちょっと利用者向けにケアが必要なポイントも話します。VMの作成時に、KubeVirtのマニフェストを書くのはけっこう大変だという話が出ました。OpenStackは、CLI、コマンドラインで2~3コマンド叩いてVMを起動する方式が一般的だったり、GUIでVMを作る人が多かったりします。そのため「OpenStackと比べるとVM作成の敷居が高い」といったコメントが出ました。

そのため、ユーザー提供するにはUXの観点でちょっと工夫が必要かなと思います。代表的な構成のテンプレート群を用意しておくとか、kubectl runみたいなジェネレータのCLIを用意するとか、パブクラのようなWeb UIを用意するなどかなと思います。

それから、基盤管理者視点のコメントです。IaaSとCaaSの基盤はいずれか一方でも複雑なのに、両方扱うのは範囲が広すぎて対応可能なメンバーが限られるのではないかというコメントも出ました。確かに技術をわかっている人から見ると両方できて楽しそうだと思いますが、両方扱うのが難しすぎる話ももっともだなと思いました。

v1.0がリリースされればより安心できる技術になるのでは

最後まとめです。KubeVirtについては、Kubernetesの仕組みをうまく利用できるように作られています。システム設計のポイントは、まずマルチテナントをどう実現するかがポイントになります。Namespace単位でも、テナント隔離のためにさまざまな機能を利用できます。あと、IaaSの用途では、クラスタ外からVMに到達するためのIPの確保方法がポイントになります。

それから、SmartNICなどのハードウェアのオフロード機能を活用したい場合は、eBPFのオフロードを検討したほうがよいと思います。あとは一般的な話ですが、CNIの選定は複雑で、検討期間も長く必要だなと思いました。

KubeVirtでのIaaS管理に関する全体的な印象ですが、KubernetesのコントロールプレーンとKubeVirtと組み合わせて、IaaS基盤は構築・提供可能だと思います。ただ、OpenStackのようにこれまで積み重ねられたきめ細かい機能というのはなく、要件次第な部分もあるかと思いました。

汎用的なIaaS基盤としてOpenStackからマイグレーションするには、まだ機能や実績の少なさに不安を覚える感じです。ただ、v1.0がリリースされればさまざま実績が出てきて、より安心して使える技術になっていくのかなと思いました。以上になります。

質疑応答

司会者:たくさん質問が来ているのでいくつか質問します。「Podが消費するリソース、CPUメモリはKubernetesで管理されると思いますが、VMを起動することで消費されるリソースとの兼ね合いはどのようになっているのでしょう?」。

相良:それは確かに難しい問題ですね。すみません、今は答えを持っていません。

司会者:ありがとうございます。では次です。「ノード障害時のVMの可用性、VMware HAのようなものはどのように検討されましたか?」。

相良:VMware HAのような機能は、KubernetesのPodでも同じだと思いますが、自動でKubernetesの仕組みで対応できる感じになっています。VMが消えれば、ほかの場所で勝手に上げてくれます。

司会者:ありがとうございます。では、発表ありがとうございました!

相良:ありがとうございました。