外部サービスに対するプロキシとしての Istio

外部サービスに対するプロキシとして機能するように Istio イングレスゲートウェイを設定します。

2019年10月15日 | Vadim Eisenberg - IBM 著

イングレストラフィックの制御TLS 終端なしのイングレスゲートウェイ のタスクでは、メッシュ内のサービスを外部トラフィックに公開するようにイングレスゲートウェイを設定する方法について説明しています。サービスは HTTP または HTTPS にすることができます。HTTPS の場合、ゲートウェイは TLS を終端せずにトラフィックを通過させます。

このブログ記事では、メッシュ内のアプリケーションではなく、外部サービスへのアクセスを有効にするために、Istio の同じイングレスゲートウェイメカニズムを使用する方法について説明します。このようにすることで、Istio は全体としてプロキシサーバーとして機能し、可観測性、トラフィック管理、ポリシー適用という付加価値が得られます。

このブログ記事では、httpbin.orgedition.cnn.com という HTTP および HTTPS の外部サービスへのアクセスを設定する方法を示します。

イングレスゲートウェイを設定する

  1. 80 および 443 ポートを設定する servers: セクションを含むイングレスゲートウェイを定義します。ポート 443tls:mode:PASSTHROUGH に設定されていることを確認します。これにより、ゲートウェイは TLS を終端せずにイングレストラフィックをそのまま通過させます。

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: proxy
    spec:
      selector:
        istio: ingressgateway # use istio default ingress gateway
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - httpbin.org
      - port:
          number: 443
          name: tls
          protocol: TLS
        tls:
          mode: PASSTHROUGH
        hosts:
        - edition.cnn.com
    EOF
    
  2. httpbin.org および edition.cnn.com サービスに対してサービスエントリを作成し、イングレスゲートウェイからアクセスできるようにします。

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: httpbin-ext
    spec:
      hosts:
      - httpbin.org
      ports:
      - number: 80
        name: http
        protocol: HTTP
      resolution: DNS
      location: MESH_EXTERNAL
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: cnn
    spec:
      hosts:
      - edition.cnn.com
      ports:
      - number: 443
        name: tls
        protocol: TLS
      resolution: DNS
      location: MESH_EXTERNAL
    EOF
    
  3. localhost サービス用のサービスエントリを作成し、宛先ルールを設定します。メッシュ内からのトラフィックをブロックするために、メッシュ内のアプリケーションから外部サービスへのトラフィックの宛先として、次のステップでこのサービスエントリが必要になります。この例では、Istio を外部アプリケーションと外部サービス間のプロキシとして使用します。

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: localhost
    spec:
      hosts:
      - localhost.local
      location: MESH_EXTERNAL
      ports:
      - number: 80
        name: http
        protocol: HTTP
      - number: 443
        name: tls
        protocol: TLS
      resolution: STATIC
      endpoints:
      - address: 127.0.0.1
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: localhost
    spec:
      host: localhost.local
      trafficPolicy:
        tls:
          mode: DISABLE
          sni: localhost.local
    EOF
    
  4. 各外部サービスに対して仮想サービスを作成して、それへのルーティングを設定します。両方の仮想サービスには、gateways: セクションに proxy ゲートウェイが含まれており、HTTP および HTTPS トラフィックに対する match: セクションにも含まれています。

    メッシュ内のアプリケーションを表すゲートウェイである mesh ゲートウェイの route: セクションに注目してください。mesh ゲートウェイの route: は、トラフィックが localhost.local サービスにどのように転送され、トラフィックを効果的にブロックするかを示しています。

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
    spec:
      hosts:
      - httpbin.org
      gateways:
      - proxy
      - mesh
      http:
      - match:
        - gateways:
          - proxy
          port: 80
          uri:
            prefix: /status
        route:
        - destination:
            host: httpbin.org
            port:
              number: 80
      - match:
        - gateways:
          - mesh
          port: 80
        route:
        - destination:
            host: localhost.local
            port:
              number: 80
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: cnn
    spec:
      hosts:
      - edition.cnn.com
      gateways:
      - proxy
      - mesh
      tls:
      - match:
        - gateways:
          - proxy
          port: 443
          sni_hosts:
          - edition.cnn.com
        route:
        - destination:
            host: edition.cnn.com
            port:
              number: 443
      - match:
        - gateways:
          - mesh
          port: 443
          sni_hosts:
          - edition.cnn.com
        route:
        - destination:
            host: localhost.local
            port:
              number: 443
    EOF
    
  5. Envoy のアクセスログを有効にする.

  6. イングレス IP およびポートの決定 の手順に従って、SECURE_INGRESS_PORT および INGRESS_HOST 環境変数を定義します。

  7. 前のステップで $INGRESS_HOST および $INGRESS_PORT 環境変数に格納したイングレス IP とポートを介して httpbin.org サービスにアクセスします。HTTP ステータス 418 I’m a teapot を返す httpbin.org サービスの /status/418 パスにアクセスします。

    $ curl $INGRESS_HOST:$INGRESS_PORT/status/418 -Hhost:httpbin.org
    
    -=[ teapot ]=-
    
       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`
    
  8. Istio イングレスゲートウェイが istio-system 名前空間にデプロイされている場合は、次のコマンドでゲートウェイのログを出力します

    $ kubectl logs -l istio=ingressgateway -c istio-proxy -n istio-system | grep 'httpbin.org'
    
  9. 次のようなエントリをログで検索します

    [2019-01-31T14:40:18.645Z] "GET /status/418 HTTP/1.1" 418 - 0 135 187 186 "10.127.220.75" "curl/7.54.0" "28255618-6ca5-9d91-9634-c562694a3625" "httpbin.org" "34.232.181.106:80" outbound|80||httpbin.org - 172.30.230.33:80 10.127.220.75:52077 -
    
  10. イングレスゲートウェイを介して edition.cnn.com サービスにアクセスします

    $ curl -s --resolve edition.cnn.com:$SECURE_INGRESS_PORT:$INGRESS_HOST https://edition.cnn.com:$SECURE_INGRESS_PORT | grep -o "<title>.*</title>"
    <title>CNN International - Breaking News, US News, World News and Video</title>
    
  11. Istio イングレスゲートウェイが istio-system 名前空間にデプロイされている場合は、次のコマンドでゲートウェイのログを出力します

    $ kubectl logs -l istio=ingressgateway -c istio-proxy -n istio-system | grep 'edition.cnn.com'
    
  12. 次のようなエントリをログで検索します

    [2019-01-31T13:40:11.076Z] "- - -" 0 - 589 17798 1644 - "-" "-" "-" "-" "172.217.31.132:443" outbound|443||edition.cnn.com 172.30.230.33:54508 172.30.230.33:443 10.127.220.75:49467 edition.cnn.com
    

クリーンアップ

ゲートウェイ、仮想サービス、サービスエントリを削除します

$ kubectl delete gateway proxy
$ kubectl delete virtualservice cnn httpbin
$ kubectl delete serviceentry cnn httpbin-ext localhost
$ kubectl delete destinationrule localhost
この記事を共有する