Istio v1alpha3ルーティングAPIの紹介

Istio v1alpha3ルーティングAPIの導入、動機、設計原則について説明します。

2018年4月25日 | フランク・ブディンスキー (IBM) およびシュリラム・ラジャゴパラン (VMware) 著

これまで、IstioはRouteRuleDestinationPolicyEgressRule、および(Kubernetes)Ingressの4つの構成リソースを使用して、トラフィック管理のためのシンプルなAPIを提供してきました。このAPIにより、ユーザーはIstioサービスメッシュ内のトラフィックフローを簡単に管理できるようになりました。このAPIを使用すると、アプリケーションコード自体を変更することなく、リクエストを特定のバージョンのサービスにルーティングしたり、レジリエンステストのために遅延や障害を注入したり、タイムアウトやサーキットブレーカーを追加したりすることができます。

この機能はIstioの非常に魅力的な部分であることが証明されていますが、ユーザーフィードバックによると、特に数千のサービスを含む非常に大規模なアプリケーションを管理する場合や、HTTP以外のプロトコルを扱う場合には、このAPIにはいくつかの欠点があることも示されています。さらに、外部トラフィックを構成するためにKubernetes Ingressリソースを使用することは、私たちのニーズにはまったく不十分であることが判明しました。

これらの問題やその他の懸念に対処するために、新しいトラフィック管理API、別名v1alpha3が導入され、今後、以前のAPIを完全に置き換える予定です。v1alpha3モデルは基本的に同じですが、下位互換性がないため、古いAPIからの手動変換が必要になります。

この中断を正当化するために、v1alpha3 APIは、時間とともに大幅に改善されたAPIになることを期待して、長くて苦痛なコミュニティレビュープロセスを経てきました。この記事では、新しい構成モデルを紹介し、それに影響を与えた動機と設計原則の一部を説明しようと試みます。

設計原則

ルーティングモデルの再設計には、いくつかの重要な設計原則が役割を果たしました。

v1alpha3の構成リソース

一般的なメッシュには、外部ネットワークからのTLSを終端し、メッシュへのトラフィックを許可する1つ以上のロードバランサー(ゲートウェイと呼びます)があります。その後、トラフィックはサイドカーゲートウェイを介して内部サービスを通過します。アプリケーションが外部サービス(例:Google Maps API)を消費することも一般的です。これらは直接呼び出される場合もあれば、特定のデプロイメントでは、メッシュから出るすべてのトラフィックが専用のegressゲートウェイを通過するように強制される場合もあります。次の図は、このメンタルモデルを示しています。

Role of gateways in the mesh
Istioサービスメッシュのゲートウェイ

上記のセットアップを念頭に置いて、v1alpha3は、メッシュへのトラフィックルーティング、メッシュ内ルーティング、メッシュ外ルーティングを制御するための次の新しい構成リソースを導入します。

  1. Gateway
  2. VirtualService
  3. DestinationRule
  4. ServiceEntry

VirtualServiceDestinationRule、およびServiceEntryは、それぞれRouteRuleDestinationPolicy、およびEgressRuleを置き換えます。Gatewayは、専用のミドルボックスに流れるトラフィックをモデル化するための、プラットフォームに依存しない抽象化です。

下の図は、構成リソース全体での制御の流れを示しています。

Relationship between different v1alpha3 elements
異なるv1alpha3要素間の関係

Gateway

Gatewayは、実行場所に関係なく、HTTP/TCPトラフィック用のロードバランサーを構成します。メッシュ内には任意の数のゲートウェイが存在でき、複数の異なるゲートウェイ実装を共存させることができます。実際、ゲートウェイ構成は、構成の一部としてワークロード(ポッド)ラベルのセットを指定することにより、特定のワークロードにバインドできます。これにより、ユーザーはシンプルなゲートウェイコントローラーを記述することで、既製のネットワークアプライアンスを再利用できます。

イングレストラフィック管理の場合、Kubernetes Ingress APIを再利用しないのはなぜですかと尋ねるかもしれません。Ingress APIは、Istioのルーティングニーズを表現することができないことが判明しました。異なるHTTPプロキシ間で共通の分母を描こうとすると、Ingressは最も基本的なHTTPルーティングのみをサポートでき、最新のプロキシの他のすべての機能を非ポータブルなアノテーションにプッシュすることになります。

Istio Gatewayは、L4-L6仕様をL7から分離することにより、Ingressの欠点を克服します。これは、すべての優れたL7プロキシによって均一に実装されるL4-L6関数(例:公開するポート、TLS構成)のみを構成します。ユーザーは、GatewayVirtualServiceをバインドすることにより、標準のIstioルールを使用して、Gatewayに入るHTTPリクエストとTCPトラフィックを制御できます。

たとえば、次の簡単なGatewayは、ホストbookinfo.comの外部httpsトラフィックをメッシュに許可するようにロードバランサーを構成します

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - bookinfo.com
    tls:
      mode: SIMPLE
      serverCertificate: /tmp/tls.crt
      privateKey: /tmp/tls.key

