將 Istio 作為外部服務的代理

設定 Istio 入口閘道以作為外部服務的代理。

2019 年 10 月 15 日 | 作者:Vadim Eisenberg - IBM

控制入口流量不使用 TLS 終止的入口閘道任務描述了如何設定入口閘道,以將網格內部的服務暴露給外部流量。這些服務可以是 HTTP 或 HTTPS。在 HTTPS 的情況下,閘道會直接傳遞流量,而不終止 TLS。

這篇部落格文章描述如何使用 Istio 相同的入口閘道機制,來啟用對外部服務的訪問,而不是對網格內部的應用程式的訪問。這樣一來,Istio 整體可以作為一個代理伺服器,並具有可觀測性、流量管理和策略強制執行等附加價值。

這篇部落格文章展示了如何設定對 HTTP 和 HTTPS 外部服務的訪問,即 httpbin.orgedition.cnn.com

設定入口閘道

  1. 定義一個入口閘道,並使用 servers: 區段設定 80443 連接埠。確保連接埠 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.orgedition.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: 區段中包含 proxy 閘道。

    請注意 mesh 閘道的 route: 區段,mesh 閘道代表網格內部的應用程式。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_PORTINGRESS_HOST 環境變數。

  7. 透過您的入口 IP 和連接埠訪問 httpbin.org 服務,這些 IP 和連接埠在先前的步驟中分別儲存在 $INGRESS_HOST$INGRESS_PORT 環境變數中。訪問 httpbin.org 服務的 /status/418 路徑,該路徑會返回 HTTP 狀態418 I'm a teapot

    $ 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
分享這篇文章