スタンドアロン・プログラムとしてのIstioの作業

Kubernetes Engine (OKE)で作成したクラスタにスタンドアロン・プログラムとしてIstioをインストールする方法をご紹介します。

このトピックでは、Kubernetes Engine (OKE)で作成したクラスタにスタンドアロン・プログラムとしてIstioをインストールする方法の例を示します。また、OKEとIstioの主な特徴を示した。

次のトピックが含まれています。

サービス・メッシュ製品(Oracle Cloud Infrastructure Service Mesh、Istio、Linkerdなど)は、ポッド・ネットワーキングにOCI VCNネイティブ・ポッド・ネットワーキングCNIプラグインを使用するときにサポートされます。Istioアドオンを除き、現在サポートはOracle Linux 7に制限されています(Oracle Linux 8のサポートが計画されています)。Istioアドオンは、Oracle Linux 7とOracle Linux 8の両方でサポートされています。ワーカー・ノードは、Kubernetes 1.26 (以降)を実行している必要があります。

ノート

Istioは、管理対象ノード・プールで使用できますが、仮想ノード・プールでは使用できません。

スタンドアロン・プログラムとしてのIstioのインストール

Istioの使用を開始するには、OKEクラスタを作成するか、既存のOKEクラスタを使用してから、Istioをインストールします。次の項では、Istio設定をインストールおよびテストするステップについて説明します。インストール・オプションの詳細は、ここを参照してください。

OKEクラスタの作成

OKEクラスタを作成します。

  1. まだ作成していない場合は、OCIテナンシ内にOKEクラスタを作成します。OKEクラスタの作成には、複数のオプションを使用できます。最も簡単なオプションは、Webコンソールの「クイック作成」ウィザードです。
  2. ローカル・マシン上のOKEクラスタにアクセスするには、kubectlおよびoci-cliをインストールします。
  3. kubectlを使用してコマンドラインからOKEクラスタにアクセスするには、kubeconfigファイルを設定し、kubectlがクラスタにアクセスできることを確認します。

コマンドラインからのIstioのダウンロード

コマンドラインからIstioをダウンロードするには、次のステップに従います。

  1. 次のコマンドを実行してIstioをダウンロードします。
    curl -L https://istio.io/downloadIstio | sh -
  2. Istioパッケージのディレクトリに移動します。たとえば、パッケージがistio-1.1.11.2の場合:
    cd istio-1.11.2
  3. istioctlクライアント・ツールをワークステーションのPATHに追加します。
    export PATH=$PWD/bin:$PATH
  4. 事前チェックを実行して、クラスタがIstioインストール要件を満たしているかどうかを検証します。
    istioctl x precheck

istioctlによるIstioのインストール

次のコマンドを使用して、istioctlを使用してIstioをインストールします。
istioctl install

Bookinfoアプリケーションの実行

Istioプロジェクトは、Istioの機能を実証する方法としてBookinfoアプリケーションを提供します。オンライン・ブック・ストアの単一のカタログ・エントリと同様に、ブックに関する情報が表示されます。各ブック・ページには、ブックの説明、ブックの詳細(ISBN、ページ数)、およびいくつかのブック・レビューが含まれます。Bookinfoアプリケーションの詳細は、Bookinfoのドキュメントを参照してください。

Bookinfoアプリケーションの図

図に示すように、Bookinfoアプリケーションは4つのマイクロサービスで構成されています。

  • 製品ページ・サービス: 「詳細」および「レビュー」サービスをコールして、製品ページを作成します。
  • 詳細サービス:ブック情報を返します。
  • レビュー・サービス:ブック・レビューを返し、評価サービスをコールします。
  • 評価サービス:ブックレビューのランキング情報を返します。

Bookinfoアプリケーションをインストールして実行するには、次のステップに従います。

  1. アプリケーションをホストするネームスペースにistio-injection=enabledでラベルを付けます。
    kubectl label namespace default istio-injection=enabled
  2. サンプルBookinfoアプリケーションをデプロイします。
    kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
  3. すべてのサービスおよびポッドが実行されていることを確認します。
    kubectl get services
    kubectl get pods
  4. ポッドからcurlコマンドを送信して、アプリケーションが実行中であることを確認します。
    kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
  5. クラスタの外部からアプリケーションにアクセスできるようにします。
    kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  6. アプリケーションがゲートウェイを使用していることを確認します。これらの手順を使用して、INGRESS_HOSTおよびINGRESS_PORTを決定します。
    curl -s "http://${INGRESS_HOST}:${INGRESS_PORT}/productpage" | grep -o "<title>.*</title>"

また、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開いて、Bookinfo Webページを表示します。ページを何度かリフレッシュすると、製品ページに表示される様々なバージョンのレビューが表示されます。

Istio統合アプリケーションの追加

Istioは、一般的なKubernetes関連アプリケーションとよく統合されています。

プロメテウス

Istioは、Prometheusを迅速に起動して実行するための基本的なサンプル・インストールを提供します。

kubectl apply -f samples/addons/prometheus.yaml

または、prometheusをインストールし、Istioメトリックをスクレイプするように構成します。

Prometheusを使用した本番規模のモニタリングについては、「本番規模のモニタリングでのPrometheusの使用」を参照してください。

Grafana

Istioは、Grafanaを迅速に起動して実行するための基本的なサンプル・インストールを提供します。すべてのIstioダッシュボードがインストールに含まれています。

kubectl apply -f samples/addons/grafana.yaml

または、Grafanaを別途インストールします。さらに、Istioの事前構成済ダッシュボードをインポートできます。

Jaeger

Istioは、Jaegerをすばやく起動して実行するための基本的なサンプル・インストールを提供します。

kubectl apply -f samples/addons/jaeger.yaml

または、Jaegerを個別にインストールし、Jaegerデプロイメントにトレースを送信するためにIstioを構成します。

ジプキン

Istioは、zipkinをすばやく起動して実行するための基本的なサンプル・インストールを提供します。

kubectl apply -f samples/addons/extras/zipkin.yaml

または、zipkinを個別にインストールし、Istioを構成してトレースをzipkinデプロイメントに送信します。

キアリ

Istioは、Kialiを迅速に起動して実行するための基本的なサンプルインストールを提供します。

kubectl apply -f samples/addons/kiali.yaml
            

または、Kialiを別途インストールおよび構成します。

Istio監視の確認

この項では、Istio統合アプリケーションによって提供されるパフォーマンス・メトリックおよびトレース機能を確認します。

PrometheusからのBookinfoアプリケーションのメトリックの問合せ

PrometheusとIstioでは、Bookinfoのパフォーマンス・データをいくつかの方法で分析します。

まず、Prometheusがインストールされていることを確認します。

kubectl -n istio-system get svc prometheus

次のコマンドを使用してPrometheus UIを起動します。

istioctl dashboard prometheus

ヘッダーのPrometheusの右側にある「Graph(グラフ)」をクリックします。一部のデータを表示するには、ブラウザまたはcurlを使用して製品ページのトラフィックを生成します。トラフィックはPrometheusダッシュボードに反映されます。

Grafanaを使用したBookinfoアプリケーションのメトリックのビジュアル化

PrometheusとGrafanaを組み合せると、アプリケーションに適したパフォーマンス・ダッシュボードが提供されます。ダッシュボードを使用するには、まずPrometheusとGrafanaの両方がインストールされていることを確認します。

