使用萬用字元主機的出口流量
存取外部服務任務和設定出口閘道範例說明如何為特定主機名稱(例如 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
$ istioctl install --set profile=minimal -y \
--set values.pilot.env.PILOT_ENABLE_ALPHA_GATEWAY_API=true \
--set meshConfig.accessLogFile=/dev/stdout \
--set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
部署 curl 範例應用程式,以作為傳送請求的測試來源。如果啟用自動 Sidecar 注入,請執行以下命令來部署範例應用程式。
$ kubectl apply -f @samples/curl/curl.yaml@
否則,請在部署
curl
應用程式之前,使用以下命令手動注入 Sidecar。$ 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 呼叫服務。當直接呼叫服務時(即不透過出口閘道),萬用字元主機的配置與任何其他(例如,完全合格的)主機的配置沒有什麼不同,只有當通用網域中有許多主機時,會更方便許多。
為
*.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
傳送 HTTPS 請求至 https://en.wikipedia.org 和 https://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。
- 為 *.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
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: wikipedia-egress-gateway
annotations:
networking.istio.io/service-type: ClusterIP
spec:
gatewayClassName: istio
listeners:
- name: tls
hostname: "*.wikipedia.org"
port: 443
protocol: TLS
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: direct-wikipedia-to-egress-gateway
spec:
parentRefs:
- kind: ServiceEntry
group: networking.istio.io
name: wikipedia
rules:
- backendRefs:
- name: wikipedia-egress-gateway-istio
port: 443
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: forward-wikipedia-from-egress-gateway
spec:
parentRefs:
- name: wikipedia-egress-gateway
hostnames:
- "*.wikipedia.org"
rules:
- backendRefs:
- kind: Hostname
group: networking.istio.io
name: www.wikipedia.org
port: 443
---
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: wikipedia
spec:
hosts:
- "*.wikipedia.org"
ports:
- number: 443
name: https
protocol: HTTPS
EOF
為目標伺服器,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
傳送 HTTPS 請求至 https://en.wikipedia.org 和 https://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>
檢查出口閘道代理的統計資訊,查看與您對 *.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 exec "$(kubectl get pod -l gateway.networking.k8s.io/gateway-name=wikipedia-egress-gateway -o jsonpath='{.items[0].metadata.name}')" -c istio-proxy -- 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
$ kubectl delete se wikipedia
$ kubectl delete se www-wikipedia
$ kubectl delete gtw wikipedia-egress-gateway
$ kubectl delete tlsroute direct-wikipedia-to-egress-gateway
$ kubectl delete tlsroute forward-wikipedia-from-egress-gateway
用於任意網域的萬用字元設定
上一節中的配置之所以有效,是因為所有 *.wikipedia.org
網站都可以由任何一個 wikipedia.org
伺服器提供服務。但是,情況並非總是如此。例如,您可能希望配置出口控制,以存取更通用的萬用字元網域,如 *.com
或 *.org
。為任意萬用字元網域配置流量,為 Istio 閘道帶來挑戰;Istio 閘道只能配置為將流量路由到預定義的主機、預定義的 IP 位址,或請求的原始目標 IP 位址。
在上一節中,您將虛擬服務配置為將流量導向到預定義的主機 www.wikipedia.org
。然而,一般情況下,您不知道哪個主機或 IP 位址可以為請求中收到的任意主機提供服務,這使得請求的原始目標位址成為路由請求的唯一值。不幸的是,當使用出口閘道時,由於原始請求被重新導向到閘道,導致目標 IP 位址變成閘道的 IP 位址,因此請求的原始目標位址會遺失。
雖然不如它所依賴的 Istio 實作細節容易且有點脆弱,但您可以使用 Envoy 過濾器 來配置閘道以支援任意網域,方法是使用 HTTPS 中的 SNI 值或任何 TLS 請求來識別要路由請求的原始目標。這種配置方法的一個範例可以在將出口流量路由到萬用字元目的地中找到。
清除
關閉 curl 服務。
$ kubectl delete -f @samples/curl/curl.yaml@
從您的叢集中解除安裝 Istio。
$ istioctl uninstall --purge -y