TT Lab
はじめる
学ぶ 学習パス コース

Envoyの内部構造

503 はルートではなくクラスタの言葉だ

TT Labで続きを見る

一言でいうと

ルートはクラスター名までしか言いません。その名前の後ろにアドレスがいくつ立っているか、どうやって知るか、そのうち何が健全か、健全なものが足りなければどうするか、そのすべてをクラスターが決めます。

なぜ必要なのか

「ルートは合っているのに503が出ます」という報告は、ルーティングの問題ではありません。ルートが指したクラスターに、送れる先がないという意味です。そのため、プロキシを運用していて実際によく見る画面は、ルート表ではなくクラスターの一覧です。どのクラスターにサーバーが何台あり、そのうち何台が健全か、です。

ここで2つを区別する必要があります。エンドポイントを知る方法とそのうち何が健全かを判断する方法は、別の軸です。前者はクラスターのtypeで、後者はヘルスチェックです。2つを混ぜて考えると、「DNSから外れたのに、なぜまだ送るのか」のような疑問で道に迷います。

どう動くのか

エンドポイントを知る4つの方法。

type 方法 使う場面
STATIC 設定にアドレスをそのまま書く アドレスが固定のとき
STRICT_DNS 名前を定期的に解決し、応答に含まれるアドレスをすべてエンドポイントにする ヘッドレスServiceのように複数のアドレスが返るとき
LOGICAL_DNS 解決結果のうち1つだけを使い続ける 接続を長く維持する大きな相手(例: 外部API)
EDS コントロールプレーンがリストを送り込む サービスメッシュ。Podが起動・停止するたびに更新

健全かどうかを判断する2つの方法。この2つは向きが反対です。

2つは排他的ではありません。一緒に使うと、「つついて確かめることで事前に除き、それでも漏れるものは結果で除く」になります。/clustersのhealth_flagsには、それぞれ別の表示が出ます。アクティブ検査の失敗は/failed_active_hcです。

健全なものが足りないとき。Envoyには2つの仕組みがあります。

1つ目はパニックモードです。健全な割合がしきい値(デフォルト50%)を下回ると、健康情報を無視してすべてに送ります。初めて見ると奇妙ですが、判断は単純です。検査のほうが間違っている可能性があるのにどこにも送らなければ確実に障害になり、送れば一部だけでも生き残れます。起きたかどうかは、cluster.<이름>.lb_healthy_panic(プレースホルダーはクラスター名です)の統計で見ます。この数字が上がっているなら、負荷分散はすでに意味を失った状態です。

もう1つは優先度です。エンドポイントのグループごとにpriorityを指定すると、普段は優先度0だけを使い、優先度0の健全な割合が下がった分を、優先度1が受けます。優先度0が全滅すると、すべてが優先度1へ行きます。別のリージョンの予備サーバーを普段は遊ばせておき、障害のときだけ使う構成が、こうして作られます。

現場での姿

「DNSから外したのに、まだそのサーバーへ行きます」という場合です。STRICT_DNSは定期的に解決し直しますが、その周期が過ぎるまでは古いリストを使います。LOGICAL_DNSなら、さらに長く保持し続けることがあります。外す作業と反映される時点の間に時間があることを前提に、作業の順序を組む必要があります。

「ヘルスチェックを有効にしたら、バックエンドのCPUが上がりました」という場合です。プロキシ20台が1秒ごとにつつくと、サーバーから見れば毎秒20回の追加リクエストです。間隔とプロキシの数を一緒に計算し、ヘルスチェックのパスを軽くします(データベースに触れないパスにします)。

パニックモードを誤解する場合。「全部死んでいるのに、なぜ送り続けるのか」という疑問が出ます。統計を見れば答えが出ています。このとき直すべきなのはEnvoyではなく、ヘルスチェックのしきい値かバックエンドです。

公式ドキュメント: Service discovery・Health checking・Cluster configuration

次のラボですること

エンドポイントが3つのクラスターを作り、名前で探すクラスターをもう1つ置き、アクティブヘルスチェックが故障した1つを外すのを確認します。その後、すべてが故障したクラスターでパニックモードを、優先度を付けたクラスターで予備段階への切り替えを、それぞれ確認し、最後に4つのクラスターの一覧表を統計から取り出して作ります。