kubectl -n istio-system get svc prometheus
kubectl -n istio-system get svc grafana

Istio Grafanaダッシュボードを起動します。

istioctl dashboard grafana

Grafanaダッシュボードの管理

Istioサービス・メッシュは、6つのGrafanaダッシュボードを提供します。Istioサービス・メッシュGrafanaダッシュボードのスナップショットがここで取得されます。

ノート

ブラウザまたはcurlを使用して製品ページへのトラフィックを生成し、Grafanaダッシュボードに反映されるようにします。

Istioメッシュダッシュボード

Istioメッシュ・ダッシュボードのスナップショット

Istioサービス・ダッシュボード

Istioサービス・ダッシュボードのスナップショット

Istioワークロード・ダッシュボード

Istioワークロード・ダッシュボードのスナップショット

Istioパフォーマンス・ダッシュボード

Istioパフォーマンス・ダッシュボードのスナップショット

Istioコントロール・ペイン・ダッシュボード

Istioコントロール・ペイン・ダッシュボードのスナップショット

ダッシュボードの作成、構成および編集方法の詳細は、Grafanaのドキュメントを参照してください。

Jaegerを使用した分散トレースの実行

Jaegerオープン・ソース・フレームワークを使用して、Istioでアプリケーション・トレースを実行します。

  1. istioctlを使用してトレースを有効化および構成します。
    istioctl install --set meshConfig.enableTracing=true
  2. Bookinfoアプリケーションがデプロイされた状態で、istioctlを使用してJaeger UIを開きます。
    istioctl dashboard jaeger
  3. トレースを生成するには、プロダクト・ページにリクエストを送信します。
    for i in $(seq 1 100); do curl -s -o /dev/null "http://$INGRESS_HOST:$INGRESS_PORT/productpage"; done

トレースがJaegerダッシュボードに反映されていることがわかります。

Jaegerダッシュボード

Istio Jaegerダッシュボードのスナップショット

Jaegerアプリケーション・トレース

Istio Jaegerアプリケーション・トレースのスナップショット

zipkinを使用した分散トレースの実行

zipkinオープン・ソース・フレームワークを使用して、Istioでアプリケーション・トレースを実行します。

  1. istioctlを使用してトレースを有効化および構成します。
    istioctl install --set meshConfig.enableTracing=true
  2. Bookinfoアプリケーションがデプロイされた状態で、istioctlを使用してzipkin UIを開きます。
    istioctl dashboard zipkin
  3. トレースを生成するには、プロダクト・ページにリクエストを送信します。
    for i in $(seq 1 100); do curl -s -o /dev/null "http://$INGRESS_HOST:$INGRESS_PORT/productpage"; done

トレースがzipkinダッシュボードに反映されていることがわかります。

サンプルzipkinダッシュボード

Istio Zipkinダッシュボードのスナップショット

OCI Application Performance Monitoringを使用した分散トレースの実行

OCI Application Performance Monitoring (APM)は、Jaegerやzipkinなどのオープン・ソース・トレース・システム・ツールと統合されます。APMでは、OCIでトレース・データをアップロードできます。OCI APMと統合するには、ここに記載されている手順に従ってAPMドメインを作成します。APMドメインは、APMによってモニターされるシステムを含むOCIリソースです。

ドメインの作成後、ドメインの詳細を表示し、データ・アップロード・エンドポイントの取得、秘密キーおよび公開キーを使用してAPMコレクタURLを構成します。APMコレクタURLは、APMサービスと通信するようにオープン・ソース・トレーサを構成するときに必要です。コレクタURL形式では、データ・アップロード・エンドポイントをベースURLとして使用して構築されたURLが必要であり、秘密キーまたは公開キーの値を含む選択肢に基づいてパスが生成されます。形式はここに記載されています。URLパスを構成して、そのURLをIstio構成に接続します。

ノート

APMサービス・ポリシーの構成の詳細は、次を参照してください:

APMにトレースを送信するためのIstioの構成

  1. istioctlを使用してトレースを有効にします。
    istioctl install --set meshConfig.defaultConfig.tracing.zipkin.address=aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com:443
    ノート

    aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.comのエンドポイント・アドレスは例であり、実際のエンドポイントではありません。
  2. Envoyを構成して、APMにzipkinトレースを送信します。samples/custom-bootstrap/custom-bootstrap.yamlのコードを次のコード・ブロックに置き換えます。
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: istio-custom-bootstrap-config
      namespace: default
    data:
      custom_bootstrap.json: |
        {
            "tracing": {
                "http": {
                    "name": "envoy.tracers.zipkin",
                    "typed_config": {
                        "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
                        "collector_cluster": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain]
                        "collector_endpoint": "/20200101/observations/private-span?dataFormat=zipkin&dataFormatVersion=2&dataKey=2C6YOLQSUZ5Q7IGN", // [Replace with the private datakey of your apm domain. You can also use public datakey but change the observation type to public-span]
                        "collectorEndpointVersion": "HTTP_JSON",
                        "trace_id_128bit": true,
                        "shared_span_context": false
                    }
                }
            },
            "static_resources": {
                "clusters": [{
                    "name": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain:443]
                    "type": "STRICT_DNS",
                    "lb_policy": "ROUND_ROBIN",
                    "load_assignment": {
                        "cluster_name": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain]
                        "endpoints": [{
                            "lb_endpoints": [{
                                "endpoint": {
                                    "address": {
                                        "socket_address": {
                                            "address": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain]
                                            "port_value": 443
                                        }
                                    }
                                }
                            }]
                        }]
                    },
                    "transport_socket": {
                        "name": "envoy.transport_sockets.tls",
                        "typed_config": {
                            "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
                            "sni": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com" // [Replace this with data upload endpoint of your apm domain]
                        }
                    }
                }]
            }
        }
    EOF
  3. カスタム構成を適用します。
    kubectl apply -f samples/custom-bootstrap/custom-bootstrap.yaml
  4. Bookinfoのすべてのサービスでこのカスタム・ブートストラップ構成を使用するには、値としてカスタムConfigMapの名前を持つ注釈sidecar.istio.io/bootstrapOverrideを追加します。次の例では、製品ページの注釈がsamples/bookinfo/platform/kube/bookinfo.yamlの下に追加されます。同様の注釈を他のサービスに追加します。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productpage-v1
      labels:
        app: productpage
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: productpage
          version: v1
      template:
        metadata:
          labels:
            app: productpage
            version: v1
          annotations:
            sidecar.istio.io/bootstrapOverride: "istio-custom-bootstrap-config" #[Name of custom configmap]
        spec:
          serviceAccountName: bookinfo-productpage
          containers:
            - name: productpage
              image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 9080
              volumeMounts:
                - name: tmp
                  mountPath: /tmp
              securityContext:
                runAsUser: 1000
          volumes:
            - name: tmp
              emptyDir: {}
    ---
  5. yamlを適用すると、再起動されたすべてのポッドがAPMへのトレースの送信を開始します。
    kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
  6. イングレス・ゲートウェイがトレースを送信できるようにするには、istio-systemネームスペースにcustom-bootstrap.yamlという名前のconfigmapを作成します:
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: istio-custom-bootstrap-config
      namespace: istio-system
    data:
      custom_bootstrap.json: |
        {
            "tracing": {
                "http": {
                    "name": "envoy.tracers.zipkin",
                    "typed_config": {
                        "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
                        "collector_cluster": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain]
                        "collector_endpoint": "/20200101/observations/private-span?dataFormat=zipkin&dataFormatVersion=2&dataKey=2C6YOLQSUZ5Q7IGN", // [Replace with the private datakey of your apm domain. You can also use public datakey but change the observation type to public-span]
                        "collectorEndpointVersion": "HTTP_JSON",
                        "trace_id_128bit": true,
                        "shared_span_context": false
                    }
                }
            },
            "static_resources": {
                "clusters": [{
                    "name": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain:443]
                    "type": "STRICT_DNS",
                    "lb_policy": "ROUND_ROBIN",
                    "load_assignment": {
                        "cluster_name": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain]
                        "endpoints": [{
                            "lb_endpoints": [{
                                "endpoint": {
                                    "address": {
                                        "socket_address": {
                                            "address": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com", // [Replace this with data upload endpoint of your apm domain]
                                            "port_value": 443
                                        }
                                    }
                                }
                            }]
                        }]
                    },
                    "transport_socket": {
                        "name": "envoy.transport_sockets.tls",
                        "typed_config": {
                            "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
                            "sni": "aaaabbbb.apm-agt.us-ashburn-1.oci.oraclecloud.com" // [Replace this with data upload endpoint of your apm domain]
                        }
                    }
                }]
            }
        }
    EOF
  7. カスタム・ブートストラップ構成の使用を開始するイングレス・ゲートウェイ用のgateway-patch.yamlという名前のパッチを作成します:
    spec:
      template:
        spec:
          containers:
          - name: istio-proxy
            env:
            - name: ISTIO_BOOTSTRAP_OVERRIDE
              value: /etc/istio/custom-bootstrap/custom_bootstrap.json
            volumeMounts:
            - mountPath: /etc/istio/custom-bootstrap
              name: custom-bootstrap-volume
              readOnly: true
          volumes:
          - configMap:
              name: istio-custom-bootstrap-config
              defaultMode: 420
              optional: false
            name: custom-bootstrap-volume
  8. イングレス・ゲートウェイに以前のパッチを適用します:
    kubectl --namespace istio-system patch deployment istio-ingressgateway --patch "$(cat gateway-patch.yaml)"
  9. トレースを生成するには、プロダクト・ページにリクエストを送信します。
    for i in $(seq 1 100); do curl -s -o /dev/null "http://$INGRESS_HOST:$INGRESS_PORT/productpage"; done

