外部サービスのフェイルオーバー設定
メッシュ外のエンドポイントに対する、ローカル優先ロードバランシングとフェイルオーバーの設定方法について説明します。
Istioの強力なAPIは、様々なサービスメッシュのユースケースを解決するために使用できます。多くのユーザーはIstioの強力なイングレスとイーストウエスト機能について知っていますが、それはまた、エグレス(アウトバウンド)トラフィックのための多くの機能を提供します。これは、アプリケーションがクラウドプロバイダーが提供するデータベースエンドポイントなどの外部サービスと通信する必要がある場合に特に役立ちます。ワークロードの実行場所に応じて、選択できるエンドポイントは複数あります。たとえば、AmazonのDynamoDBは、複数のエンドポイントをリージョン全体に提供しています。レイテンシの理由から、通常はワークロードに最も近いエンドポイントを選択しますが、予期せず問題が発生した場合に備えて、別のエンドポイントへの自動フェイルオーバーを設定する必要がある場合があります。
サービスメッシュ内で実行されているサービスと同様に、Istioは外れ値を検出し、健全なエンドポイントにフェイルオーバーするように設定できます。これはアプリケーションに対して完全に透過的です。この例では、Amazon DynamoDBエンドポイントを使用し、Google Kubernetes Engine(GKE)クラスタで実行されているワークロードと同じリージョンまたは近接したリージョンをプライマリリージョンとして選択します。また、フェイルオーバーリージョンも設定します。
ルーティング | エンドポイント |
---|---|
プライマリ | http://dynamodb.us-east-1.amazonaws.com |
フェイルオーバー | http://dynamodb.us-west-1.amazonaws.com |
ServiceEntryを使用した外部エンドポイントの定義
ローカル優先ロードバランシングは、通常はKubernetesノードに設定されたラベルから推論されるregion
またはzone
に基づいて機能します。まず、ワークロードの場所を特定します。
$ kubectl describe node | grep failure-domain.beta.kubernetes.io/region
failure-domain.beta.kubernetes.io/region=us-east1
failure-domain.beta.kubernetes.io/region=us-east1
この例では、GKEクラスタノードはus-east1
で実行されています。
次に、使用するエンドポイントを集約するServiceEntry
を作成します。この例では、ホストとしてmydb.com
を選択しました。これは、アプリケーションが接続するように設定する必要があるアドレスです。プライマリエンドポイントのlocality
をワークロードと同じリージョンに設定します。
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-dns
spec:
hosts:
- mydb.com
location: MESH_EXTERNAL
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
endpoints:
- address: dynamodb.us-east-1.amazonaws.com
locality: us-east1
ports:
http: 80
- address: dynamodb.us-west-1.amazonaws.com
locality: us-west
ports:
http: 80
リクエスト送信のテストソースとして使用するsleepコンテナをデプロイしましょう。
$ kubectl apply -f @samples/sleep/sleep.yaml@
sleepコンテナから、http://mydb.com
に5回アクセスしてみてください。
$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
Istioは両方のエンドポイントにリクエストを送信していることがわかります。ノードと同じリージョンにマークされているエンドポイントにのみ送信する必要があります。
そのためには、DestinationRule
を設定する必要があります。
DestinationRuleを使用したフェイルオーバー条件の設定
IstioのDestinationRule
を使用すると、ロードバランシング、接続プール、外れ値検出の設定を行うことができます。エンドポイントが不安定と識別され、ロードバランシングプールから削除される条件を指定できます。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: mydynamodb
spec:
host: mydb.com
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 1
interval: 15s
baseEjectionTime: 1m
上記のDestinationRule
は、15秒ごとにエンドポイントをスキャンするように設定されており、5xxエラーコードでエンドポイントが1回でも失敗すると、1分間不安定とマークされます。このサーキットブレーカーがトリガーされない場合、トラフィックはポッドと同じリージョンにルーティングされます。
curlを再度実行すると、トラフィックが常にus-east1
エンドポイントに送られていることがわかります。
$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
障害のシミュレーション
次に、us-eastエンドポイントがダウンした場合にどうなるかを見てみましょう。これをシミュレートするために、ServiceEntryを変更し、us-east
エンドポイントを無効なポートに設定します。
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-dns
spec:
hosts:
- mydb.com
location: MESH_EXTERNAL
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
endpoints:
- address: dynamodb.us-east-1.amazonaws.com
locality: us-east1
ports:
http: 81 # INVALID - This is purposefully wrong to trigger failover
- address: dynamodb.us-west-1.amazonaws.com
locality: us-west
ports:
http: 80
curlを再度実行すると、us-eastエンドポイントへの接続に失敗した後、トラフィックが自動的にus-westリージョンにフェイルオーバーされることがわかります。
$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
upstream connect error or disconnect/reset before headers. reset reason: connection failure
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
us-eastエンドポイントの外れ値ステータスは、以下を実行して確認できます。
$ istioctl pc endpoints <sleep-pod> | grep mydb
ENDPOINT STATUS OUTLIER CHECK CLUSTER
52.119.226.80:81 HEALTHY FAILED outbound|80||mydb.com
52.94.12.144:80 HEALTHY OK outbound|80||mydb.com
HTTPSのフェイルオーバー
外部HTTPSサービスのフェイルオーバーの設定も同様に簡単です。アプリケーションは引き続きプレーンHTTPを使用でき、IstioプロキシにHTTPSエンドポイントへのTLS開始を実行させることができます。
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-dns
spec:
hosts:
- mydb.com
ports:
- number: 80
name: http-port
protocol: HTTP
targetPort: 443
resolution: DNS
endpoints:
- address: dynamodb.us-east-1.amazonaws.com
locality: us-east1
- address: dynamodb.us-west-1.amazonaws.com
locality: us-west
上記のServiceEntryは、ポート80でmydb.com
サービスを定義し、ポート443で実際のDynamoDBエンドポイントにトラフィックをリダイレクトします。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: mydynamodb
spec:
host: mydb.com
trafficPolicy:
tls:
mode: SIMPLE
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
failover:
- from: us-east1
to: us-west
outlierDetection:
consecutive5xxErrors: 1
interval: 15s
baseEjectionTime: 1m
DestinationRule
は、TLS開始を実行し、外れ値検出を設定します。このルールには、フェイルオーバーフィールドも設定されており、フェイルオーバーターゲットとして正確にどのリージョンを指定できるようになっています。これは、複数のリージョンが定義されている場合に役立ちます。
まとめ
IstioのVirtualService
とDestinationRule
APIは、トラフィックルーティング、障害復旧、障害注入機能を提供するため、耐障害性の高いアプリケーションを作成できます。ServiceEntry APIは、これらの機能の多くを、サービスメッシュの一部ではない外部サービスに拡張します。