インクリメンタル Istio パート1、トラフィック管理

サイドカープロキシをデプロイせずに、Istio をトラフィック管理に使用する手順。

2018年11月21日 | Sandeep Parikh 著

トラフィック管理は、Istio が提供する重要なメリットの1つです。Istio のトラフィック管理の中心には、トラフィックフローとインフラストラクチャのスケーリングを切り離す機能があります。これにより、Istio のようなサービスメッシュがないと不可能な方法でトラフィックを制御できます。

たとえば、カナリアデプロイメント を実行したいとします。Istio を使用すると、サービスの v1 が着信トラフィックの 90% を受信し、そのサービスの v2 が 10% だけ受信するように指定できます。標準の Kubernetes デプロイメントでは、これを達成する唯一の方法は、各バージョンの利用可能な Pod の数を手動で制御することです(たとえば、v1 を実行する 9 個の Pod と v2 を実行する 1 個の Pod)。このタイプの手動制御は実装が難しく、時間の経過とともにスケーリングが困難になる可能性があります。詳細については、Istio を使用したカナリアデプロイメント をご覧ください。

同じ問題は、既存のサービスへの更新をデプロイする場合にも存在します。Kubernetes を使用してデプロイメントを更新できますが、v1 Pod を v2 Pod で置き換える必要があります。Istio を使用すると、サービスの v2 をデプロイし、組み込みのトラフィック管理メカニズムを使用して、ネットワークレベルで更新されたサービスにトラフィックをシフトしてから、v1 Pod を削除できます。

カナリアデプロイメントと一般的なトラフィックシフトに加えて、Istio は動的なリクエストルーティング(HTTP ヘッダーに基づく)、障害復旧、再試行、サーキットブレーカー、フォールトインジェクションを実装する機能も提供します。詳細については、トラフィック管理のドキュメント をご覧ください。

この投稿では、特に便利な方法、つまり個々の Pod を更新することなく、Istio を段階的に(この場合はトラフィック管理機能のみ)実装する方法について説明します。

設定:Istio トラフィック管理機能を実装する理由

もちろん、最初の質問は次のとおりです。なぜこれを行う必要があるのでしょうか?

多数のチームがデプロイする大規模なクラスタを持つ多くの組織の1つに所属している場合、答えは非常に明確です。チームA が Istio を開始し、サービスA でカナリアデプロイメントを開始したいが、チームB は Istio を使用していないため、サイドカーがデプロイされていないとします。

Istio を使用すると、チームA は、サービスB が Istio のイングレスゲートウェイを介してサービスA を呼び出すことで、カナリアを実装できます。

背景:Istio メッシュでのトラフィックルーティング

しかし、アプリケーションの各 Pod を Istio サイドカーを含めるように更新せずに、Istio のトラフィック管理機能を使用するにはどうすればよいでしょうか?その質問に答える前に、Istio メッシュにトラフィックが入力される方法とルーティングされる方法の概要を簡単に見てみましょう。

Istio メッシュの一部である Pod には、Pod へのすべてのインバウンドトラフィックとアウトバウンドトラフィックを仲介するサイドカープロキシが含まれています。Istio メッシュ内では、Pilot は高度なルーティングルールを構成に変換し、それらをサイドカープロキシに伝播する役割を担っています。つまり、サービスがお互いに通信する場合、ルーティングの決定はクライアント側で決定されます。

Istio メッシュの一部である2つのサービス、サービスAとサービスBがあるとします。A が B と通信したい場合、Pod A のサイドカープロキシはサービスB へのトラフィックのルーティングを担当します。たとえば、サービスB の v1 と v2 にトラフィックを 50/50 で分割したい場合、トラフィックは次のように流れます。

50/50 Traffic Split
50/50 トラフィック分割

サービスAとサービスBが Istio メッシュの一部でない場合、サービスB の異なるバージョンにトラフィックをルーティングする方法を知るサイドカープロキシはありません。その場合、設定した 50/50 ルールに従って、サービスA からサービスB へのトラフィックを取得する別の方法を使用する必要があります。

幸いにも、標準的な Istio デプロイメントには、Istio メッシュ外のイングレストラフィックを特に処理する ゲートウェイ が既に含まれています。このゲートウェイは、外部ロードバランサを介してクラスタ外部からのイングレストラフィックを許可したり、Kubernetes クラスタ内だがサービスメッシュ外部からのイングレストラフィックを許可したりするために使用されます。サイドカープロキシがない場合でも、適切な Pod に着信イングレストラフィックをプロキシするように構成できます。このアプローチにより、Istio のトラフィック管理機能を活用できますが、イングレスゲートウェイを通過するトラフィックは追加のホップが発生します。

50/50 Traffic Split using Ingress Gateway
イングレスゲートウェイを使用した 50/50 トラフィック分割

実践:Istio を使用したトラフィックルーティング

