トラフィック管理
Istioのトラフィックルーティングルールを使用すると、サービス間のトラフィックとAPI呼び出しの流れを簡単に制御できます。Istioは、サーキットブレーカー、タイムアウト、再試行などのサービスレベルのプロパティの構成を簡素化し、A/Bテスト、カナリアリリース、パーセンテージベースのトラフィック分割による段階的ロールアウトなどの重要なタスクを簡単に設定できます。また、依存サービスまたはネットワークの障害からアプリケーションをより強固にするのに役立つ、すぐに使える信頼性機能も提供します。
Istioのトラフィック管理モデルは、Envoyプロキシに依存しており、これはサービスと一緒にデプロイされます。メッシュサービスが送受信するすべてのトラフィック(データプレーントラフィック)はEnvoyを介してプロキシされるため、サービスに変更を加えることなく、メッシュ周辺のトラフィックを簡単に方向付けおよび制御できます。
このガイドで説明されている機能の動作の詳細に関心がある場合は、アーキテクチャの概要でIstioのトラフィック管理の実装について詳しく知ることができます。このガイドの残りの部分では、Istioのトラフィック管理機能を紹介します。
Istioトラフィック管理の紹介
メッシュ内のトラフィックを方向付けるには、Istioはすべてのエンドポイントとその所属サービスを認識する必要があります。独自のサービスレジストリに情報を追加するために、Istioはサービスディスカバリシステムに接続します。たとえば、KubernetesクラスタにIstioをインストールした場合、Istioはそのクラスタ内のサービスとエンドポイントを自動的に検出します。
このサービスレジストリを使用すると、Envoyプロキシは関連サービスにトラフィックを方向付けることができます。ほとんどのマイクロサービスベースのアプリケーションには、サービストラフィックを処理するために、各サービスワークロードの複数のインスタンス(ロードバランシングプールと呼ばれることもあります)があります。デフォルトでは、Envoyプロキシは、プールからランダムに選択された2つのホストのうち、アクティブなリクエストが少ないホストに各リクエストをルーティングする最小リクエストモデルを使用して、各サービスのロードバランシングプール全体にトラフィックを分散します。このようにして、最も負荷の高いホストは、他のホストと負荷が同じになるまでリクエストを受信しません。
Istioの基本的なサービスディスカバリとロードバランシングにより、動作するサービスメッシュが得られますが、Istioの機能はそれ以外にもはるかにあります。多くの場合、メッシュトラフィックに対してより詳細な制御が必要になる場合があります。A/Bテストの一環として、特定の割合のトラフィックを新しいバージョンのサービスに送信したり、サービスインスタンスの特定のサブセットのトラフィックに異なるロードバランシングポリシーを適用したりする場合があります。また、メッシュへの入出トラフィックに特別なルールを適用したり、メッシュの外部依存関係をサービスレジストリに追加したりする場合もあります。Istioのトラフィック管理APIを使用して、独自のトラフィック構成をIstioに追加することで、これらすべてを行うことができます。
他のIstio構成と同様に、APIはKubernetesカスタムリソース定義(CRD)を使用して指定され、例に示すようにYAMLを使用して構成できます。
このガイドの残りの部分では、各トラフィック管理APIリソースとその使用方法について説明します。これらのリソースは
このガイドでは、APIリソースに組み込まれているネットワークの回復力とテスト機能の概要も示します。
仮想サービス
仮想サービスと宛先ルールは、Istioのトラフィックルーティング機能の主要な構成要素です。仮想サービスを使用すると、Istioとプラットフォームによって提供される基本的な接続と検出に基づいて、Istioサービスメッシュ内のサービスへのリクエストのルーティング方法を構成できます。各仮想サービスは、順に評価される一連のルーティングルールで構成され、Istioは与えられた各リクエストを仮想サービスからメッシュ内の特定の実際の宛先に一致させます。ユースケースに応じて、メッシュには複数の仮想サービスが必要な場合もあれば、不要な場合もあります。
仮想サービスを使用する理由
仮想サービスは、Istioのトラフィック管理を柔軟で強力にする上で重要な役割を果たします。クライアントがリクエストを送信する場所と、リクエストを実際に実装する宛先ワークロードを厳密に切り離すことで実現します。また、これらのワークロードへのトラフィック送信のためのさまざまなトラフィックルーティングルールを指定するための豊富な方法も提供します。
なぜこれほど便利なのでしょうか?仮想サービスがない場合、Envoyは、はじめに説明したように、すべてのサービスインスタンス間で最小リクエストロードバランシングを使用してトラフィックを分散します。ワークロードに関する知識を使用して、この動作を改善できます。たとえば、一部は異なるバージョンを表している場合があります。これは、異なるサービスバージョンのパーセンテージに基づいてトラフィックルートを構成したり、内部ユーザーからのトラフィックを特定のインスタンスセットに送信したりする必要があるA/Bテストで役立ちます。
仮想サービスを使用すると、1つ以上のホスト名に対してトラフィック動作を指定できます。仮想サービスのルーティングルールを使用して、Envoyが仮想サービスのトラフィックを適切な宛先に送信する方法を指定します。ルートの宛先は、同じサービスの異なるバージョンまたは完全に異なるサービスにすることができます。
一般的なユースケースは、サービスサブセットとして指定されたサービスの異なるバージョンにトラフィックを送信することです。クライアントは、仮想サービスホストが単一のエンティティであるかのようにリクエストを送信し、Envoyは仮想サービスのルールに応じてトラフィックを異なるバージョンにルーティングします(例:「20%の呼び出しを新しいバージョンに送信する」、「これらのユーザーからの呼び出しをバージョン2に送信する」)。これにより、たとえば、新しいサービスバージョンに送信されるトラフィックの割合を徐々に増やすカナリアリリースを作成できます。トラフィックルーティングはインスタンスデプロイメントから完全に分離されているため、新しいサービスバージョンを実装するインスタンスの数は、トラフィックルーティングを参照せずにトラフィック負荷に基づいてスケールアップおよびスケールダウンできます。対照的に、Kubernetesなどのコンテナオーケストレーションプラットフォームは、インスタンスのスケーリングに基づいたトラフィック分散のみをサポートしており、すぐに複雑になります。Istioを使用したカナリアデプロイメントで、仮想サービスがカナリアデプロイメントにどのように役立つかについて詳しく読むことができます。
仮想サービスを使用すると、次のようなこともできます。
- 単一の仮想サービスを介して複数のアプリケーションサービスに対処します。たとえば、メッシュがKubernetesを使用している場合、特定の名前空間内のすべてのサービスを処理するように仮想サービスを構成できます。単一の仮想サービスを複数の「実際の」サービスにマッピングすることは、サービスのコンシューマーが移行に適応する必要なく、モノリシックアプリケーションを個別のマイクロサービスで構築された複合サービスに変換する上で特に役立ちます。「
monolith.com
のこれらのURIへの呼び出しはmicroservice A
に送信する」など、ルーティングルールで指定できます。これは、以下の例で確認できます。 - インバウンドおよびアウトバウンドトラフィックを制御するために、ゲートウェイと組み合わせてトラフィックルールを構成します。
場合によっては、サービスサブセットを指定する宛先ルールを構成する必要もあります。これらは、仮想サービス間でクリーンに再利用できるサービスサブセットやその他の宛先固有のポリシーを指定する場所です。宛先ルールについて詳しくは、次のセクションをご覧ください。
仮想サービスの例
次の仮想サービスは、リクエストが特定のユーザーから来たかどうかによって、リクエストをサービスの異なるバージョンにルーティングします。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v3
hostsフィールド
hosts
フィールドには、仮想サービスのホスト、つまりこれらのルーティングルールが適用されるユーザーがアドレス指定できる宛先がリストされます。これは、クライアントがサービスへのリクエストを送信するときに使用するアドレスです。
hosts:
- reviews
仮想サービスのホスト名は、IPアドレス、DNS名、またはプラットフォームによっては、暗黙的または明示的に完全修飾ドメイン名(FQDN)に解決される短い名前(Kubernetesサービスの短い名前など)にすることができます。ワイルドカード("*")プレフィックスを使用することもでき、これにより、すべての一致するサービスに対して単一のルーティングルールセットを作成できます。仮想サービスのホストは、実際にはIstioサービスレジストリの一部である必要はありません。単なる仮想的な宛先です。これにより、メッシュ内にルーティング可能なエントリを持たない仮想ホストのトラフィックをモデル化できます。
ルーティングルール
http
セクションには、仮想サービスのルーティングルールが含まれており、ホストフィールドで指定された宛先(複数可)に送信されるHTTP/1.1、HTTP2、およびgRPCトラフィックの照合条件とアクションを記述しています(tcp
およびtls
セクションを使用して、TCPおよび未終了のTLSトラフィックのルーティングルールを構成することもできます)。ルーティングルールは、トラフィックの送信先となる宛先と、ユースケースに応じて0個以上の照合条件で構成されます。
一致条件
例にある最初のルーティングルールには条件が含まれているため、match
フィールドから始まります。この場合、このルーティングをユーザー「jason」からのすべてのリクエストに適用したいので、headers
、end-user
、exact
フィールドを使用して適切なリクエストを選択します。
- match:
- headers:
end-user:
exact: jason
宛先
routeセクションのdestination
フィールドは、この条件に一致するトラフィックの実際の宛先を指定します。仮想サービスのホストとは異なり、宛先のホストは、Istioのサービスレジストリに存在する実際の宛先である必要があります。そうでなければ、Envoyはトラフィックの送信先を認識しません。これは、プロキシを持つメッシュサービス、またはサービスエントリを使用して追加されたメッシュ外のサービスにすることができます。この例では、Kubernetes上で実行されており、ホスト名はKubernetesサービス名です。
route:
- destination:
host: reviews
subset: v2
このページの他の例と同様に、ここでは簡潔にするため、宛先ホストにKubernetesの短い名前を使用しています。このルールが評価されると、Istioはルーティングルールを含む仮想サービスの名前空間に基づいてドメインサフィックスを追加し、ホストの完全修飾名を取得します。例で短い名前を使用することで、任意の名前空間でコピーして試すことができます。
destinationセクションでは、このルールの条件に一致するリクエストを送信する、このKubernetesサービスのどのサブセットを指定します。この例では、v2という名前のサブセットです。サービスサブセットの定義方法については、以下のデスティネーションルールに関するセクションを参照してください。
ルーティングルールの優先順位
ルーティングルールは、上から下へ順番に評価され、仮想サービス定義の最初のルールが最優先されます。この例では、最初のルーティングルールに一致しないものはすべて、2番目のルールで指定されたデフォルトの宛先に送信されます。そのため、2番目のルールには照合条件がなく、トラフィックをv3サブセットに直接送信します。
- route:
- destination:
host: reviews
subset: v3
各仮想サービスの最後のルールとして、このようなデフォルトの「条件なし」ルールまたはウェイトベースのルール(以下で説明)を提供することをお勧めします。これにより、仮想サービスへのトラフィックには常に少なくとも1つの一致するルートが確保されます。
ルーティングルールについて詳しく
上記のように、ルーティングルールは、特定のトラフィックのサブセットを特定の宛先にルーティングするための強力なツールです。トラフィックポート、ヘッダーフィールド、URIなど、トラフィックの照合条件を設定できます。たとえば、この仮想サービスでは、ユーザーは、http://bookinfo.com/.
のより大きな仮想サービスの一部であるかのように、ratingsとreviewsという2つの個別のサービスにトラフィックを送信できます。仮想サービスルールは、リクエストURIに基づいてトラフィックを照合し、適切なサービスにリクエストを直接送信します。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
http:
- match:
- uri:
prefix: /reviews
route:
- destination:
host: reviews
- match:
- uri:
prefix: /ratings
route:
- destination:
host: ratings
一部の照合条件では、正確な値、プレフィックス、または正規表現を使用して選択することもできます。
同じmatch
ブロックに複数の照合条件を追加して条件をANDで連結したり、同じルールに複数のmatchブロックを追加して条件をORで連結したりできます。任意の仮想サービスに対して複数のルーティングルールを持つこともできます。これにより、単一の仮想サービス内でルーティング条件を自由に複雑または簡素化できます。照合条件フィールドとその可能な値の完全なリストは、HTTPMatchRequest
リファレンスにあります。
照合条件を使用することに加えて、パーセンテージ「重み」でトラフィックを分散させることができます。これは、A/Bテストとカナリアリリースに役立ちます。
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 75
- destination:
host: reviews
subset: v2
weight: 25
ルーティングルールを使用して、トラフィックに対していくつかのアクションを実行することもできます。たとえば、
- ヘッダーを追加または削除します。
- URLを書き換えます。
- この宛先への呼び出しに対してリトライポリシーを設定します。
使用可能なアクションの詳細については、HTTPRoute
リファレンスを参照してください。
宛先ルール
仮想サービスとデスティネーションルールは、Istioのトラフィックルーティング機能の重要な部分です。仮想サービスは、トラフィックを特定の宛先にどのようにルーティングするかを定義するものと考えることができます。そして、デスティネーションルールを使用して、その宛先のトラフィックに何が起こるかを構成します。デスティネーションルールは、仮想サービスのルーティングルールが評価された後に適用されるため、「実際の」宛先のトラフィックに適用されます。
特に、デスティネーションルールを使用して、名前付きサービスサブセット(たとえば、特定のサービスのすべてのインスタンスをバージョン別にグループ化など)を指定します。次に、これらのサービスサブセットを仮想サービスのルーティングルールで使用して、サービスの異なるインスタンスへのトラフィックを制御できます。
デスティネーションルールを使用すると、宛先サービス全体または特定のサービスサブセットを呼び出す際のEnvoyのトラフィックポリシー(優先ロードバランシングモデル、TLSセキュリティモード、サーキットブレーカー設定など)をカスタマイズすることもできます。デスティネーションルールのオプションの完全なリストは、デスティネーションルールリファレンスを参照してください。
ロードバランシングオプション
デフォルトでは、Istioは最小リクエストロードバランシングポリシーを使用しており、リクエストはリクエスト数が最小のインスタンスに分散されます。Istioは、特定のサービスまたはサービスサブセットへのリクエストに対して、デスティネーションルールで指定できる次のモデルもサポートしています。
- ランダム:リクエストは、プール内のインスタンスにランダムに転送されます。
- 加重:リクエストは、特定のパーセンテージに従って、プール内のインスタンスに転送されます。
- ラウンドロビン:リクエストは、各インスタンスに順番に転送されます。
- 整合性ハッシュ:HTTPヘッダー、Cookie、その他のプロパティに基づいて、ソフトセッションアフィニティを提供します。
- リングハッシュ:Ketamaアルゴリズムを使用して、アップストリームホストに整合性ハッシュを実装します。
- Maglev:Maglev論文で説明されているように、アップストリームホストに整合性ハッシュを実装します。
各オプションの詳細については、Envoyロードバランシングドキュメントを参照してください。
宛先ルールの例
次の例では、my-svc
宛先サービスに対して、異なるロードバランシングポリシーを持つ3つの異なるサブセットを構成するデスティネーションルールを示しています。
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: my-destination-rule
spec:
host: my-svc
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: v3
labels:
version: v3
各サブセットは、1つ以上のlabels
に基づいて定義されます。Kubernetesでは、これはPodなどのオブジェクトに添付されたキー/値のペアです。これらのラベルは、Kubernetesサービスのデプロイメントでmetadata
として適用され、異なるバージョンを識別します。
サブセットを定義することに加えて、このデスティネーションルールには、この宛先のすべてのサブセットに対するデフォルトのトラフィックポリシーと、そのサブセットのみに対してそれをオーバーライドするサブセット固有のポリシーの両方があります。subsets
フィールドの上で定義されているデフォルトポリシーは、v1
およびv3
サブセットにシンプルなランダムロードバランサーを設定します。v2
ポリシーでは、対応するサブセットのフィールドにラウンドロビンロードバランサーが指定されています。
ゲートウェイ
ゲートウェイを使用して、メッシュの送受信トラフィックを管理し、メッシュに出入りさせるトラフィックを指定できます。ゲートウェイ構成は、サービスワークロードとともに実行されているサイドカーEnvoyプロキシではなく、メッシュのエッジで実行されているスタンドアロンのEnvoyプロキシに適用されます。
Kubernetes Ingress APIなどのシステムに入るトラフィックを制御するための他のメカニズムとは異なり、Istioゲートウェイを使用すると、Istioのトラフィックルーティングのすべての機能と柔軟性を活用できます。これは、IstioのGatewayリソースを使用すると、公開するポート、TLS設定などのレイヤー4〜6のロードバランシングプロパティを構成できるためです。次に、同じAPIリソースにアプリケーションレイヤーのトラフィックルーティング(L7)を追加する代わりに、通常のIstio 仮想サービスをゲートウェイにバインドします。これにより、基本的に、Istioメッシュ内の他のデータプレーントラフィックと同様に、ゲートウェイトラフィックを管理できます。
ゲートウェイは主にイングレストラフィックの管理に使用されますが、エグレスゲートウェイを構成することもできます。エグレスゲートウェイを使用すると、メッシュから出るトラフィック専用の出口ノードを構成し、外部ネットワークにアクセスできる、またはアクセスする必要があるサービスを制限したり、エグレストラフィックのセキュアな制御を有効にしてメッシュのセキュリティを強化したりできます。ゲートウェイを使用して、純粋に内部のプロキシを構成することもできます。
Istioは、使用できる事前構成済みのゲートウェイプロキシデプロイメント(istio-ingressgateway
とistio-egressgateway
)を提供しています。これらは両方とも、デモインストールを使用する場合にデプロイされますが、デフォルトプロファイルではイングレスゲートウェイのみがデプロイされます。これらのデプロイメントに独自のゲートウェイ構成を適用するか、独自のゲートウェイプロキシをデプロイして構成できます。
ゲートウェイの例
次の例は、外部HTTPSイングレストラフィックの可能なゲートウェイ構成を示しています。
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: ext-host-gwy
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- ext-host.example.com
tls:
mode: SIMPLE
credentialName: ext-host-cert
このゲートウェイ構成では、ext-host.example.com
からのHTTPSトラフィックをポート443でメッシュに許可しますが、トラフィックのルーティングは指定しません。
ルーティングを指定し、ゲートウェイを意図したとおりに機能させるには、ゲートウェイを仮想サービスにもバインドする必要があります。これは、次の例に示すように、仮想サービスのgateways
フィールドを使用して行います。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- ext-host.example.com
gateways:
- ext-host-gwy
その後、外部トラフィックのルーティングルールを使用して仮想サービスを構成できます。
サービスエントリ
サービスエントリを使用して、Istioが内部的に維持するサービスレジストリにエントリを追加します。サービスエントリを追加した後、Envoyプロキシは、それがメッシュ内のサービスであるかのように、サービスにトラフィックを送信できます。サービスエントリを構成することで、メッシュ外で実行されているサービス(Webから消費されるAPIやレガシーインフラストラクチャ内のサービスなど)のトラフィックを管理できます。
- 外部宛先(Webから消費されるAPIやレガシーインフラストラクチャ内のサービスなど)のトラフィックをリダイレクトおよび転送します。
- 外部宛先に対してリトライ、タイムアウト、フォルトインジェクションポリシーを定義します。
- VMをメッシュに追加することにより、仮想マシン(VM)でメッシュサービスを実行します。
メッシュサービスが使用するすべての外部サービスにサービスエントリを追加する必要はありません。デフォルトでは、IstioはEnvoyプロキシが未知のサービスへのリクエストをパススルーするように構成されています。ただし、メッシュに登録されていない宛先へのトラフィックを制御するためにIstio機能を使用することはできません。
サービスエントリの例
次の例では、メッシュ外部サービスエントリによって、ext-svc.example.com
という外部依存関係がIstioのサービスレジストリに追加されます。
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: svc-entry
spec:
hosts:
- ext-svc.example.com
ports:
- number: 443
name: https
protocol: HTTPS
location: MESH_EXTERNAL
resolution: DNS
外部リソースはhosts
フィールドを使用して指定します。完全修飾名を使用することも、ワイルドカードプレフィックス付きのドメイン名を使用することもできます。
仮想サービスと宛先ルールを構成して、メッシュ内の他のサービスと同様に、サービスエントリへのトラフィックをより詳細に制御できます。たとえば、次の宛先ルールは、サービスエントリを使用して構成したext-svc.example.com
外部サービスへのリクエストのTCP接続タイムアウトを調整します。
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: ext-res-dr
spec:
host: ext-svc.example.com
trafficPolicy:
connectionPool:
tcp:
connectTimeout: 1s
その他の構成オプションについては、サービスエントリのリファレンスを参照してください。
サイドカー
デフォルトでは、IstioはすべてのEnvoyプロキシが関連するワークロードのすべてのポートでトラフィックを受け入れ、トラフィック転送時にメッシュ内のすべてのワークロードに到達するように構成します。サイドカー構成を使用して、次の操作を実行できます。
- Envoyプロキシが受け入れるポートとプロトコルのセットを微調整します。
- Envoyプロキシが到達できるサービスのセットを制限します。
大規模なアプリケーションでは、すべてのプロキシがメッシュ内の他のすべてのサービスに到達するように構成されていると、メモリ使用率の増加によりメッシュのパフォーマンスに影響する可能性があるため、このようにサイドカーの到達可能性を制限することをお勧めします。
特定のネームスペース内のすべてのワークロードにサイドカー構成を適用するか、workloadSelector
を使用して特定のワークロードを選択できます。たとえば、次のサイドカー構成は、bookinfo
ネームスペース内のすべてのサービスが、同じネームスペースとIstioコントロールプレーン(Istioのエグレスとテレメトリ機能に必要なもの)で実行されているサービスのみに到達するように構成します。
apiVersion: networking.istio.io/v1
kind: Sidecar
metadata:
name: default
namespace: bookinfo
spec:
egress:
- hosts:
- "./*"
- "istio-system/*"
詳細については、サイドカーのリファレンスを参照してください。
ネットワークの回復力とテスト
Istioは、メッシュ内のトラフィックのルーティングを支援するだけでなく、実行時に動的に構成できるオプトインの障害回復機能とフォルトインジェクション機能を提供します。これらの機能を使用することで、アプリケーションの信頼性を確保し、サービスメッシュがノードの障害に耐え、局所的な障害が他のノードに波及するのを防ぐことができます。
タイムアウト
タイムアウトとは、Envoyプロキシが特定のサービスからの応答を待つ時間の長さで、サービスが応答を無期限に待機したり、予測可能な時間枠内で呼び出しが成功または失敗することを保証します。HTTPリクエストのEnvoyタイムアウトは、Istioではデフォルトで無効になっています。
アプリケーションやサービスによっては、Istioのデフォルトのタイムアウトが適切ではない場合があります。たとえば、タイムアウトが長すぎると、障害が発生したサービスからの応答を待つことによる遅延が過剰になる可能性があり、短すぎると、複数のサービスを含む操作が戻るのを待っている間に、呼び出しが不必要に失敗する可能性があります。最適なタイムアウト設定を見つけて使用するために、Istioでは、サービスコードを編集することなく、仮想サービスを使用して、サービスごとにタイムアウトを簡単に動的に調整できます。これは、ratingsサービスのv1サブセットへの呼び出しに10秒のタイムアウトを指定する仮想サービスの例です。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
timeout: 10s
再試行
リトライ設定は、最初の呼び出しが失敗した場合に、Envoyプロキシがサービスへの接続を試行する最大回数を指定します。リトライは、一時的な問題(一時的に過負荷状態のサービスやネットワークなど)のために呼び出しが永久に失敗しないようにすることで、サービスの可用性とアプリケーションのパフォーマンスを向上させることができます。リトライ間のインターバル(25ms以上)は可変であり、Istioによって自動的に決定され、呼び出されたサービスがリクエストで過負荷状態になるのを防ぎます。HTTPリクエストのデフォルトのリトライ動作は、エラーを返す前に2回リトライすることです。
タイムアウトと同様に、Istioのデフォルトのリトライ動作は、遅延(障害が発生したサービスへのリトライが多すぎると速度が低下する可能性がある)または可用性の点で、アプリケーションのニーズに合わない場合があります。タイムアウトと同様に、サービスコードに触れることなく、仮想サービスでサービスごとにリトライ設定を調整できます。また、リトライごとのタイムアウトを追加して、サービスへの接続に成功するまで待つ時間を指定することで、リトライ動作をさらに洗練させることができます。次の例では、最初の呼び出しの失敗後にこのサービスサブセットへの接続を最大3回リトライし、それぞれに2秒のタイムアウトを設定します。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
retries:
attempts: 3
perTryTimeout: 2s
サーキットブレーカー
サーキットブレーカーは、Istioが耐障害性のあるマイクロサービスベースのアプリケーションを作成するために提供するもう1つの便利なメカニズムです。サーキットブレーカーでは、サービス内の個々のホストへの呼び出しの制限(同時接続数やこのホストへの呼び出しが失敗した回数など)を設定します。この制限に達すると、サーキットブレーカーは「トリップ」し、そのホストへの接続を停止します。サーキットブレーカーパターンを使用すると、クライアントが過負荷状態または障害が発生しているホストへの接続を試行するのではなく、迅速に障害を検出できます。
サーキットブレーキングはロードバランシングプール内の「実際の」メッシュ宛先に適用されるため、サーキットブレーカーのしきい値は宛先ルールで構成され、設定はサービス内の各ホストに適用されます。次の例では、v1サブセットのreviews
サービスワークロードの同時接続数を100に制限します。
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
サーキットブレーカーの作成の詳細については、サーキットブレーキングを参照してください。
フォールトインジェクション
ネットワーク(障害回復ポリシーを含む)の構成が完了したら、Istioのフォルトインジェクションメカニズムを使用して、アプリケーション全体の障害回復能力をテストできます。フォルトインジェクションは、システムにエラーを導入して、エラー条件に耐え、そこから回復できることを確認するためのテスト方法です。フォルトインジェクションを使用すると、障害回復ポリシーが互換性がなく、または厳しすぎて、重要なサービスが使用できなくなる可能性があることを確認するのに特に役立ちます。
パケットの遅延やネットワーク層でのポッドのキルなど、エラーを導入するための他のメカニズムとは異なり、Istioではアプリケーション層でフォルトを注入できます。これにより、HTTPエラーコードなど、より関連性の高い障害を注入して、より関連性の高い結果を得ることができます。
2種類のフォルトを注入できます。どちらも仮想サービスを使用して構成します。
- 遅延:遅延はタイミングの障害です。ネットワーク遅延の増加または上流サービスの過負荷を模倣します。
- 異常終了:異常終了はクラッシュ障害です。上流サービスの障害を模倣します。異常終了は通常、HTTPエラーコードまたはTCP接続障害として発生します。
たとえば、この仮想サービスは、ratings
サービスへの1000リクエストのうち1リクエストに5秒間の遅延を導入します。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percentage:
value: 0.1
fixedDelay: 5s
route:
- destination:
host: ratings
subset: v1
遅延と異常終了の構成方法の詳細については、フォルトインジェクションを参照してください。
アプリケーションとの連携
Istioの障害回復機能は、アプリケーションに対して完全に透過的です。アプリケーションは、Envoyサイドカープロキシが応答を返す前に呼び出されたサービスの障害を処理しているかどうかを知りません。つまり、アプリケーションコードにも障害回復ポリシーを設定している場合は、両方が独立して動作し、競合する可能性があることを考慮する必要があります。たとえば、仮想サービスで1つ、アプリケーションで別のタイムアウトの2つのタイムアウトを設定できるとします。アプリケーションは、サービスへのAPI呼び出しに2秒のタイムアウトを設定します。ただし、仮想サービスでは、1回のリトライで3秒のタイムアウトを構成しました。この場合、アプリケーションのタイムアウトが最初に有効になるため、Envoyのタイムアウトとリトライ試行は無効になります。
Istioの障害回復機能は、メッシュ内のサービスの信頼性と可用性を向上させますが、アプリケーションは障害またはエラーを処理し、適切なフォールバックアクションを実行する必要があります。たとえば、ロードバランシングプール内のすべてのインスタンスが失敗した場合、EnvoyはHTTP 503
コードを返します。アプリケーションは、HTTP 503
エラーコードを処理するために必要なフォールバックロジックを実装する必要があります。