はじめに
世の中にはすごいエンジニアや、よりよい物を作ろうと工夫しているエンジニアがたくさんいます。しかもその工夫や苦労をネットに公開してくれていることさえあります。
本になっているわけではないので体系的に学ぶことはできないのですが、そこで考えた工夫やエッセンス、調査内容は必ず誰かの糧になると思います。この記事では私が「読む価値がある!」と思った記事を引用しながら、自分の考えを追加して理解を深めていこうというものです。
今回紹介する記事
素晴らしい記事をありがとうございます!
背景
Entrainという世界的なスポーツベッディングにおけるAWSでのkubernetes利用時の課題です。ユーザはリアルタイムのイベントに対して賭けを行い、イベントの結果に応じて配当がきまるのでUXはレイテンシーに直結します。
課題
AWSのスポットインスタンスとKubernetesを利用してマイクロサービスを運用しているが、マイクロサービス間でのgRPCのロードバランシングに以下の課題があった
- (予想) インスタンス間のEast-West通信が多く発生し大きいインスタンスタイプを用意する必要があった(本文には書いてないがおそらくこういう意味だと思われる)
- k8sのServiceでのロードバランシングは単純なラウンドロビンである振り分け先の状態を気にしないため、大量のトラフィックを捌くことに向いておらずノードをスケールアウトをしてもリクエストを想定以下しか捌けなかった
- AZ跨ぎのk8sクラスタではAZ間通信によるレイテンシーやコストが問題になった(AWSではAZ跨ぎの通信に課金がされる、ロケーションが異なるのでレイテンシーが発生する)
解決策
- Linkerdを導入した(OSSのServiceMesh)
- LinkerdにはgRPC対応の負荷分散機能があり、リッチな負荷分散ができた
- k8sのServiceによるLBはラウンドロビンを使っているがLinkerdはExponentially weighted moving average(指数加重移動平均) Beyond Round Robin: Load Balancing for Latency | Linkerdと呼ばれるレイテンシーベースでの分散を行ってくれるので問題になっていたAZ間通信を抑えることができた
- Istioも検討したが、Istioを管理するだけでチームが必要になりそうだった
- その点、Linkerdは簡単だったしCRDも少なかった
学び
- AZ跨ぎのレイテンシーをServiceMesh内のバランシングの仕組みで解決するナレッジを得た
- ServiceMesh=Istioであったが、やりたいことに応じて選択の必要性を改めて感じた
- Linkerdは簡単という認識になった
- Exponentially weighted moving average(指数加重移動平均)はLinkerdではPeak-EWMA(ぴーくゆま)と呼ばれる機能、kube-proxyをバイパスしてPodから直接Serviceに通信できる。
- ロジックとして振り分け先へのRTTの移動平均を持ち、最小となる相手に分散を行うので、ラウンドロビンやリースとコネクションよりもパーセンタイルごとのレイテンシーが低くなる傾向にある。
Beyond Round Robin: Load Balancing for Latency | Linkerd
- gRPC(HTTP/2)における負荷分散について軽く調べたところ以下の記事が見つかった。この記事ではHTTP/2が長寿的なコネクションの確立であるため、負荷が分散されづらいことに提言している。
- サービスメッシュとしてLinkerdを導入するに至った経緯 - ANDPAD Tech Blog
- HTTP/2ではL7の世界でコネクションと呼ばれるものを貼り、その中で複数のファイルをやり取りするためのストリームを作成する。そのため1つのコネクションの中でたくさんのHTTPリクエストが送られることになる
- すると 宛先 A / B / C にk8sのServiceでコネクションを貼る際に分散を行ったとしても、それぞれのコネクションを流れるHTTPリクエストの量にばらつきがあれば、真の意味で負荷分散がされているとは言えない。
- なのでより正確に分散するのであればHTTPリクエスト単位で分散ができる必要があるのでL7のgRPCを解釈できるProxy/LBが必要になる
- こんな記事も見つけた gRPCでのLoad Balancing - Carpe Diem