イングレスゲートウェイ

Istioは、Kubernetes Ingress リソースのサポートに加えて、Istio Gateway または Kubernetes Gateway リソースを使用してイングレストラフィックを設定することもできます。GatewayIngress よりも広範なカスタマイズと柔軟性を提供し、モニタリングやルートルールなどのIstioの機能をクラスタに流入するトラフィックに適用できます。

このタスクでは、Gateway を使用してサービスメッシュの外部にサービスを公開するようにIstioを設定する方法について説明します。

始める前に

  • インストールガイドの手順に従ってIstioをセットアップします。

  • イングレストラフィックのターゲットサービスとして機能する httpbin サンプルを開始します。

    Zip
    $ kubectl apply -f samples/httpbin/httpbin.yaml

    このドキュメントでは、ゲートウェイを使用して「Kubernetesクラスタ」へのイングレストラフィックを制御する方法を示しているため、サイドカーインジェクションを有効または無効にして httpbin サービスを開始できます(つまり、ターゲットサービスはIstioメッシュの内部または外部のいずれかに配置できます)。

ゲートウェイを使用したイングレスの設定

イングレス Gateway は、メッシュのエッジで動作し、着信HTTP/TCP接続を受信するロードバランサーを記述します。公開ポート、プロトコルなどを設定しますが、Kubernetes Ingressリソース とは異なり、トラフィックルーティング設定は含まれていません。イングレストラフィックのトラフィックルーティングは、代わりに、内部サービスリクエストの場合とまったく同じ方法で、ルーティングルールを使用して設定されます。

HTTPトラフィック用にポート80で Gateway を設定する方法を見てみましょう。

Istio Gateway を作成します。

$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: Gateway metadata: name: httpbin-gateway spec: # The selector matches the ingress gateway pod labels. # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress" selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "httpbin.example.com" EOF

Gateway を介して入ってくるトラフィックのルートを設定します。

$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: httpbin spec: hosts: - "httpbin.example.com" gateways: - httpbin-gateway http: - match: - uri: prefix: /status - uri: prefix: /delay route: - destination: port: number: 8000 host: httpbin EOF

これで、パス /status/delay のトラフィックを許可する2つのルートルールを含む、httpbin サービスの 仮想サービス 設定が作成されました。

gateways リストは、httpbin-gateway を介したリクエストのみが許可されることを指定します。その他のすべての外部リクエストは、404レスポンスで拒否されます。

イングレスのIPとポートの確認

すべての Gateway は、LoadBalancerタイプのサービス によって支えられています。このサービスの外部ロードバランサーのIPとポートは、ゲートウェイへのアクセスに使用されます。LoadBalancer タイプのKubernetesサービスは、ほとんどのクラウドプラットフォームで実行されているクラスタではデフォルトでサポートされていますが、一部の環境(例:テスト)では、次の操作が必要になる場合があります。

  • minikube - 別のターミナルで次のコマンドを実行して、外部ロードバランサーを起動します。

    $ minikube tunnel
  • kind - LoadBalancer タイプのサービスを動作させるには、MetalLBのセットアップガイド に従ってください。

  • その他のプラットフォーム - MetalLB を使用して、LoadBalancer サービスの EXTERNAL-IP を取得できる場合があります。

便宜上、イングレスのIPとポートを環境変数に格納し、後続の手順で使用します。以下の手順に従って、INGRESS_HOST および INGRESS_PORT 環境変数を設定します。

Istioイングレスゲートウェイがクラスタ内に配置されている名前と名前空間に、次の環境変数を設定します。

$ export INGRESS_NAME=istio-ingressgateway $ export INGRESS_NS=istio-system

Kubernetesクラスタが外部ロードバランサーをサポートする環境にあるかどうかを判断するには、次のコマンドを実行します。

$ kubectl get svc "$INGRESS_NAME" -n "$INGRESS_NS"
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 172.21.109.129 130.211.10.121 ... 17h

EXTERNAL-IP 値が設定されている場合、環境にはイングレスゲートウェイに使用できる外部ロードバランサーがあります。EXTERNAL-IP 値が <none>(または永久に <pending>)の場合、環境はイングレスゲートウェイの外部ロードバランサーを提供していません。

環境が外部ロードバランサーをサポートしていない場合は、イングレスゲートウェイにノードポートを使用してアクセスすることを試すことができます。それ以外の場合は、次のコマンドを使用してイングレスのIPとポートを設定します。