トレースは、ここのステップに従ってAPMダッシュボードに反映されます。

Zipkinトレース・エクスプローラ

Zipkin Trace Explorerのスクリーンショット

ジプキントレース

Zipkinトレースのスクリーンショット

ジプキンスパン

スパンを表示するには、APMリストの「ホーム」をクリックします。

ジプキンスパンのスクリーンショット

Zipkinアプリ・ダッシュボード

APMには、ダッシュボードを作成し、時間の経過とともに生成されたスパンを調べる機能があります。ダッシュボードは、ここのステップに従って作成できます。

Zipkinアプリ・ダッシュボードのスクリーンショット

Zipkinメトリック・エクスプローラ

APMでは、メトリックアラームおよび通知を使用して、アプリケーションのヘルス、容量およびパフォーマンスをモニターできます。メトリックを構成するには、ここのステップに従います。

Zipkinメトリック・エクスプローラのスクリーンショット

OCIロギングを使用したログの監視

OCI Loggingは、OCIのテナンシのログ・ファイル・エントリを分析および検索するための中央コンポーネントです。OKEワーカー・ノードからのKubernetesコンテナ・ログは、カスタム・ログとしてOCIロギングに公開できます。コンテナ・ログを取り込むには、ここで説明するステップに従ってOCIロギングを構成します

  1. istioctlを使用して、Istioでのenvoyアクセス・ロギングを有効にします。
    istioctl install --set meshConfig.accessLogFile=/dev/stdout
  2. ブラウザまたはcurlを使用して、Bookinfo製品ページにアクセスします。生成されたアクセス・ログは、kubectlコマンドを使用して表示できます。
    kubectl logs -l app=productpage -c istio-proxy

クラスタにOCIロギングが構成されている場合は、OCIコンソールのログ検索ページを使用して、これらのログを問い合せて分析できます。

OCIロギング検索

OCIロギング検索のスクリーンショット

OCIロギング検索の拡張

展開されたOCIロギング検索のスクリーンショット

Kialiを使用したメッシュの視覚化

Kialiがインストールされていることを確認します。

kubectl -n istio-system get svc kiali

ブラウザでKiali UIを開きます。

istioctl dashboard kiali

製品ページにトラフィックを送信します。

for i in $(seq 1 100); do curl -s -o /dev/null "http://$INGRESS_HOST:$INGRESS_PORT/productpage"; done

ここからステップ5に従って、Kialiでメッシュを視覚化します。

トラフィックの管理

Istioのトラフィック・ルーティング・ルールにより、サービス間のトラフィックのフローを制御し、サーキット・ブレーカ、タイムアウト、再試行などのサービス・レベルのプロパティの構成を簡素化できます。Istioを使用すると、A/Bテスト、カナリア・ロールアウト、ステージ・ロールアウトなどの重要なタスクを、パーセンテージ・ベースのトラフィック分割で簡単に設定できます。

Istioのトラフィック管理APIリソース:

IstioでBookinfoアプリケーションのバージョン・ルーティングを制御するには、宛先ルールで、サービスの使用可能なすべてのバージョン(サブセット)を定義します。Bookinfoサービスのデフォルトの宛先ルールを作成します。
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

シフト・トラフィック

Istioでは、Istioの重み付けされたルーティング機能を使用して、トラフィックをあるバージョンのマイクロサービスから別のバージョンに段階的に移行できます。次の例は、トラフィックの50%をreviews:v1に送信し、50%をreviews:v3に送信するように構成する方法を示しています。その後、トラフィックの100%をreviews:v3に送信して移行を完了します。

  1. すべてのトラフィックを各マイクロサービスのv1バージョンにルーティングします。
    kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

    Bookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。リフレッシュの回数に関係なく、ページのレビュー部分は星の評価なしで表示されます。Istioは、レビュー・サービスのすべてのトラフィックをreviews:v1にルーティングするように構成されており、このバージョンのサービスはスター評価サービスにアクセスしません。

  2. 次のコマンドを使用して、トラフィックの50%をreviews:v1からreviews:v3に転送し、新しいルールが伝播されるまで待機します。
    kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

    ブラウザの/productpage URLをリフレッシュし、約50%の赤色の星評価を確認します。reviews:v3は星評価サービスにアクセスしますが、reviews:v1バージョンはアクセスしません。

  3. トラフィックの100%をreviews:v3にルーティングします。
    kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yaml
  4. ブラウザの/productpage URLをリフレッシュし、レビューごとに赤色の星評価を常に表示します。

リクエスト・ルーティングの管理

Istioは様々な方法でトラフィックをルーティングできます。開始するには、各マイクロサービスのv1を介してすべてのトラフィックをルーティングするようにIstioを構成します。
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

Bookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。リフレッシュの回数に関係なく、ページのレビュー部分は星の評価なしで表示されます。Istioは、レビュー・サービスのすべてのトラフィックをバージョンreviews:v1にルーティングするように構成されているためです。このバージョンのサービスは、星評価サービスにアクセスしません。

Booinfoのサンプルのスクリーンショット。

ユーザー・アイデンティティに基づくルーティング

ユーザー・アイデンティティに基づいてルーティングするには:

  1. jasonという名前の特定のユーザーからのすべてのトラフィックがreviews:v2にルーティングされるように、ルート構成を変更します。Istioには、ユーザー・アイデンティティに関する特別な組込みの理解はありません。この例では、productpageサービスは、レビュー・サービスへのすべてのアウトバウンドHTTPリクエストにカスタム・エンドユーザー・ヘッダーを追加します。
    kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
  2. Bookinfo Webページを表示し、ユーザーjasonとしてログインするには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。ブラウザをリフレッシュして、各レビューの横に星評価が表示されます。

    星を持つBooinfoのサンプルのスクリーンショット
  3. ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開き、Bookinfo Webページを表示し、jason以外のユーザーとしてログインします。ブラウザをリフレッシュして、レビューごとに星を表示しません。

    星のないBooinfoのサンプルのスクリーンショット

URLリライトに基づくルーティング

この例では、/productsまたは/bookinfoproductpageで始まるパスを持つHTTPリクエストは、/productpageにリライトされます。HTTPリクエストは、ポート9080で実行されているproductpageを使用してポッドに送信されます。Istio URLのリライトの詳細は、ここを参照

  1. 次のyamlを適用します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: bookinfo
    spec:
      hosts:
      - "*"
      gateways:
      - bookinfo-gateway
      http:
      - match:
        - uri:
            prefix: /products
        - uri:
            prefix: /bookinfoproductpage
        rewrite:
          uri: /productpage
        route:
        - destination:
            host: productpage
            port:
              number: 9080
    EOF
  2. Bookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productsおよびhttp://${INGRESS_HOST}:${INGRESS_PORT}/bookinfoproductpageを開きます。どちらの場合も、リクエストを転送する前にリライトが実行されます。

    リライト/ブック製品ページ

    /bookproductpageを使用したBooinfoのサンプル・ブックのスクリーンショット

    リライト/製品

    /productsを使用したBooinfoのサンプル・ブックのスクリーンショット
  3. yamlファイルをIstioが提供する元のバージョンにクリーンアップし、適用します。
    kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  4. URL http://${INGRESS_HOST}:${INGRESS_PORT}/bookinfoproductpageまたはhttp://${INGRESS_HOST}:${INGRESS_PORT}/productsを開いて、yamlがリクエストをリライトしないため、製品ページを表示しません。

    404エラー/製品

    /products 404を使用したBooinfoのサンプル・ブックのスクリーンショット

    404エラー/booksproductpage

    /booksproductpage 404を使用したBooinfoのサンプルのスクリーンショット

ネットワークの自己回復性のテスト

Istioでは、リクエスト・タイムアウト、フォルト・インジェクションおよび回路遮断器用にインストールを構成できます。これらの設定により、デプロイされたアプリケーションのフォルト・トレランスを管理およびテストできます。

リクエスト・タイムアウトの設定

タイムアウトは、Envoyプロキシが特定のサービスからの応答を待機する時間です。タイムアウトにより、サービスは応答を無期限に待機せず、予測可能な時間枠内にコールが成功または失敗することを保証します。タイムアウトの詳細は、こちらを参照してください。

HTTPリクエストのタイムアウトは、ルート・ルールのタイムアウト・フィールドを使用して指定できます。デフォルトでは、リクエスト・タイムアウトは無効です。

  1. 次のコマンドを実行して、アプリケーション・バージョン・ルーティングを初期化します。
    kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
  2. reviews:v2サービスにリクエストをルーティングします。実際には、評価サービスをコールするバージョンです。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: reviews
    spec:
      hosts:
        - reviews
      http:
      - route:
        - destination:
            host: reviews
            subset: v2
    EOF
  3. 評価サービスへのコールに2秒間の遅延を追加します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: ratings
    spec:
      hosts:
      - ratings
      http:
      - fault:
          delay:
            percent: 100
            fixedDelay: 2s
        route:
        - destination:
            host: ratings
            subset: v1
    EOF
  4. 評価の星が表示されたBookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。ページをリフレッシュすると、2秒間の遅延が発生します。
    ブック製品のWebページのスクリーンショット。
  5. レビュー・サービスへのコールの半秒リクエスト・タイムアウトを追加します:
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: reviews
    spec:
      hosts:
      - reviews
      http:
      - route:
        - destination:
            host: reviews
            subset: v2
        timeout: 0.5s
    EOF
  6. Bookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。ページが2ではなく約1秒で戻ってきて、レビューが使用できないことに注意してください。
    ブック製品のWebページのスクリーンショット。

タイムアウトが半秒で構成されていても、レスポンスに1秒かかる理由は、productpageサービスでハードコードされた再試行が原因です。サービスは、タイムアウトしたレビュー・サービスを2回コールしてから戻ります。

ルート・ルールでオーバーライドする以外に、アプリケーションがアウトバウンド・リクエストにx-envoy-upstream-rq-timeout-msヘッダーを追加する場合、リクエストごとにタイムアウトをオーバーライドすることもできます。

フォルト・インジェクションの管理

障害注入は、システムにエラーを導入して、システムがエラー状態に耐え、エラー状態から回復するようにするテスト方法です。Istioでは、HTTPエラー・コードなどのアプリケーション・レイヤーでのフォルト・インジェクションが可能です。Istioは、2つのタイプのフォルトを注入します。どちらも仮想サービスを使用して構成されます。障害インジェクションの詳細は、ここを参照してください

  • 遅延:遅延とは、ネットワーク・レイテンシの増加またはオーバーロードされたアップストリーム・サービスを模倣するタイミングの失敗です。
  • 中断:中断は、アップストリーム・サービスの障害を模倣するクラッシュ障害です。HTTPエラーコードまたはTCP接続の失敗の形式でマニフェストを中止します。

障害インジェクションをテストするには、次のコマンドを実行してアプリケーション・バージョン・ルーティングを初期化します。

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

HTTP遅延フォルトの注入

遅延障害を注入するには、次の手順に従います。

  • ユーザーjasonからのトラフィックを遅延させるフォルト・インジェクション・ルールを作成します。次のコマンドは、reviews:v2とユーザーjasonの評価マイクロサービスの間に7秒の遅延を注入します。
    kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml
    ノート

    reviews:v2サービスには、評価サービスへのコールに対する10秒のハードコードされた接続タイムアウトがあります。7秒の遅延では、エンドツーエンドのフローがエラーなしで続行されることを想定します。
  • Bookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。
    遅延エラーを示すBookinfoページのスナップショット

    Bookinfoホーム・ページは、約7秒でエラーなしでロードされます。ただし、レビュー・セクションにエラー・メッセージが表示されます: 「申し訳ありません。このマニュアルでは、製品レビューは現在使用できません」。アプリケーション・コードにバグが存在します。productpagereviewsサービス間のハードコードされたタイムアウトにより、6秒の遅延、3秒に1回の再試行が発生します。その結果、reviewsへのproductpageコールは途中でタイムアウトし、6秒後にエラーがスローされます。

    バグを修正するには、productpagereviewsサービス・タイムアウトに増やすか、reviewsratingsタイムアウトに減らして3秒未満にします。

  • ユーザーjasonratingsサービスに2秒の遅延を追加して、バグを修正します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: ratings
    spec:
      hosts:
      - ratings
      http:
      - match:
        - headers:
            end-user:
              exact: jason
        fault:
          delay:
            percentage:
              value: 100.0
            fixedDelay: 2s
        route:
        - destination:
            host: ratings
            subset: v1
      - route:
        - destination:
            host: ratings
            subset: v1
    EOF
  • バグが修正されたら、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開き、Bookinfo Webページを表示します。評価星が表示された状態でjasonとしてサインインします。
    Bookinfoページのスナップショット(エラーなし)

