使用外部 HTTPS 代理

設定出口閘道」範例示範如何透過名為「出口閘道」的 Istio 邊緣元件將流量從網格導向外部服務。然而,在某些情況下,需要外部、舊有 (非 Istio) HTTPS 代理才能存取外部服務。例如,您的公司可能已經有這樣一個代理,並且組織內的所有應用程式可能都需要將其流量導向該代理。

這個範例展示如何啟用對外部 HTTPS 代理的存取。由於應用程式使用 HTTP CONNECT 方法來建立與 HTTPS 代理的連線,因此設定導向外部 HTTPS 代理的流量與設定導向外部 HTTP 和 HTTPS 服務的流量不同。

開始之前

  • 請按照安裝指南中的說明設定 Istio。

  • 部署 curl 範例應用程式,作為傳送請求的測試來源。如果您已啟用自動 Sidecar 注入,請執行以下命令來部署範例應用程式

    Zip
    $ kubectl apply -f @samples/curl/curl.yaml@
    

    否則,請在部署 curl 應用程式之前,使用以下命令手動注入 Sidecar

    Zip
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@)
    
  • SOURCE_POD 環境變數設定為您的來源 Pod 的名稱

    $ export SOURCE_POD=$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})
    

部署 HTTPS 代理

為了模擬舊式代理,並且僅限於此範例,您會在叢集內部部署一個 HTTPS 代理。此外,為了模擬在叢集外部執行的更真實的代理,您將使用代理 Pod 的 IP 位址,而不是 Kubernetes 服務的網域名稱來存取代理 Pod。此範例使用 Squid,但您可以使用任何支援 HTTP CONNECT 的 HTTPS 代理。

  1. 為 HTTPS 代理建立一個命名空間,而不要標記它以進行 Sidecar 注入。沒有標籤,Sidecar 注入在新命名空間中會被停用,因此 Istio 將不會控制該處的流量。您需要此行為來模擬代理位於叢集外部的情況。

    $ kubectl create namespace external
    
  2. 為 Squid 代理建立一個設定檔。

    $ cat <<EOF > ./proxy.conf
    http_port 3128
    
    acl SSL_ports port 443
    acl CONNECT method CONNECT
    
    http_access deny CONNECT !SSL_ports
    http_access allow localhost manager
    http_access deny manager
    http_access allow all
    
    coredump_dir /var/spool/squid
    EOF
    
  3. 建立一個 Kubernetes ConfigMap 來保存代理的設定

    $ kubectl create configmap proxy-configmap -n external --from-file=squid.conf=./proxy.conf
    
  4. 部署一個包含 Squid 的容器

    $ kubectl apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: squid
      namespace: external
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: squid
      template:
        metadata:
          labels:
            app: squid
        spec:
          volumes:
          - name: proxy-config
            configMap:
              name: proxy-configmap
          containers:
          - name: squid
            image: sameersbn/squid:3.5.27
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - name: proxy-config
              mountPath: /etc/squid
              readOnly: true
    EOF
    
  5. external 命名空間中部署 curl 範例,以測試在沒有 Istio 流量控制的情況下,導向代理的流量。

    Zip
    $ kubectl apply -n external -f @samples/curl/curl.yaml@
    
  6. 取得代理 Pod 的 IP 位址,並定義 PROXY_IP 環境變數來儲存它

    $ export PROXY_IP="$(kubectl get pod -n external -l app=squid -o jsonpath={.items..podIP})"
    
  7. 定義 PROXY_PORT 環境變數以儲存您的代理的埠。在此範例中,Squid 使用埠 3128。

    $ export PROXY_PORT=3128
    
  8. external 命名空間中的 curl Pod 透過代理向外部服務傳送請求

    $ kubectl exec "$(kubectl get pod -n external -l app=curl -o jsonpath={.items..metadata.name})" -n external -- sh -c "HTTPS_PROXY=$PROXY_IP:$PROXY_PORT curl https://en.wikipedia.org/wiki/Main_Page" | grep -o "<title>.*</title>"
    <title>Wikipedia, the free encyclopedia</title>
    
  9. 檢查代理的存取記錄,查看您的請求

    $ kubectl exec "$(kubectl get pod -n external -l app=squid -o jsonpath={.items..metadata.name})" -n external -- tail /var/log/squid/access.log
    1544160065.248    228 172.30.109.89 TCP_TUNNEL/200 87633 CONNECT en.wikipedia.org:443 - HIER_DIRECT/91.198.174.192 -
    