対応するルートを構成するには、同じホストに対してVirtualService次のセクションで説明)を定義し、構成内のgatewaysフィールドを使用してGatewayにバインドする必要があります

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
    - bookinfo.com
  gateways:
  - bookinfo-gateway # <---- bind to gateway
  http:
  - match:
    - uri:
        prefix: /reviews
    route:
    ...

Gatewayは、最初の図に示すように、エッジプロキシまたは純粋に内部プロキシをモデル化するために使用できます。場所に関係なく、すべてのゲートウェイを同じ方法で構成および制御できます。

VirtualService

ルートルールを「仮想サービス」と呼ばれるものに置き換えることは、最初は奇妙に思えるかもしれませんが、実際には、特に以前のモデルのスケーラビリティの問題に対処するためにAPIを再設計した後では、構成されるものの名前としてははるかに優れています。

事実上、変更されたのは、特定の宛先サービスに対する個々の構成リソース(ルール)のセットを使用してルーティングを構成するのではなく、評価順序を制御する優先度フィールドを含める代わりに、対応するVirtualServiceリソース内の順序付きリストにあるすべてのルールを使用して、(仮想)宛先自体を構成するようになったことです。たとえば、以前はBookinfoアプリケーションのreviewsサービスに対して2つのRouteRuleリソースがありましたが、このようになります

apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: reviews-default
spec:
  destination:
    name: reviews
  precedence: 1
  route:
  - labels:
      version: v1
---
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: reviews-test-v2
spec:
  destination:
    name: reviews
  precedence: 2
  match:
    request:
      headers:
        cookie:
          regex: "^(.*?;)?(user=jason)(;.*)?$"
  route:
  - labels:
      version: v2

v1alpha3では、同じ構成を1つのVirtualServiceリソースで提供します

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        cookie:
          regex: "^(.*?;)?(user=jason)(;.*)?$"
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

ご覧のとおり、reviewsサービスの両方のルールは1つの場所に統合されており、最初は好ましいかどうかわからないかもしれません。ただし、この新しいモデルをよく見ると、v1alpha3をはるかに機能的にする根本的な違いがあることがわかります。

まず、VirtualServiceの宛先サービスがhostsフィールド(実際には繰り返しフィールド)を使用して指定され、次に各ルート仕様のdestinationフィールドで再度指定されていることに注意してください。これは、以前のモデルからの非常に重要な違いです。

VirtualServiceは、1つ以上のユーザーがアドレス可能な宛先と、メッシュ内の実際の宛先ワークロード間のマッピングを記述します。私たちの例では、それらは同じですが、ユーザーがアドレス指定したホストは、サービスの住所として使用されるオプションのワイルドカードプレフィックスまたはCIDRプレフィックスを持つ任意のDNS名にすることができます。これは、サービスのコンシューマーが移行に適応する必要なく、モノリスを個別のマイクロサービスから構築された複合サービスに変えることを容易にする上で特に役立ちます。

たとえば、次のルールを使用すると、ユーザーはBookinfoアプリケーションのreviewsサービスとratingsサービスの両方をhttp://bookinfo.com/にあるより大きな(仮想)サービスの一部としてアドレス指定できます

apiVersion: networking.istio.io/v1alpha3
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
  ...

VirtualServiceのホストは、実際にはサービスレジストリの一部である必要はなく、単に仮想宛先です。これにより、ユーザーはメッシュ内にルーティング可能なエントリがない仮想ホストのトラフィックをモデル化できます。これらのホストは、同じホストのGateway構成にVirtualServiceをバインドすることにより(前のセクションで説明)、メッシュの外部に公開できます。

この根本的な再構築に加えて、VirtualServiceには他のいくつかの重要な変更が含まれています

  1. 複数のマッチ条件をVirtualService構成内で表現できるため、冗長なルールの必要性が軽減されます。

  2. 各サービスバージョンには名前(サービスサブセットと呼ばれます)があります。サブセットに属するポッド/VMのセットは、次のセクションで説明するDestinationRuleで定義されます。

  3. VirtualServiceホストは、ワイルドカードDNSプレフィックスを使用して指定し、一致するすべてのサービスに対して単一のルールを作成できます。たとえば、Kubernetesで、foo名前空間のすべてのサービスに対して同じ書き換えルールを適用する場合、VirtualServiceはホストとして*.foo.svc.cluster.localを使用します。

DestinationRule

DestinationRuleは、トラフィックをサービスに転送する際に適用されるポリシーのセットを構成します。それらは、サービス所有者が、サーキットブレーカー、ロードバランサー設定、TLS設定などを記述することを目的としています。DestinationRuleは、次の例外を除いて、前身のDestinationPolicyとほぼ同じです

  1. DestinationRulehostにはワイルドカードプレフィックスを含めることができるため、多くの実際のサービスに対して単一のルールを指定できます。
  2. DestinationRuleは、対応する宛先ホストのアドレス可能なsubsets(つまり、名前付きバージョン)を定義します。これらのサブセットは、特定のバージョンのサービスにトラフィックを送信する際に、VirtualServiceのルート仕様で使用されます。このようにバージョンに名前を付けることで、異なる仮想サービス間でそれらを明確に参照でき、Istioプロキシが出力する統計情報を簡素化し、SNIヘッダーにサブセットをエンコードできます。

