使用萬用字元主機的出口流量

存取外部服務任務和設定出口閘道範例說明如何為特定主機名稱(例如 edition.cnn.com)設定出口流量。此範例說明如何為通用網域中的一組主機(例如 *.wikipedia.org)啟用出口流量,而不是單獨設定每個主機。

背景

假設您想要在 Istio 中為所有語言的 wikipedia.org 網站啟用出口流量。特定語言的每個 wikipedia.org 版本都有自己的主機名稱,例如,英文版的 en.wikipedia.org 和德文版的 de.wikipedia.org。您希望為所有 Wikipedia 網站透過通用配置項目啟用出口流量,而無需單獨指定每個語言的網站。

開始之前

  • 安裝 Istio 時,啟用存取記錄並使用預設封鎖的輸出流量策略。
$ istioctl install --set profile=demo --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
  • 部署 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})
    

設定直接流量到萬用字元主機

在一個通用網域中存取一組主機的第一種也是最簡單的方式,是透過配置一個簡單的 ServiceEntry,其中包含萬用字元主機,並直接從 Sidecar 呼叫服務。當直接呼叫服務時(即不透過出口閘道),萬用字元主機的配置與任何其他(例如,完全合格的)主機的配置沒有什麼不同,只有當通用網域中有許多主機時,會更方便許多。

  1. *.wikipedia.org 定義一個 ServiceEntry

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: wikipedia
    spec:
      hosts:
      - "*.wikipedia.org"
      ports:
      - number: 443
        name: https
        protocol: HTTPS
    EOF
    
  2. 傳送 HTTPS 請求至 https://en.wikipedia.orghttps://de.wikipedia.org

    $ kubectl exec "$SOURCE_POD" -c curl -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"'
    <title>Wikipedia, the free encyclopedia</title>
    <title>Wikipedia – Die freie Enzyklopädie</title>
    

清除直接流量到萬用字元主機

$ kubectl delete serviceentry wikipedia

設定出口閘道流量到萬用字元主機

當所有萬用字元主機都由單一伺服器提供服務時,基於出口閘道存取萬用字元主機的配置與任何主機的配置非常相似,只有一個例外:配置的路由目的地將與配置的主機(即萬用字元)不同。相反,它將配置為網域集中單一伺服器的 host。

  1. *.wikipedia.org 建立出口 Gateway,並建立路由規則,將流量導向通過出口閘道,並從出口閘道導向外部服務。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - "*.wikipedia.org"
    tls:
      mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: egressgateway-for-wikipedia
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
    - name: wikipedia
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: direct-wikipedia-through-egress-gateway
spec:
  hosts:
  - "*.wikipedia.org"
  gateways:
  - mesh
  - istio-egressgateway
  tls:
  - match:
    - gateways:
      - mesh
      port: 443
      sniHosts:
      - "*.wikipedia.org"
    route:
    - destination:
        host: istio-egressgateway.istio-system.svc.cluster.local
        subset: wikipedia
        port:
          number: 443
      weight: 100
  - match:
    - gateways:
      - istio-egressgateway
      port: 443
      sniHosts:
      - "*.wikipedia.org"
    route:
    - destination:
        host: www.wikipedia.org
        port:
          number: 443
      weight: 100
EOF
  1. 為目標伺服器,www.wikipedia.org 建立一個 ServiceEntry

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: www-wikipedia
    spec:
      hosts:
      - www.wikipedia.org
      ports:
      - number: 443
        name: https
        protocol: HTTPS
      resolution: DNS
    EOF
    
  2. 傳送 HTTPS 請求至 https://en.wikipedia.orghttps://de.wikipedia.org

    $ kubectl exec "$SOURCE_POD" -c curl -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"'
    <title>Wikipedia, the free encyclopedia</title>
    <title>Wikipedia – Die freie Enzyklopädie</title>
    
  3. 檢查出口閘道代理的統計資訊,查看與您對 *.wikipedia.org 的請求相對應的計數器。

$ kubectl exec "$(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}')" -c istio-proxy -n istio-system -- pilot-agent request GET clusters | grep '^outbound|443||www.wikipedia.org.*cx_total:'
outbound|443||www.wikipedia.org::208.80.154.224:443::cx_total::2

清除出口閘道流量到萬用字元主機

$ kubectl delete serviceentry www-wikipedia
$ kubectl delete gateway istio-egressgateway
$ kubectl delete virtualservice direct-wikipedia-through-egress-gateway
$ kubectl delete destinationrule egressgateway-for-wikipedia

用於任意網域的萬用字元設定

上一節中的配置之所以有效,是因為所有 *.wikipedia.org 網站都可以由任何一個 wikipedia.org 伺服器提供服務。但是,情況並非總是如此。例如,您可能希望配置出口控制,以存取更通用的萬用字元網域,如 *.com*.org。為任意萬用字元網域配置流量,為 Istio 閘道帶來挑戰;Istio 閘道只能配置為將流量路由到預定義的主機、預定義的 IP 位址,或請求的原始目標 IP 位址。

在上一節中,您將虛擬服務配置為將流量導向到預定義的主機 www.wikipedia.org。然而,一般情況下,您不知道哪個主機或 IP 位址可以為請求中收到的任意主機提供服務,這使得請求的原始目標位址成為路由請求的唯一值。不幸的是,當使用出口閘道時,由於原始請求被重新導向到閘道,導致目標 IP 位址變成閘道的 IP 位址,因此請求的原始目標位址會遺失。

雖然不如它所依賴的 Istio 實作細節容易且有點脆弱,但您可以使用 Envoy 過濾器 來配置閘道以支援任意網域,方法是使用 HTTPS 中的 SNI 值或任何 TLS 請求來識別要路由請求的原始目標。這種配置方法的一個範例可以在將出口流量路由到萬用字元目的地中找到。

清除

  • 關閉 curl 服務。

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@
    
  • 從您的叢集中解除安裝 Istio。

    $ istioctl uninstall --purge -y
    
這項資訊對您有幫助嗎?
您有任何改進的建議嗎?

感謝您的回饋!