Istio v1alpha3ルーティングAPIの紹介
Istio v1alpha3ルーティングAPIの導入、動機、設計原則について説明します。
これまで、IstioはRouteRule
、DestinationPolicy
、EgressRule
、および(Kubernetes)Ingress
の4つの構成リソースを使用して、トラフィック管理のためのシンプルなAPIを提供してきました。このAPIにより、ユーザーはIstioサービスメッシュ内のトラフィックフローを簡単に管理できるようになりました。このAPIを使用すると、アプリケーションコード自体を変更することなく、リクエストを特定のバージョンのサービスにルーティングしたり、レジリエンステストのために遅延や障害を注入したり、タイムアウトやサーキットブレーカーを追加したりすることができます。
この機能はIstioの非常に魅力的な部分であることが証明されていますが、ユーザーフィードバックによると、特に数千のサービスを含む非常に大規模なアプリケーションを管理する場合や、HTTP以外のプロトコルを扱う場合には、このAPIにはいくつかの欠点があることも示されています。さらに、外部トラフィックを構成するためにKubernetes Ingress
リソースを使用することは、私たちのニーズにはまったく不十分であることが判明しました。
これらの問題やその他の懸念に対処するために、新しいトラフィック管理API、別名v1alpha3
が導入され、今後、以前のAPIを完全に置き換える予定です。v1alpha3
モデルは基本的に同じですが、下位互換性がないため、古いAPIからの手動変換が必要になります。
この中断を正当化するために、v1alpha3
APIは、時間とともに大幅に改善されたAPIになることを期待して、長くて苦痛なコミュニティレビュープロセスを経てきました。この記事では、新しい構成モデルを紹介し、それに影響を与えた動機と設計原則の一部を説明しようと試みます。
設計原則
ルーティングモデルの再設計には、いくつかの重要な設計原則が役割を果たしました。
- インフラストラクチャと意図を明示的にモデル化します。たとえば、ingressゲートウェイを構成することに加えて、それを実装するコンポーネント(コントローラー)も指定できます。
- オーサリングモデルは、構成的なものではなく、「プロデューサー指向」および「ホスト中心」である必要があります。たとえば、特定のホストに関連付けられたすべてのルールは、個別にではなく、まとめて構成されます。
- ルーティングとルーティング後の動作を明確に分離します。
v1alpha3の構成リソース
一般的なメッシュには、外部ネットワークからのTLSを終端し、メッシュへのトラフィックを許可する1つ以上のロードバランサー(ゲートウェイと呼びます)があります。その後、トラフィックはサイドカーゲートウェイを介して内部サービスを通過します。アプリケーションが外部サービス(例:Google Maps API)を消費することも一般的です。これらは直接呼び出される場合もあれば、特定のデプロイメントでは、メッシュから出るすべてのトラフィックが専用のegressゲートウェイを通過するように強制される場合もあります。次の図は、このメンタルモデルを示しています。
上記のセットアップを念頭に置いて、v1alpha3
は、メッシュへのトラフィックルーティング、メッシュ内ルーティング、メッシュ外ルーティングを制御するための次の新しい構成リソースを導入します。
Gateway
VirtualService
DestinationRule
ServiceEntry
VirtualService
、DestinationRule
、およびServiceEntry
は、それぞれRouteRule
、DestinationPolicy
、およびEgressRule
を置き換えます。Gateway
は、専用のミドルボックスに流れるトラフィックをモデル化するための、プラットフォームに依存しない抽象化です。
下の図は、構成リソース全体での制御の流れを示しています。
Gateway
Gateway
は、実行場所に関係なく、HTTP/TCPトラフィック用のロードバランサーを構成します。メッシュ内には任意の数のゲートウェイが存在でき、複数の異なるゲートウェイ実装を共存させることができます。実際、ゲートウェイ構成は、構成の一部としてワークロード(ポッド)ラベルのセットを指定することにより、特定のワークロードにバインドできます。これにより、ユーザーはシンプルなゲートウェイコントローラーを記述することで、既製のネットワークアプライアンスを再利用できます。
イングレストラフィック管理の場合、Kubernetes Ingress APIを再利用しないのはなぜですかと尋ねるかもしれません。Ingress APIは、Istioのルーティングニーズを表現することができないことが判明しました。異なるHTTPプロキシ間で共通の分母を描こうとすると、Ingressは最も基本的なHTTPルーティングのみをサポートでき、最新のプロキシの他のすべての機能を非ポータブルなアノテーションにプッシュすることになります。
Istio Gateway
は、L4-L6仕様をL7から分離することにより、Ingress
の欠点を克服します。これは、すべての優れたL7プロキシによって均一に実装されるL4-L6関数(例:公開するポート、TLS構成)のみを構成します。ユーザーは、Gateway
にVirtualService
をバインドすることにより、標準の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
には他のいくつかの重要な変更が含まれています
複数のマッチ条件を
VirtualService
構成内で表現できるため、冗長なルールの必要性が軽減されます。各サービスバージョンには名前(サービスサブセットと呼ばれます)があります。サブセットに属するポッド/VMのセットは、次のセクションで説明する
DestinationRule
で定義されます。VirtualService
ホストは、ワイルドカードDNSプレフィックスを使用して指定し、一致するすべてのサービスに対して単一のルールを作成できます。たとえば、Kubernetesで、foo
名前空間のすべてのサービスに対して同じ書き換えルールを適用する場合、VirtualService
はホストとして*.foo.svc.cluster.local
を使用します。
DestinationRule
DestinationRule
は、トラフィックをサービスに転送する際に適用されるポリシーのセットを構成します。それらは、サービス所有者が、サーキットブレーカー、ロードバランサー設定、TLS設定などを記述することを目的としています。DestinationRule
は、次の例外を除いて、前身のDestinationPolicy
とほぼ同じです
DestinationRule
のhost
にはワイルドカードプレフィックスを含めることができるため、多くの実際のサービスに対して単一のルールを指定できます。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
構成は単に宛先を内部サービスレジストリに追加するだけなので、レジストリ内の他のサービスと同様に、VirtualService
やDestinationRule
と組み合わせて使用できます。例えば、次の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
と比較して、次のようなその他の改善点を提供します。
- 単一の
ServiceEntry
で複数のサービスエンドポイントを構成できます。これは以前は複数のEgressRules
が必要でした。 - エンドポイントの解決モードは構成可能になりました(
NONE
、STATIC
、またはDNS
)。 - さらに、別の課題点にも取り組んでいます。プレーンテキストポート(例えば、
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
を使用して既存のリソースを更新することで行われます。
サービスバージョンを参照するルートを追加または削除する場合は、サービスの対応するDestinationRule
でsubsets
を更新する必要があります。ご想像のとおり、これもkubectl apply
を使用して行われます。
まとめ
Istioのv1alpha3
ルーティングAPIは、以前のものよりも大幅に多くの機能を持っていますが、残念ながら後方互換性がないため、1回の手動変換が必要です。以前の設定リソースであるRouteRule
、DesintationPolicy
、およびEgressRule
は、Istio 0.9以降ではサポートされません。Kubernetesユーザーは、基本的なルーティングのためにエッジロードバランサーを構成するためにIngress
を引き続き使用できます。ただし、高度なルーティング機能(例えば、2つのバージョン間でのトラフィック分割)には、大幅に機能が向上し、強く推奨されるIngress
の代替であるGateway
の使用が必要になります。
謝辞
ルーティングモデルの再設計と実装作業の功績は、次の人々(アルファベット順)にあります。
- Frank Budinsky (IBM)
- Zack Butcher (Google)
- Greg Hanson (IBM)
- Costin Manolache (Google)
- Martin Ostrowski (Google)
- Shriram Rajagopalan (VMware)
- Louis Ryan (Google)
- Isaiah Snell-Feikema (IBM)
- Kuat Yessenov (Google)