KubernetesとgRPCと負荷分と
Kubernetesは、Serviceリソースを通じてコネクションレベルの負荷分散を提供します。
一方で、gRPCはHTTP/2上に構築されており、HTTP/2は長寿命なコネクションを利用し続けます。
コネクションレベルの負荷分散では、コネクションの確立時にのみ分散が考慮され、確立されたコネクション内ではリクエストは同じバックエンドにのみ送られ続けます。つまり、3つのバックエンドがあり、それぞれに1つずつコネクションが張られている場合、「コネクションレベル」では完璧に分散されているように見えますが、実際にはリクエストレベルでは分散が行われていないことになります。
これを解決する方法としていくつか方法があります
- クライアントに負荷分散を実装する* gRPCサーバーのIPアドレスを取得し、負荷を考慮して宛先を決定する処理をgRPCクライアント側に実装します。
- KubernetesではPodは頻繁に再作成されIPアドレスも頻繁に入れ替わるため、APIサーバーに問い合わせることで最新のPodのIPアドレス一覧を更新し続ける必要があります。
- L7プロキシをクライアントのPodへサイドカーとして挿入する* Envoyやnginxをサイドカーとして挿入し、プロキシ側に負荷分散してもらう
- サービスメッシュ* istio, linkerd, cilium
- istio, linkerdはサイドカーとしてL7プロキシを挿入してその子らに負荷分散をしてもらう。
- knative* なんかHTTP/2のロードバランシングしてくれる機能があるらしい・・・