このアプローチを実践で確認する簡単な方法は、まず プラットフォームの設定 の手順を使用して Kubernetes 環境を設定し、次に Helm を使用してトラフィック管理コンポーネント(イングレスゲートウェイ、エグレスゲートウェイ、Pilot)のみを含む、**最小限の** Istio プロファイル をインストールすることです。次の例では Google Kubernetes Engine を使用します。

最初に、GKE を設定および構成します。

$ gcloud container clusters create istio-inc --zone us-central1-f
$ gcloud container clusters get-credentials istio-inc
$ kubectl create clusterrolebinding cluster-admin-binding \
   --clusterrole=cluster-admin \
   --user=$(gcloud config get-value core/account)

次に、Helm をインストール し、最小限の Istio インストールを生成 します(トラフィック管理コンポーネントのみ)。

$ helm template install/kubernetes/helm/istio \
  --name istio \
  --namespace istio-system \
  --set security.enabled=false \
  --set galley.enabled=false \
  --set sidecarInjectorWebhook.enabled=false \
  --set mixer.enabled=false \
  --set prometheus.enabled=false \
  --set pilot.sidecar=false > istio-minimal.yaml

次に、istio-system 名前空間を作成し、Istio をデプロイします。

$ kubectl create namespace istio-system
$ kubectl apply -f istio-minimal.yaml

次に、Istio サイドカーコンテナなしで Bookinfo サンプルをデプロイします。

圧縮
$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo.yaml@

次に、Istio メッシュの外からレビューサービスへのアクセスを許可する新しいゲートウェイ、レビューサービスの v1 と v2 にトラフィックを均等に分割する新しい VirtualService、およびサービスバージョンに宛先サブセットを一致させる新しい DestinationRule リソースのセットを構成します。

$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: reviews-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - "*"
  gateways:
  - reviews-gateway
  http:
  - match:
    - uri:
        prefix: /reviews
    route:
    - destination:
        host: reviews
        subset: v1
      weight: 50
    - destination:
        host: reviews
        subset: v2
      weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
EOF

最後に、curl でテストできる Pod(Istio サイドカーコンテナなし)をデプロイします。

圧縮
$ kubectl apply -f @samples/sleep/sleep.yaml@

デプロイメントのテスト

これで、curl コマンドを使用して sleep Pod を介してさまざまな動作をテストできます。

最初の例は、標準の Kubernetes サービスDNS動作を使用してレビューサービスにリクエストを送信することです(**注記**:以下の例では、jq を使用して curl の出力をフィルタリングしています)。

$ export SLEEP_POD=$(kubectl get pod -l app=sleep \
  -o jsonpath={.items..metadata.name})
$ for i in `seq 3`; do \
  kubectl exec -it $SLEEP_POD curl http://reviews:9080/reviews/0 | \
  jq '.reviews|.[]|.rating?'; \
  done
{
  "stars": 5,
  "color": "black"
}
{
  "stars": 4,
  "color": "black"
}
null
null
{
  "stars": 5,
  "color": "red"
}
{
  "stars": 4,
  "color": "red"
}

レビューサービスの3つのバージョンすべて(null は評価がないレビューv1からのもの)からの応答を取得しており、v1とv2で均等に分割されていないことに注目してください。これは、curlコマンドがレビューサービスの3つのバージョンすべてにわたってKubernetesサービスのロードバランシングを使用しているため、予想される動作です。レビューの50/50分割にアクセスするには、イングレスゲートウェイを介してサービスにアクセスする必要があります。

$ for i in `seq 4`; do \
  kubectl exec -it $SLEEP_POD curl http://istio-ingressgateway.istio-system/reviews/0 | \
  jq '.reviews|.[]|.rating?'; \
  done
{
  "stars": 5,
  "color": "black"
}
{
  "stars": 4,
  "color": "black"
}
null
null
{
  "stars": 5,
  "color": "black"
}
{
  "stars": 4,
  "color": "black"
}
null
null

ミッション完了!この投稿では、トラフィック管理コンポーネント(Pilot、イングレスゲートウェイ)のみを含む最小限の Istio インストールをデプロイし、それらのコンポーネントを使用してレビューサービスの特定のバージョンにトラフィックを誘導する方法を示しました。そして、これらの機能を得るために Istio サイドカープロキシをデプロイする必要はなかったため、既存のワークロードやアプリケーションの中断はほとんどまたはまったくありませんでした。

組み込みのイングレスゲートウェイ(いくつかの VirtualServiceDestinationRule リソースと共に)を使用して、この投稿では、クラスタ外部のイングレストラフィックとクラスタ内部のサービス間トラフィックに Istio のトラフィック管理を簡単に活用する方法を示しました。この手法は、Istio を採用するための段階的なアプローチの優れた例であり、Pod が異なるチームによって所有されているか、異なる名前空間にデプロイされている実際のケースで特に役立ちます。

この投稿を共有する