HTTP中断フォルトの注入

中断フォルトを注入するには、次のステップを実行します。

  1. ユーザーjasonのHTTP中断レスポンスを送信するフォルト・インジェクション・ルールを作成します:
    kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml
  2. Bookinfo Webページを表示するには、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開きます。ユーザーjasonとしてログインします。ratingsサービスが使用できないことを示すメッセージが表示されます。
    評価サービスが使用不可のBookinfoページのスクリーンショット

    ユーザーjasonからログアウトするか、他のユーザーでログインしてエラー・メッセージを表示しません。

    エラーのないBookinfoページのスクリーンショット

回路遮断器の作成

回路遮断により、障害の影響、遅延スパイク、およびネットワークの特殊性によるその他の望ましくない影響を制限するアプリケーションを記述できます。回路遮断器の詳細は、こちらを参照してください。

  1. 宛先ルールを作成して、製品サービスを呼び出すときに回路遮断設定を適用します。次のルールは、最大接続数を1つ以下に設定し、最大1つのHTTP保留リクエストを持ちます。また、ルールはホストを1秒ごとにスキャンするように構成します。5XXエラーコードで1回失敗するホストは、3分間イジェクトされます。また、アップストリーム・サービスのロード・バランシング・プール内のホストの100%がイジェクトされます。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productpage
    spec:
      host: productpage
      trafficPolicy:
        connectionPool:
          tcp:
            maxConnections: 1
          http:
            http1MaxPendingRequests: 1
            maxRequestsPerConnection: 1
        outlierDetection:
          consecutive5xxErrors: 1
          interval: 1s
          baseEjectionTime: 3m
          maxEjectionPercent: 100
      subsets:
      - name: v1
        labels:
          version: v1
    EOF
  2. すべてのトラフィックを各マイクロサービスのv1バージョンにルーティングします。
    kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
  3. 製品サービスにトラフィックを送信するクライアントを作成します。Fortioでは、送信HTTPコールの接続数、同時実行性および遅延を制御できます。自動サイドカー・インジェクションを有効にした場合は、fortioサービスをデプロイします。
    kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml
    または、fortioアプリケーションをデプロイする前に、サイドカーを手動で注入します。
    kubectl apply -f <(istioctl kube-inject -f samples/httpbin/sample-client/fortio-deploy.yaml)
  4. クライアント・ポッドにログインし、fortioツールを使用してproductpageをコールし、次のコマンドを使用してレスポンス・ステータス・コードが200であることを確認します。
    export FORTIO_POD=$(kubectl get pods -l app=fortio -o 'jsonpath={.items[0].metadata.name}')
    kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio curl http://productpage:9080
    
    次の出力が生成されます。
    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 1683
    server: envoy
    date: Tue, 07 Sep 2021 11:01:02 GMT
    x-envoy-upstream-service-time: 5
  5. 2つの同時接続(-c 2)でサービスをコールし、20リクエスト(-n 20)を送信します。興味深いことに、16のリクエストパススルーと4が失敗します。
    kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://productpage:9080
    このコマンドを実行すると、次のような出力が生成されます。
    11:03:43 I logger.go:127> Log level is now 3 Warning (was 2 Info)
    Fortio 1.11.3 running at 0 queries per second, 128->128 procs, for 20 calls: http://productpage:9080
    Starting at max qps with 2 thread(s) [gomax 128] for exactly 20 calls (10 per thread + 0)
    11:03:43 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:03:43 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:03:43 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:03:43 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    Ended after 51.340006ms : 20 calls. qps=389.56
    Aggregated Function Time : count 20 avg 0.0045031997 +/- 0.002036 min 0.000387421 max 0.007704444 sum 0.090063995
    # range, mid point, percentile, count
    >= 0.000387421 <= 0.001 , 0.000693711 , 15.00, 3
    > 0.003 <= 0.004 , 0.0035 , 20.00, 1
    > 0.004 <= 0.005 , 0.0045 , 65.00, 9
    > 0.005 <= 0.006 , 0.0055 , 75.00, 2
    > 0.006 <= 0.007 , 0.0065 , 95.00, 4
    > 0.007 <= 0.00770444 , 0.00735222 , 100.00, 1
    # target 50% 0.00466667
    # target 75% 0.006
    # target 90% 0.00675
    # target 99% 0.00756356
    # target 99.9% 0.00769036
    Sockets used: 5 (for perfect keepalive, would be 2)
    Jitter: false
    Code 200 : 16 (80.0 %)
    Code 503 : 4 (20.0 %)
    Response Header Sizes : count 20 avg 133.6 +/- 66.8 min 0 max 167 sum 2672
    Response Body/Total Sizes : count 20 avg 1528.2 +/- 643.6 min 241 max 1850 sum 30564
    All done 20 calls (plus 0 warmup) 4.503 ms avg, 389.6 qps
  6. 同時接続数を3に増やします。
    kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://productpage:9080
    リクエストの26.7%のみが成功し、回路が切断されて残りがトラップされます。
    11:10:19 I logger.go:127> Log level is now 3 Warning (was 2 Info)
    Fortio 1.11.3 running at 0 queries per second, 128->128 procs, for 30 calls: http://productpage:9080
    Starting at max qps with 3 thread(s) [gomax 128] for exactly 30 calls (10 per thread + 0)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    11:10:19 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
    Ended after 28.105508ms : 30 calls. qps=1067.4
    Aggregated Function Time : count 30 avg 0.0024256753 +/- 0.003264 min 0.000261072 max 0.010510116 sum 0.07277026
    # range, mid point, percentile, count
    >= 0.000261072 <= 0.001 , 0.000630536 , 66.67, 20
    > 0.001 <= 0.002 , 0.0015 , 73.33, 2
    > 0.005 <= 0.006 , 0.0055 , 76.67, 1
    > 0.006 <= 0.007 , 0.0065 , 83.33, 2
    > 0.007 <= 0.008 , 0.0075 , 93.33, 3
    > 0.009 <= 0.01 , 0.0095 , 96.67, 1
    > 0.01 <= 0.0105101 , 0.0102551 , 100.00, 1
    # target 50% 0.000805545
    # target 75% 0.0055
    # target 90% 0.00766667
    # target 99% 0.0103571
    # target 99.9% 0.0104948
    Sockets used: 25 (for perfect keepalive, would be 3)
    Jitter: false
    Code 200 : 8 (26.7 %)
    Code 503 : 22 (73.3 %)
    Response Header Sizes : count 30 avg 44.533333 +/- 73.85 min 0 max 167 sum 1336
    Response Body/Total Sizes : count 30 avg 670.06667 +/- 711.5 min 241 max 1850 sum 20102
    All done 30 calls (plus 0 warmup) 2.426 ms avg, 1067.4 qps
  7. istio-proxy統計を問い合せて、詳細情報を取得します。
    kubectl exec "$FORTIO_POD" -c istio-proxy -- pilot-agent request GET stats | grep productpage | grep pending
    回路遮断は、メトリックupstream_rq_pending_overflowを参照して32コールにフラグを付けます。
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.circuit_breakers.default.remaining_pending: 1
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.circuit_breakers.default.rq_pending_open: 0
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.circuit_breakers.high.rq_pending_open: 0
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.upstream_rq_pending_active: 0
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.upstream_rq_pending_failure_eject: 0
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.upstream_rq_pending_overflow: 32
    cluster.outbound|9080|v1|productpage.default.svc.cluster.local.upstream_rq_pending_total: 39
  8. クライアントをクリーンアップします。
    kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
    kubectl delete deploy fortio-deploy
    kubectl delete svc fortio

