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

Istio深化 — なぜそう流れるのか

何が何を担当するのか

TT Labで続きを見る

一言でいうと

「どこへ送るか」を決めるのがVirtualServiceで、「送った後でどう扱うか」を決めるのがDestinationRuleです。カナリアデプロイに両方が必要な理由が、これです。

なぜ必要なのか

Istioを初めて使うと、たいていこの間違いをします。

# VirtualService 만 쓴 카나리 — 동작하지 않는다
http:
  - route:
      - destination: { host: shop, subset: v1 }
        weight: 90
      - destination: { host: shop, subset: v2 }
        weight: 10

subset: v1が何を指すのか、誰にもわかりません。サブセットはDestinationRuleで定義します。

# DestinationRule — 서브셋의 정의
spec:
  host: shop
  subsets:
    - name: v1
      labels: { version: v1 }
    - name: v2
      labels: { version: v2 }

これでようやく、v1がversion: v1ラベルの付いたPodを意味するようになります。前のコースで見たEnvoyの用語に置き換えると、DestinationRuleのsubsetがクラスターを作り(outbound|8080|v1|shop...)、VirtualServiceのweightがルートの重みになります。

4つのリソース

リソース 役割 Envoyでは
Gateway メッシュの外から入ってくるトラフィックの入口(ポート・ホスト・TLS) Listener
VirtualService どのリクエストをどこへ送るか(マッチ・重み・リトライ・タイムアウト) Route
DestinationRule 宛先をどう扱うか(サブセット・LB・コネクションプール・外れ値・TLS) Cluster
ServiceEntry メッシュが知らない外部サービスをリストに登録 Cluster + Endpoint

Gatewayは入口を開くだけです。Gateway1つではトラフィックは流れません。そのGatewayをgateways:で参照するVirtualServiceがあって初めて、ルーティングが生まれます。これもよくある落とし穴です。

mTLSはいつ掛かるのか

PeerAuthenticationがmodeを決めます。

mode 意味
PERMISSIVE 平文もmTLSも受け付けます(デフォルト、移行用)
STRICT mTLSだけを受け付けます
DISABLE mTLSを使いません

デフォルトがPERMISSIVEなのは、サイドカーのないPodが残っていることがあるからです。そのため、「Istioを入れたから暗号化される」という言い方は間違いです。STRICTに変えるまでは、平文もそのまま通ります。

STRICTに変えるときによく壊れるもの: サイドカーのないPod(例: Job)、ヘルスチェックを送るkubelet、そしてメッシュの外の監視。kubeletは、Istioがプローブのパスを迂回させて処理しますが、自作のチェックスクリプトは壊れます。

設定が実際にプロキシに届いたかを確認する

Istioで最もよくある状況は、YAMLは適用されたのに、動作が変わらないことです。コントロールプレーンが受け入れたものと、サイドカーが持っているものは、違うことがあるので、確認はプロキシ側で行います。

istioctl proxy-status                 # 각 프록시가 최신 설정과 동기인지
istioctl analyze -n prod              # 설정끼리의 모순을 정적으로 찾는다
istioctl proxy-config routes deploy/frontend -n prod
istioctl proxy-config cluster deploy/frontend -n prod --fqdn api.prod.svc.cluster.local

proxy-statusがSTALEなら、そのプロキシは古い設定で動いています。SYNCEDなのに動作が違うなら、設定そのものが意図と違うので、routesとclusterを直接読みます。

VirtualServiceには、付く場所が必要です。hostsに書いた名前が実際のサービスと違っていたり、gatewaysを書かなかったために、メッシュの内側にだけ適用されたりするケースが多いです。ゲートウェイから入るトラフィックに適用するには、そのゲートウェイの名前を明示する必要があり、別のネームスペースのゲートウェイなら、네임스페이스/이름と書きます(プレースホルダーはネームスペースと名前です)。

DestinationRuleのサブセットは、ラベルであって、デプロイではありません。subset: v2は、その名前のラベルを持つPodを指すだけです。Deploymentを新しく作るときにラベルを付けなければ、サブセットは空の宛先になり、リクエストは503に落ちます。proxy-config endpointで、実際のアドレスがいくつあるかを確認するのが、最も早いです。

istioctl proxy-config endpoint deploy/frontend -n prod | grep api

適用の順序があります。同じホストにVirtualServiceが複数あると、ルールはマージされず、先に作られたものが勝ちます。チームごとに1つずつ作っていると、他のチームのルールが、静かに無視される状況が生まれます。ホスト1つにリソース1つを原則にし、パスごとに分けたいなら、1つのリソースの中で分けます。

mTLSを厳格にする前に、何が平文で来ているかを見ます。PeerAuthenticationをSTRICTに変えた瞬間、サイドカーのないワークロードと、Kubernetesのヘルスチェックの一部が切れます。まずPERMISSIVEのままにして、テレメトリーで平文の割合が0になるのを確認してから、厳格にします。

よくある勘違い

「Istioを入れればオブザーバビリティが得られる」というのは勘違いです。サイドカーが出すメトリクスは、L7のリクエストメトリクス(リクエスト数・レイテンシ・ステータスコード)です。アプリケーションの中で何が起きたかは、依然としてわかりません。トレースも同じで、サイドカーはスパンを作りますが、アプリケーションがヘッダーをつないであげないと、チェーンが切れます。コードを直さなくてよいわけではありません。

実務で本当に大切なこと

設定が意図どおりに届いたかは、プロキシに尋ねます。

istioctl analyze                     # 정적 검사 — 서브셋 미정의 같은 것을 잡는다
istioctl proxy-status                # 각 사이드카가 최신 설정을 받았나(SYNCED)
istioctl proxy-config route <pod>    # 실제로 받은 라우트
istioctl proxy-config cluster <pod> --fqdn shop.default.svc.cluster.local

proxy-statusがSTALEなら、設定がまだ届いていないということで、そのときYAMLをいくら見ても無駄です。