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

ICA — Istio認定アソシエイト

ルーティング規則を設計する

TT Labで続きを見る

目標

VirtualServiceとDestinationRuleの役割を手で切り分け、マッチルールの順序とAND/OR結合が、実際のルーティング結果をどう変えるかを身につけます。

なぜ重要なのか

ICAの出題比重の40%が、トラフィック管理です。ところが、この領域での実務の事故は、ほとんどが文法ではなく役割分担を知らないために生じます。「v2へ10%送る」ことはVirtualServiceが行いますが、「v2とは何か」はDestinationRuleが定義します。どちらか一方だけを作ると、Envoyの中には行き先のないルートや、誰も参照しないクラスターが残り、結果は503です。

ルールの順序も同じです。Istioは最初のマッチで評価を止めるので、包括的なルールを上に置くと、その下のルールは永遠に実行されません。逆に、最後にcatch-allがないと、予想外のリクエストがNRに落ちます。この2つは、コードレビューで捕まえるべき項目であり、そのためには目になじませておく必要があります。

このラボでは、Kubernetesの基本リソースは実際にapplyし、Istio CRDは/root/ica-traffic/の下にファイルとして作成します。ラボのクラスターにIstioのCRDがインストールされていないためであり、試験で求められる能力も「マニフェストを正確に書くこと」だからです。

ステップ

  1. ネームスペースica-trafficを作成し、ラベルistio-injection=enabledを付けてください。
  2. ネームスペースica-trafficに、Deployment reviews-v1とreviews-v2を、それぞれレプリカ1つでデプロイしてください。2つのPodテンプレートはどちらもラベルapp=reviewsを持ち、reviews-v1はversion=v1を、reviews-v2はversion=v2を、追加で持つ必要があります。イメージはnginx:1.27-alpineを使ってください。
  3. 同じネームスペースにService reviewsを作成してください。ポートは9080、ポート名はhttp、selectorはapp=reviewsだけを使います。
  4. /root/ica-traffic/dr-reviews.yamlにDestinationRule reviewsを作成してください。spec.hostはreviews.ica-traffic.svc.cluster.local、subsetsはv1(labels version: v1)、v2(labels version: v2)の順です。
  5. /root/ica-traffic/vs-reviews-weight.yamlにVirtualServiceを作成してください。spec.hosts[0]はreviews.ica-traffic.svc.cluster.localで、httpルール1つにdestinationを2つ置き、subset v1にweight 90、subset v2にweight 10を指定します。
  6. /root/ica-traffic/vs-reviews-header.yamlにVirtualServiceを作成してください。ルールは2つです。最初のルールは、ヘッダーx-qa-userがtrueのリクエストをsubset v2へ送り、2番目のルールは、matchなしでsubset v1へ送ります。
  7. /root/ica-traffic/vs-reviews-rewrite.yamlにVirtualServiceを作成してください。uri.prefixが/api/v2/のリクエストのパスを/に書き換えて、subset v2へ送ります。redirectは使わないでください。
  8. /root/ica-traffic/vs-reviews-final.yamlに、名前がreviews-finalのVirtualServiceを作成してください。ルール3つを順に置きます。(1)ヘッダーx-qa-user: trueならv2、(2)uri.prefixが/api/v2/で、かつmethod.exactがGETならv2、(3)matchのないcatch-allはv1。

参考

メッシュに組み込むネームスペースを作成する

ネームスペースica-trafficを作成し、ラベルistio-injection=enabledを付けてください。

ネームスペースを作るだけでは、サイドカーは注入されません。自動注入を有効にするラベルをもう1つ付ける必要があります。ラベルのキーはistio-injectionです。

バージョンのラベルが異なる2つのDeploymentをデプロイする

ネームスペースica-trafficに、Deployment reviews-v1とreviews-v2を、それぞれレプリカ1つでデプロイしてください。2つのPodテンプレートはどちらもラベルapp=reviewsを持ち、reviews-v1はversion=v1を、reviews-v2はversion=v2を、追加で持つ必要があります。イメージはnginx:1.27-alpineを使ってください。

2つのDeploymentのPodが同じServiceにまとまるには、共通のラベル(app)が同じである必要があり、subsetで分かれるには、区別するラベル(version)が異なる必要があります。ラベルは、Podテンプレート側にあって初めて意味を持ちます。

2つのバージョンをまとめるServiceを作成する

同じネームスペースにService reviewsを作成してください。ポートは9080、ポート名はhttp、selectorはapp=reviewsだけを使います。

Serviceのselectorにversionを入れると、1つのバージョンだけが対象になり、重みによる分配ができなくなります。バージョンの区別は、Serviceではなく、DestinationRuleの役割です。ポート名も、プロトコルが分かるように付けてください。

subsetを定義する

/root/ica-traffic/dr-reviews.yamlにDestinationRule reviewsを作成してください。spec.hostはreviews.ica-traffic.svc.cluster.local、subsetsはv1(labels version: v1)、v2(labels version: v2)の順です。

subsetのlabelsは、Podのラベルと文字どおりに同じである必要があります。食い違うと、クラスターはできるのにエンドポイントが0個になり、503 UHに遭遇します。hostは、短い名前ではなくFQDNで書いてください。

90/10の重みによる分配

/root/ica-traffic/vs-reviews-weight.yamlにVirtualServiceを作成してください。spec.hosts[0]はreviews.ica-traffic.svc.cluster.localで、httpルール1つにdestinationを2つ置き、subset v1にweight 90、subset v2にweight 10を指定してください。

重みは、route配列の各destinationに付きます。合計が100になる必要があり、subset名は、ステップ4で作ったものと正確に同じである必要があります。

ヘッダーベースのルーティングとcatch-all

/root/ica-traffic/vs-reviews-header.yamlにVirtualServiceを作成してください。ルールは2つです。最初のルールは、ヘッダーx-qa-userがtrueのリクエストをsubset v2へ送り、2番目のルールは、matchなしでsubset v1へ送ってください。

ルールは上から下へ評価され、最初にマッチしたものが勝ちます。ヘッダー条件が付いたルールを先に、matchがまったくないルールを最後に置いてください。exactの値は文字列です。

URIプレフィックスの書き換え

/root/ica-traffic/vs-reviews-rewrite.yamlにVirtualServiceを作成してください。uri.prefixが/api/v2/のリクエストのパスを/に書き換えて、subset v2へ送ってください。redirectは使わないでください。

rewriteはリクエストをプロキシしながらパスを変え、redirectはクライアントに3xxを返します。このステップで必要なのは、バックエンドに気づかれないようにパスを変えるほうです。

3つのルールを1つのVirtualServiceにまとめる

/root/ica-traffic/vs-reviews-final.yamlに、名前がreviews-finalのVirtualServiceを作成してください。ルール3つを順に置いてください。(1)ヘッダーx-qa-user: trueならv2、(2)uri.prefixが/api/v2/で、かつmethod.exactがGETならv2、(3)matchのないcatch-allはv1。

最も具体的なルールが一番上、包括的なルールが一番下です。パスとメソッドをANDで結ぶには、matchの項目を2つ作らず、1つの項目の中に2つの条件を並べて置いてください。