ミラー化

トラフィック・ミラーリング(シャドウイングとも呼ばれる)により、チームはできるだけ少ないリスクで本番環境に変更を加えることができます。ミラー化では、ライブ・トラフィックのコピーがミラー化サービスに送信されます。ミラー化されたトラフィックは、プライマリ・サービスのクリティカル・リクエスト・パスの外部で発生します。

  1. すべてのトラフィックを各マイクロサービスのv1バージョンにルーティングします。
    kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
  2. トラフィックをミラー化するようにルート・ルールをreviews:v2に変更します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: reviews
    spec:
      hosts:
        - reviews
      http:
      - route:
        - destination:
            host: reviews
            subset: v1
          weight: 100
        mirror:
          host: reviews
          subset: v2
        mirrorPercentage:
          value: 100.0
    EOF

    前のルート・ルールは、トラフィックの100%をreviews:v1に送信し、同じトラフィックの100%をreviews:v2サービスにミラー化します。

    トラフィックがミラー化されると、リクエストは、ホスト/認可ヘッダーに-shadowが付加されたミラー化サービスに送信されます。たとえば、レビューはreviews-shadow.Mirroredリクエストになり、「fire and forget」とみなされます。ミラー化されたレスポンスは破棄されます。

    すべてのリクエストをミラー化するかわりに、mirrorPercentageフィールドの値フィールドを変更してトラフィックの割合をミラー化します。このフィールドがない場合、すべてのトラフィックがミラー化されます。

  3. ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageをリフレッシュして、一部のトラフィックを送信します。
  4. reviews:v1サービスのログ。v1サービスは評価サービスをコールしません。
    reviews:v1サービスのスクリーンショット
  5. reviews:v2ミラー化サービスのログ。v2サービスでは、ヘッダーに-shadowが付加されます。
    -shadowを使用したreviews:v2サービスのスクリーンショット

ゲートウェイの管理

Gatewayは、受信または送信HTTP/TCP接続を受信するメッシュの端で動作するロード・バランサを表します。ゲートウェイ構成は、サービス・ワークロードとともに実行されているサイドカーのEnvoyプロキシではなく、メッシュの端で実行されているスタンドアロンのEnvoyプロキシに適用されます。Istioには、事前構成されたゲートウェイ・プロキシ・デプロイメントistio-ingressgatewayおよびistio-egressgatewayがいくつか用意されています。

インストールの一部としてIstioゲートウェイを設定していない場合は、次のコマンドを実行してインストールします。
istioctl install

このコマンドは、ゲートウェイを含むデフォルト設定を使用してIstioをデプロイします。詳細は、ここを参照してください

ノート

これらの手順を使用して、INGRESS_HOSTおよびINGRESS_PORTを確認します。

Istio Gatewayを使用したイングレスの構成

イングレス・ゲートウェイは、公開されているポートおよびプロトコルを構成しますが、Kubernetesイングレス・リソースとは異なり、トラフィック・ルーティング構成は含まれません。イングレス・トラフィックのトラフィック・ルーティングは、かわりにIstioルーティング・ルールを使用して構成されます。Istioイングレスの詳細は、こちらを参照してください。

ノート

Bookinfoアプリケーションをすでにデプロイしている場合は、次のステップは必要ありません。
  1. HTTPトラフィックのポート80に構成するIstioゲートウェイを作成します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: bookinfo-gateway
    spec:
      selector:
        istio: ingressgateway # use istio default controller
      servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
            - "*"
    EOF
  2. ゲートウェイ経由で入力するトラフィックのルートを構成します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: bookinfo
    spec:
      hosts:
      - "*"
      gateways:
      - bookinfo-gateway
      http:
      - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
        route:
        - destination:
            host: productpage
            port:
              number: 9080
    EOF
  3. Bookinfoアプリケーションをデプロイするには、「IstioおよびOKEのインストール」ページのBookinfoアプリケーションの実行に関する項を参照してください。
  4. curlを使用してproductpageサービスにアクセスします。
    curl -s -I http://$INGRESS_HOST:$INGRESS_PORT/productpage

    このコマンドにより、次の出力が生成されます。

    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 4183
    server: istio-envoy
    date: Tue, 07 Sep 2021 13:48:39 GMT
    x-envoy-upstream-service-time: 36
  5. 明示的に公開されていないその他のURLにアクセスします。HTTP 404エラーが表示されます。
    curl -s -I http://$INGRESS_HOST:$INGRESS_PORT/any

    このコマンドにより、次の出力が生成されます。

    HTTP/1.1 404 Not Found
    date: Tue, 07 Sep 2021 13:49:45 GMT
    server: istio-envoy
    transfer-encoding: chunked
  6. ゲートウェイ内の明示的なホストの場合は、-Hフラグを使用してホストHTTPヘッダーを設定します。このフラグは、イングレス・ゲートウェイおよび仮想サービスがホストを処理するように構成されているため必要です。たとえば、ホストはexample.comで、名前はゲートウェイと仮想サービスの両方で指定されます。
    curl -s -I -HHost:example.com http://$INGRESS_HOST:$INGRESS_PORT/productpage
  7. また、ブラウザでURL http://${INGRESS_HOST}:${INGRESS_PORT}/productpageを開いて、Bookinfo Webページを表示します。

Kubernetesイングレス・リソースを使用したイングレスの構成

リーダーは、Bookinfoアプリケーションがクラスタにデプロイされていることを前提としています。Bookinfoアプリケーションをデプロイするには、「IstioおよびOKEのインストール」ページのBookinfoアプリケーションの実行に関する項を参照してください。

  1. 構成がすでに適用されている場合は、Istioゲートウェイを削除します。
    kubectl delete -f samples/bookinfo/networking/bookinfo-gateway.yaml
  2. HTTPトラフィックのポート80にイングレス・リソースを作成します。
    kubectl apply -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: istio
      name: ingress
    spec:
      rules:
      - http:
         paths:
         - path: /productpage
           pathType: Prefix
           backend:
              service:
                name: productpage
                port:
                  number: 9080
    EOF

    このIngressを処理するようにIstioゲートウェイ・コントローラに指示するには、kubernetes.io/ingress.class注釈が必要です。

  3. 前の項の手順に従って、Bookinfoアプリケーションにアクセスしていることを確認します。
  4. リソースを削除し、さらにタスクを行うためにIstioゲートウェイを有効にします。
    kubectl delete ingress ingress
    kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