reviewsサービスのポリシーとサブセットを構成するDestinationRuleは、次のようになります。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  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

DestinationPolicyとは異なり、複数のポリシー(例えば、デフォルトとv2固有)が1つのDestinationRule設定で指定されていることに注意してください。

ServiceEntry

ServiceEntryは、Istioが内部で管理するサービスレジストリに追加のエントリを追加するために使用されます。これは、ウェブから消費されるAPIやレガシーインフラストラクチャ内のサービスへのトラフィックなど、メッシュの外部依存関係へのトラフィックをモデル化するために最も一般的に使用されます。

以前にEgressRuleを使用して構成できたものはすべて、ServiceEntryで簡単に行うことができます。たとえば、メッシュ内部からのシンプルな外部サービスへのアクセスは、次のような構成を使用して有効にできます。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: foo-ext
spec:
  hosts:
  - foo.com
  ports:
  - number: 80
    name: http
    protocol: HTTP

とはいえ、ServiceEntryには、前身よりも大幅に多くの機能があります。まず、ServiceEntryは外部サービス構成に限定されず、メッシュ内部またはメッシュ外部の2つのタイプがあります。メッシュ内部エントリは他のすべての内部サービスと同様ですが、明示的にサービスをメッシュに追加するために使用されます。これらは、管理されていないインフラストラクチャ(例えば、Kubernetesベースのサービスメッシュに追加されたVM)を含めるようにサービスメッシュを拡張する一部としてサービスを追加するために使用できます。メッシュ外部エントリは、メッシュ外部のサービスを表します。それらに対しては、相互TLS認証が無効になり、ポリシー適用は、通常、内部サービスリクエストのサーバー側ではなく、クライアント側で実行されます。

ServiceEntry構成は単に宛先を内部サービスレジストリに追加するだけなので、レジストリ内の他のサービスと同様に、VirtualServiceDestinationRuleと組み合わせて使用できます。例えば、次のDestinationRuleは、外部サービスに対して相互TLS接続を開始するために使用できます。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: foo-ext
spec:
  host: foo.com
  trafficPolicy:
    tls:
      mode: MUTUAL
      clientCertificate: /etc/certs/myclientcert.pem
      privateKey: /etc/certs/client_private_key.pem
      caCertificates: /etc/certs/rootcacerts.pem

その拡張された一般性に加えて、ServiceEntryは、EgressRuleと比較して、次のようなその他の改善点を提供します。

  1. 単一のServiceEntryで複数のサービスエンドポイントを構成できます。これは以前は複数のEgressRulesが必要でした。
  2. エンドポイントの解決モードは構成可能になりました(NONESTATIC、またはDNS)。
  3. さらに、別の課題点にも取り組んでいます。プレーンテキストポート(例えば、http://google.com:443)を介してセキュアな外部サービスにアクセスする必要があるという課題です。これは今後数週間で修正される予定で、アプリケーションからhttps://google.comに直接アクセスできるようになります。この制限に対処するIstioパッチリリース(0.8.x)にご期待ください。

v1alpha3ルートルールの作成と削除

特定の宛先のすべてのルートルールは、単一のVirtualServiceリソース内の順序付きリストとしてまとめて格納されるようになったため、特定の宛先に対して2番目以降のルールを追加する場合は、新しい(RouteRule)リソースを作成するのではなく、宛先に対する唯一のVirtualServiceリソースを更新することによって行われます。

以前のルーティングルール

$ kubectl apply -f my-second-rule-for-destination-abc.yaml

v1alpha3ルーティングルール

$ kubectl apply -f my-updated-rules-for-destination-abc.yaml

特定の宛先の最後のルール以外のルートルールを削除する場合も、kubectl applyを使用して既存のリソースを更新することで行われます。

サービスバージョンを参照するルートを追加または削除する場合は、サービスの対応するDestinationRulesubsetsを更新する必要があります。ご想像のとおり、これもkubectl applyを使用して行われます。

まとめ

Istioのv1alpha3ルーティングAPIは、以前のものよりも大幅に多くの機能を持っていますが、残念ながら後方互換性がないため、1回の手動変換が必要です。以前の設定リソースであるRouteRuleDesintationPolicy、およびEgressRuleは、Istio 0.9以降ではサポートされません。Kubernetesユーザーは、基本的なルーティングのためにエッジロードバランサーを構成するためにIngressを引き続き使用できます。ただし、高度なルーティング機能(例えば、2つのバージョン間でのトラフィック分割)には、大幅に機能が向上し、強く推奨されるIngressの代替であるGatewayの使用が必要になります。

謝辞

ルーティングモデルの再設計と実装作業の功績は、次の人々(アルファベット順)にあります。

この投稿を共有する