到目前為止,您已在沒有 Istio 的情況下完成以下任務

  • 您已部署 HTTPS 代理。
  • 您已使用 curl 透過代理存取 wikipedia.org 外部服務。

接下來,您必須設定來自啟用 Istio 的 Pod 的流量,以使用 HTTPS 代理。

設定流量到外部 HTTPS 代理

  1. 為 HTTPS 代理定義一個 TCP(而不是 HTTP!)服務條目。儘管應用程式使用 HTTP CONNECT 方法來建立與 HTTPS 代理的連線,但您必須為 TCP 流量設定代理,而不是 HTTP。連線建立後,代理僅充當 TCP 通道。

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: proxy
    spec:
      hosts:
      - my-company-proxy.com # ignored
      addresses:
      - $PROXY_IP/32
      ports:
      - number: $PROXY_PORT
        name: tcp
        protocol: TCP
      location: MESH_EXTERNAL
      resolution: NONE
    EOF
    
  2. default 命名空間中的 curl Pod 發送請求。由於 curl Pod 有一個 Sidecar,因此 Istio 控制其流量。

    $ kubectl exec "$SOURCE_POD" -c curl -- sh -c "HTTPS_PROXY=$PROXY_IP:$PROXY_PORT curl https://en.wikipedia.org/wiki/Main_Page" | grep -o "<title>.*</title>"
    <title>Wikipedia, the free encyclopedia</title>
    
  3. 檢查 Istio Sidecar 代理的日誌,查看您的請求

    $ kubectl logs "$SOURCE_POD" -c istio-proxy
    [2018-12-07T10:38:02.841Z] "- - -" 0 - 702 87599 92 - "-" "-" "-" "-" "172.30.109.95:3128" outbound|3128||my-company-proxy.com 172.30.230.52:44478 172.30.109.95:3128 172.30.230.52:44476 -
    
  4. 檢查代理的存取記錄,查看您的請求

    $ kubectl exec "$(kubectl get pod -n external -l app=squid -o jsonpath={.items..metadata.name})" -n external -- tail /var/log/squid/access.log
    1544160065.248    228 172.30.109.89 TCP_TUNNEL/200 87633 CONNECT en.wikipedia.org:443 - HIER_DIRECT/91.198.174.192 -
    

了解發生了什麼

在此範例中,您執行了以下步驟

  1. 部署了一個 HTTPS 代理來模擬外部代理。
  2. 建立一個 TCP 服務條目,以啟用由 Istio 控制的導向外部代理的流量。

請注意,您不必為透過外部代理存取的外部服務(例如 wikipedia.org)建立服務條目。這是因為從 Istio 的角度來看,請求僅發送到外部代理;Istio 並不知道外部代理會將請求進一步轉發。

清理

  1. 關閉 curl 服務

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@
    
  2. 關閉 external 命名空間中的 curl 服務

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@ -n external
    
  3. 關閉 Squid 代理,移除 ConfigMap 和設定檔

    $ kubectl delete -n external deployment squid
    $ kubectl delete -n external configmap proxy-configmap
    $ rm ./proxy.conf
    
  4. 刪除 external 命名空間

    $ kubectl delete namespace external
    
  5. 刪除服務條目

    $ kubectl delete serviceentry proxy
    
此資訊是否有用?
您有任何改進建議嗎?

感謝您的回饋!