エグレスを使用した外部サービスへのアクセス

デフォルトでは、Istio対応ポッドからのすべてのアウトバウンド・トラフィックはサイドカー・プロキシにリダイレクトされ、Istioは不明なサービスに対するリクエストを通過するようにEnvoyプロキシを構成します。Istioは、構成フィールドmeshConfig.outboundTrafficPolicy.modeを介して外部サービスのサイドカー処理を構成します。このオプションを次のように設定した場合:

  • ALLOW_ANY (デフォルト): Istioプロキシでは、不明なサービスへのコールがパス・スルーされます。
  • REGISTRY_ONLY: Istioプロキシは、メッシュ内でHTTPサービスまたはサービス・エントリが定義されていないホストをブロックします。

リーダーは、Bookinfoアプリケーションがクラスタにデプロイされていることを前提としています。そうでない場合は、ステップに従ってBookinfoアプリケーションをデプロイします。

外部サービスへのEnvoyパススルーの管理

外部サービスへのパススルーを有効にするには、次のステップを実行します。

  1. istioctlを使用して、meshConfig.outboundTrafficPolicy.modeオプションをALLOW_ANYに変更します。
    istioctl install --set meshConfig.outboundTrafficPolicy.mode=ALLOW_ANY
    ノート

    このステップは、インストール中にオプションを明示的にREGISTRY_ONLYに設定した場合にのみ必要です。
  2. 成功した200レスポンスを確認するには、SOURCE_PODから外部サービスにリクエストします。
    export SOURCE_POD=$(kubectl get pod -l app=ratings -o jsonpath='{.items..metadata.name}')
    kubectl exec $SOURCE_POD -c ratings -- curl -sI http://httpbin.org/headers | grep "HTTP"
    このコマンドにより、次の出力が生成されます。
    HTTP/1.1 200 OK

しかし、このアプローチの欠点は、外部サービスへのトラフィックのIstioの監視と制御が失われることです。

外部サービスへのアクセスの制御[推奨]

外部サービスへの制御アクセスを設定するには、次のステップに従います。

  1. meshConfig.outboundTrafficPolicy.modeオプションをREGISTRY_ONLYに変更します。このステップは、インストール中にオプションを明示的にREGISTRY_ONLYに設定していない場合にのみ必要です。
  2. 「Envoy Passthrough to External Services」セクションの手順1のみに従ってください。ここで変更するのは、ALLOW_ANYREGISTRY_ONLYに置き換えることのみです。
  3. 外部サービスがブロックされていることを確認するには、SOURCE_PODから外部HTTPSサービスへのリクエストをいくつか行います。構成の変更は伝播に数秒かかるため、正常な接続が可能です。数秒待ってから、最後のコマンドを再試行してください。
    export SOURCE_POD=$(kubectl get pod -l app=ratings -o jsonpath='{.items..metadata.name}')
    kubectl exec $SOURCE_POD -c ratings -- curl -sI http://httpbin.org/headers | grep "HTTP"

    このコマンドにより、次の出力が生成されます。

    HTTP/1.1 502 Bad Gateway
  4. 外部HTTPサービスへのアクセスを許可するServiceEntryを作成します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: ServiceEntry
    metadata:
      name: httpbin-ext
    spec:
      hosts:
      - httpbin.org
      ports:
      - number: 80
        name: http
        protocol: HTTP
      resolution: DNS
      location: MESH_EXTERNAL
    EOF
  5. SOURCE_PODから外部HTTPサービスにリクエストします。Istioサイドカー・プロキシによって追加されたヘッダー(X-Envoy-Decorator-Operation)を確認します。
    kubectl exec $SOURCE_POD -c ratings -- curl -sI http://httpbin.org/headers | grep "HTTP"
    このコマンドにより、次の出力が生成されます。
    HTTP/1.1 200 OK

    grepコマンドを削除して、すべてのヘッダーを表示します。

    kubectl exec $SOURCE_POD -c ratings -- curl -sS http://httpbin.org/headers

    このコマンドにより、次の出力が生成されます。

    {
      "headers": {
        "Accept": "*/*",
        "Host": "httpbin.org",
        "User-Agent": "curl/7.52.1",
        "X-Amzn-Trace-Id": "Root=1-61384b41-2d3cf8b5571ba7504ab9a834",
        "X-B3-Sampled": "0",
        "X-B3-Spanid": "6983ef0cec914f83",
        "X-B3-Traceid": "d510c4d190cb099d6983ef0cec914f83",
        "X-Envoy-Attempt-Count": "1",
        "X-Envoy-Decorator-Operation": "httpbin.org:80/*",
        "X-Envoy-Peer-Metadata": "ChsKDkFQUF9DT05UQUlORVJTEgkaB3JhdGluZ3MKGgoKQ0xVU1RFUl9JRBIMGgpLdWJlcm5ldGVzChkKDUlTVElPX1ZFUlNJT04SCBoGMS4xMS4xCtQBCgZMQUJFTFMSyQEqxgEKEAoDYXBwEgkaB3JhdGluZ3MKIAoRcG9kLXRlbXBsYXRlLWhhc2gSCxoJYzk5NDdiOTlmCiQKGXNlY3VyaXR5LmlzdGlvLmlvL3Rsc01vZGUSBxoFaXN0aW8KLAofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIJGgdyYXRpbmdzCisKI3NlcnZpY2UuaXN0aW8uaW8vY2Fub25pY2FsLXJldmlzaW9uEgQaAnYxCg8KB3ZlcnNpb24SBBoCdjEKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCiQKBE5BTUUSHBoacmF0aW5ncy12MS1jOTk0N2I5OWYtbGN4bHQKFgoJTkFNRVNQQUNFEgkaB2RlZmF1bHQKTgoFT1dORVISRRpDa3ViZXJuZXRlczovL2FwaXMvYXBwcy92MS9uYW1lc3BhY2VzL2RlZmF1bHQvZGVwbG95bWVudHMvcmF0aW5ncy12MQoXChFQTEFURk9STV9NRVRBREFUQRICKgAKHQoNV09SS0xPQURfTkFNRRIMGgpyYXRpbmdzLXYx",
        "X-Envoy-Peer-Metadata-Id": "sidecar~10.244.0.11~ratings-v1-c9947b99f-lcxlt.default~default.svc.cluster.local"
      }
    }
  6. HTTPS呼び出しにアクセスするには、サービスエントリの作成時にポートとプロトコルを置き換えます。
  7. このアプローチでは、タイムアウトやフォルト・インジェクションなどの外部サービス・トラフィック管理機能が追加されます。次のリクエストは、約5秒で200 (OK)を返します。
    kubectl exec $SOURCE_POD -c ratings -- curl http://httpbin.org/delay/5
    kubectlを使用して、httpbin.org外部サービスへのコールで3秒間のタイムアウトを設定します。
    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: httpbin-ext
    spec:
      hosts:
        - httpbin.org
      http:
      - timeout: 3s
        route:
          - destination:
              host: httpbin.org
            weight: 100
    EOF
    今回は、3秒後にタイムアウトが表示されます。httpbin.orgは5秒待機していましたが、Istioはリクエストを3秒で停止しました。
    kubectl exec $SOURCE_POD -c ratings -- curl http://httpbin.org/delay/5
  8. 将来のタスクのためにリソースをクリーンアップします。
    kubectl delete serviceentry httpbin-ext
    kubectl delete virtualservice httpbin-ext --ignore-not-found=true

