proxy-config の数百行を表として読む方法
一言でいうと
サイドカーのクラスター名は、방향|포트|서브셋|호스트(プレースホルダーは方向、ポート、サブセット、ホストです)の4つの欄で、規則どおりに作られます。DestinationRuleのサブセット1つがクラスター1つになり、統計もエラーメッセージも、すべてこの名前を付けて出てきます。名前を読めれば、proxy-configの出力数百行が、表に見えてきます。
なぜ必要なのか
istioctl proxy-config clusters <파드>(プレースホルダーはPod名です)を初めて開くと、こんな行が延々と出てきます。
outbound|9080||reviews.default.svc.cluster.local
outbound|9080|v1|reviews.default.svc.cluster.local
outbound|9080|v2|reviews.default.svc.cluster.local
inbound|9080||
この名前を読めないと、2つのことができません。1つ目は、「v2へ行くリクエストが、なぜ503なのか」を見るときに、v2サブセットのクラスターがそもそもあるのか、エンドポイントがいくつあるのかを確認できないことです。2つ目は、ダッシュボードのcluster.outbound|9080|v2|…upstream_rq_503のようなメトリクスが、どのサービスの何なのか、わからないことです。Istioは、数千のクラスターを人の手なしで作らなければならないので、名前を規則で決め、その規則がそのまま読み方になります。
どう動くのか
| 欄 | 値 | 空になる場合 |
|---|---|---|
| 方向 | outbound(このPodが他を呼ぶとき) / inbound(他がこのPodを呼ぶとき) |
なし |
| ポート | サービスポート(9080) |
なし |
| サブセット | DestinationRuleのsubsets[].name |
サブセットを選ばないデフォルトのクラスター |
| ホスト | サービスのFQDN | 入ってくる側(自分のアプリへ送るから) |
istiodは、メッシュのサービス・ポートごとに、サブセットのないクラスターを常に作り、DestinationRuleにサブセットがあれば、サブセットごとにもう1つずつ作ります。サブセットクラスターのエンドポイントは、同じサービスのエンドポイントのうち、ラベルが合うものだけを絞り込んだ部分集合です。そのため、ラベルのないPodは、どのサブセットクラスターにも入りません。
VirtualServiceのdestination: {host: reviews, subset: v1}は、ルートがoutbound|9080|v1|reviews…クラスターを指す形に変換されます。ここで、よくある事故が出ます。DestinationRuleにないサブセットを指すと、istiodは、存在しないクラスターを指すルートを送り込みます。Envoyは、動的に受け取ったルートのクラスターを事前に確認しないので(validate_clustersのデフォルトがfalse)、設定は受け入れられ、リクエストが来たときに503が出て、アクセスログにNC(no cluster)が出力されます。ファイルで書いた静的設定は、デフォルトがtrueなので、同じ設定を起動時に拒否します。同じミスが、どこで表に出るかが違うのです。
統計は、cluster.<이름>.<지표>(プレースホルダーはクラスター名とメトリクスです)として積まれます。|の入った名前は、Prometheusのラベルに移すときに面倒なので、メッシュ設定のoutboundClusterStatNameにパターンを与えると、istiodが各クラスターにalt_stat_nameを付けます。ルーティングは元の名前で行い、統計名だけが変わります。
現場での姿
カナリアを設定したら、v2へ行くリクエストだけがすべて503。VirtualServiceを先にデプロイし、DestinationRuleを後でデプロイした場合です。その間の数秒から数分、v2サブセットのクラスターがありません。proxy-config clustersにv2の行があるかを、まず見ます。そのため、順序は常にDestinationRuleが先、VirtualServiceが後です。
サブセットクラスターのエンドポイントが0個。名前はあるのに、proxy-config endpointsが空なら、サブセットのラベルとPodのラベルがずれています(version: v2対version: 2.0)。このとき、レスポンスフラグはNCではなくUH(健全なアップストリームなし)なので、フラグの2文字だけで、「クラスターがない」のか「クラスターはあるが空」なのかを見分けられます。
ダッシュボードが突然空になった。誰かがメッシュ設定のoutboundClusterStatNameを変えると、統計名がまるごと変わって、古い名前で組んだクエリがすべて空になります。ルーティングは問題ないので、ずいぶん後になって見つかります。
公式ドキュメント: Debugging Envoy and Istiod・DestinationRule
次のラボですること
DestinationRuleを書き、規則でクラスター名を4つ導出して、その名前のままEnvoyを立て、サブセットごとにリクエストを分けてみます。統計名をalt_stat_nameで変え、ないサブセットを指して503とno_clusterを作り、サブセットが同じエンドポイントの部分集合であることを、/clustersで数えます。