$ export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}') $ export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http2")].port}') $ export SECURE_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="https")].port}') $ export TCP_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')

イングレスサービスへのアクセス

  1. curl を使用して httpbin サービスにアクセスします。

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
    ... HTTP/1.1 200 OK ... server: istio-envoy ...

    -H フラグを使用して、Host HTTPヘッダーを「httpbin.example.com」に設定していることに注意してください。これは、イングレス Gateway が「httpbin.example.com」を処理するように設定されていますが、テスト環境ではそのホストのDNSバインディングがなく、リクエストをイングレスIPに送信しているだけなので、必要です。

  2. 明示的に公開されていない他のURLにアクセスします。HTTP 404エラーが表示されるはずです。

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/headers"
    HTTP/1.1 404 Not Found ...

ブラウザを使用したイングレスサービスへのアクセス

curl のようにブラウザに Host ヘッダーを渡すことができないため、ブラウザで httpbin サービスのURLを入力しても機能しません。実際の状況では、リクエストされたホストを正しく設定し、DNSで解決できるようにするため、これは問題になりません。したがって、URLにはホストのドメイン名を使用します(例:https://httpbin.example.com/status/200)。

簡単なテストとデモでは、次のようにこの問題を回避できます。

Gateway および VirtualService 設定のホストにワイルドカード * 値を使用します。たとえば、イングレス設定を次のように変更します。

$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: Gateway metadata: name: httpbin-gateway spec: # The selector matches the ingress gateway pod labels. # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress" selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: httpbin spec: hosts: - "*" gateways: - httpbin-gateway http: - match: - uri: prefix: /headers route: - destination: port: number: 8000 host: httpbin EOF

その後、ブラウザのURLで $INGRESS_HOST:$INGRESS_PORT を使用できます。たとえば、http://$INGRESS_HOST:$INGRESS_PORT/headers は、ブラウザが送信するすべてのヘッダーを表示します。

何が起こったかの理解

Gateway 設定リソースにより、外部トラフィックがIstioサービスメッシュに流入し、Istioのトラフィック管理およびポリシー機能をエッジサービスで使用できるようになります。

前の手順では、サービスメッシュ内にサービスを作成し、サービスのHTTPエンドポイントを外部トラフィックに公開しました。

イングレスゲートウェイサービスのノードポートの使用

環境が外部ロードバランサーをサポートしていない場合でも、istio-ingressgateway サービスの ノードポート を使用することで、Istioの一部の機能を試すことができます。

イングレスポートを設定します。

$ export INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}') $ export SECURE_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}') $ export TCP_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')

イングレスIPの設定は、クラスタプロバイダーによって異なります。

  1. GKE

    $ export INGRESS_HOST=worker-node-address

    ingressgateway サービスのポートへのTCPトラフィックを許可するファイアウォールルールを作成する必要があります。HTTPポート、セキュアポート(HTTPS)、またはその両方のトラフィックを許可するには、次のコマンドを実行します。

    $ gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT" $ gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"
  2. IBM Cloud Kubernetes Service

    $ ibmcloud ks workers --cluster cluster-name-or-id $ export INGRESS_HOST=public-IP-of-one-of-the-worker-nodes
  3. Docker For Desktop

    $ export INGRESS_HOST=127.0.0.1
  4. その他の環境

    $ export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n "${INGRESS_NS}" -o jsonpath='{.items[0].status.hostIP}')

トラブルシューティング

  1. INGRESS_HOST および INGRESS_PORT 環境変数の値を調べます。次のコマンドの出力に従って、有効な値が設定されていることを確認します。

    $ kubectl get svc -n istio-system $ echo "INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT"
  2. 同じポートに他のIstioイングレスゲートウェイが定義されていないことを確認します。

    $ kubectl get gateway --all-namespaces
  3. 同じIPとポートにKubernetes Ingressリソースが定義されていないことを確認します。

    $ kubectl get ingress --all-namespaces
  4. 外部ロードバランサーがあり、それが機能しない場合は、ノードポートを使用してゲートウェイにアクセスすることを試してください。

クリーンアップ

Gateway および VirtualService 設定を削除し、httpbin サービスをシャットダウンします。

Zip
$ kubectl delete gateway httpbin-gateway $ kubectl delete virtualservice httpbin $ kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml
この情報は役に立ちましたか?
改善のための提案はありますか?

フィードバックありがとうございます!