外部サービスへのアクセスの指示

このアプローチでは、Istioサイドカー・プロキシがバイパスされ、サービスは外部サーバーに直接アクセスできます。ただし、この方法でプロキシを構成する場合は、クラスタ・プロバイダ固有の知識および構成が必要です。最初のアプローチと同様に、外部サービスへのアクセスの監視を失い、外部サービスへのトラフィックにIstio機能を適用できません。これらのステップに従って、外部サービスへの直接アクセスを提供します。

Istioの保護

Istioのセキュリティ機能は、強固なアイデンティティ、強力なポリシー、透過的なTLS暗号化、認証、認可、監査(AAA)ツールを提供し、サービスとデータを保護します。

認証の構成

Istioは、トランスポート認証のフルスタック・ソリューションとして相互TLSを提供します。これは、サービス・コードの変更を必要とせずに有効化されます。

sleepおよびhttpbinサービスをデフォルト・ネームスペースにデプロイします。
kubectl apply -f samples/sleep/sleep.yaml
kubectl apply -f samples/httpbin/httpbin.yaml

デフォルトでは、Istioは複数のタスクを実行します。Istioは、Istioプロキシに移行されたサーバー・ワークロードを追跡します。Istioは、相互TLSトラフィックをこれらのワークロードに自動的に送信するようにクライアント・プロキシを構成します。Istioは、サイドカーなしでワークロードにプレーン・テキスト・トラフィックを送信します。

証明書が送信されたことを確認するには、sleepポッドからhttpbinポッドにリクエストを送信し、X-Forwarded-Client-Certヘッダーを探します。
kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl -s http://httpbin.default:8000/headers -s | grep X-Forwarded-Client-Cert | sed 's/Hash=[a-z0-9]*;/Hash=<redacted>;/'
サイドカーを有効にせずに、sleepおよびhttpbinサービスの別のインスタンスをデプロイします。
kubectl create ns legacy
kubectl apply -f samples/sleep/sleep.yaml -n legacy
kubectl apply -f samples/httpbin/httpbin.yaml -n legacy
デフォルト・ネームスペースのsleepポッドからレガシー・ネームスペースのhttpbinポッドへのリクエストは、宛先がサイドカー対応ではないためプレーン・テキストです。次のコマンドを実行して、プレーン・テキストが送信されていることを確認します。
kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl http://httpbin.legacy:8000/headers -s | grep X-Forwarded-Client-Cert
レガシー・ネームスペースのsleepポッドからデフォルト・ネームスペースのhttpbinへのリクエストも、プレーン・テキスト接続で成功します。次のコマンドを使用して検証できます。
kubectl exec "$(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name})" -n legacy -c sleep -- curl http://httpbin.default:8000/headers
メッシュ全体の非相互TLSトラフィックを防ぐには、相互TLSモードをSTRICTに設定して、メッシュ全体のピア認証ポリシーを設定します。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT
EOF
相互TLSモードがSTRICTに設定されている場合、レガシー・ネームスペースのsleepポッドからデフォルト・ネームスペースのhttpbinへの接続は機能しなくなりました。
kubectl exec "$(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name})" -n legacy -c sleep -- curl http://httpbin.default:8000/headers
CRを削除して、STRICTピア認証設定を元に戻します。
kubectl delete peerauthentication -n istio-system default

グローバル相互TLS設定に加えて、ネームスペースまたはワークロード・レベルで設定することもできます。認証構成の詳細は、Istioのドキュメントを参照してください。

認可の構成

Istioでは、アプリケーションの認可ポリシーを構成できます。

最初に、ワークロードへのすべてのリクエストを拒否する単純なallow-nothingポリシーを構成し、ワークロードへのより多くのアクセスを段階的かつ段階的に付与します。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
  namespace: default
spec:
  {}
EOF

ブラウザでBookinfo製品ページを開きます。deny-allポリシーが意図したとおりに機能していることを確認するRBAC: access deniedエラーが表示されます。

次のコマンドを使用して、すべてのユーザーおよびワークロードに製品ページへのアクセス権を付与するポリシーを作成します。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: "productpage-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: productpage
  action: ALLOW
  rules:
  - to:
    - operation:
        methods: ["GET"]
EOF

「Bookinfoサンプル」ページが表示されますが、productpageサービスは詳細およびレビュー・ページにアクセスできません。

次のポリシーを追加して、productpageワークロードに詳細へのアクセス権を付与し、ワークロードをレビューし、ratingsワークロードへのワークロード・アクセスをレビューします。

詳細ビューアの設定

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: "details-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: details
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
    to:
    - operation:
        methods: ["GET"]
EOF

レビュービューアを設定

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: "reviews-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: reviews
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
    to:
    - operation:
        methods: ["GET"]
EOF

評価ビューアの設定

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: "ratings-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: ratings
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-reviews"]
    to:
    - operation:
        methods: ["GET"]
EOF

エラーなくブラウザから製品ページを表示します。

適用されたポリシーを元に戻すには、次のコマンドを入力します。

kubectl delete authorizationpolicy.security.istio.io/allow-nothing
kubectl delete authorizationpolicy.security.istio.io/productpage-viewer
kubectl delete authorizationpolicy.security.istio.io/details-viewer
kubectl delete authorizationpolicy.security.istio.io/reviews-viewer
kubectl delete authorizationpolicy.security.istio.io/ratings-viewer

TLSを使用したゲートウェイの保護

シンプルまたは相互TLSを使用して、BookinfoアプリケーションをセキュアなHTTPSサービスとして公開できます。サービスの証明書に署名するには、ルート証明書と秘密鍵を作成します。

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt

productpage.bookinfo.comの証明書および秘密キーを作成します。

openssl req -out bookinfo.example.com.csr -newkey rsa:2048 -nodes -keyout bookinfo.example.com.key -subj "/CN=bookinfo.example.com/O=bookinfo organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in bookinfo.example.com.csr -out bookinfo.example.com.crt

Bookinfoアプリケーションをデプロイしたことを確認します。イングレス・ゲートウェイ証明書のシークレットを作成します。

kubectl create -n istio-system secret tls bookinfo-credential --key=bookinfo.example.com.key --cert=bookinfo.example.com.crt

セキュアなポートを含めるようにBookinfoゲートウェイを更新します。

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: bookinfo-gateway-https
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: bookinfo-credential
    hosts:
    - bookinfo.example.com
EOF

Bookinfo宛先ルールを作成します(まだ作成されていない場合)。

kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

ゲートウェイにバインドされた仮想サービスを作成します。

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: bookinfo-https
spec:
  hosts:
  - "bookinfo.example.com"
  gateways:
  - bookinfo-gateway-https
  http:
  - route:
    - destination:
        host: productpage
        subset: v1
EOF

次のcurlコマンドを使用して、ゲートウェイへのTLS接続を確認できます。

curl -v -HHost:bookinfo.example.com --resolve "bookinfo.example.com:443:$INGRESS_HOST" --cacert example.com.crt "https://bookinfo.example.com/productpage"