為外部服務設定容錯移轉

了解如何為網格外部的端點設定區域性負載平衡和容錯移轉。

2021 年 6 月 4 日 | 作者:Ram Vennam - Solo.io

Istio 強大的 API 可以用來解決各種服務網格的使用案例。許多用戶知道它強大的入口和東西向功能,但它也為出口(向外)流量提供了許多功能。當您的應用程式需要與外部服務(例如雲提供商提供的資料庫端點)通信時,這特別有用。通常,根據您的工作負載在哪裡執行,有多個端點可供選擇。例如,Amazon 的 DynamoDB 在其各個區域提供多個端點。您通常會選擇最接近您的工作負載的端點以獲得較低的延遲,但是如果情況不如預期,您可能需要設定自動容錯移轉到另一個端點。

與在服務網格內執行的服務類似,您可以設定 Istio 來偵測異常值並容錯移轉到健康的端點,同時對您的應用程式完全透明。在此範例中,我們將使用 Amazon DynamoDB 端點,並選擇與在 Google Kubernetes Engine (GKE) 叢集中執行的工作負載相同或接近的主要區域。我們還將設定容錯移轉區域。

路由端點
主要http://dynamodb.us-east-1.amazonaws.com
容錯移轉http://dynamodb.us-west-1.amazonaws.com

failover

使用 ServiceEntry 定義外部端點

區域性負載平衡根據 regionzone 運作,它們通常是從 Kubernetes 節點上設定的標籤推斷出來的。首先,確定您的工作負載的位置

$ kubectl describe node | grep failure-domain.beta.kubernetes.io/region
                    failure-domain.beta.kubernetes.io/region=us-east1
                    failure-domain.beta.kubernetes.io/region=us-east1

在此範例中,GKE 叢集節點在 us-east1 中執行。

接下來,建立一個 ServiceEntry,它會聚合您想要使用的端點。在此範例中,我們選擇了 mydb.com 作為主機。這是您的應用程式應設定為連線的位址。將主要端點的 locality 設定為與您的工作負載相同的區域

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: external-svc-dns
spec:
  hosts:
  - mydb.com
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  endpoints:
  - address: dynamodb.us-east-1.amazonaws.com
    locality: us-east1
    ports:
      http: 80
  - address: dynamodb.us-west-1.amazonaws.com
    locality: us-west
    ports:
      http: 80

讓我們部署一個 sleep 容器,以用作傳送請求的測試來源。

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

從 sleep 容器嘗試前往 http://mydb.com 5 次

$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com

您會看到 Istio 正在將請求傳送到兩個端點。我們只希望它傳送到標記為與我們節點相同區域的端點。

為此,我們需要設定一個 DestinationRule

使用 DestinationRule 設定容錯移轉條件

Istio 的 DestinationRule 可讓您設定負載平衡、連線池和異常值偵測設定。我們可以指定用於識別端點為不健康的條件,並將其從負載平衡池中移除。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: mydynamodb
spec:
  host: mydb.com
  trafficPolicy:
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 15s
      baseEjectionTime: 1m

上述 DestinationRule 設定為每 15 秒掃描一次端點,並且如果任何端點發生 5xx 錯誤碼,即使只有一次,也會被標記為不健康一分鐘。如果未觸發此斷路器,流量將路由到與 Pod 相同的區域。

如果我們再次執行 curl,我們應該會看到流量始終傳送到 us-east1 端點。

$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done

healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com

模擬失敗

接下來,讓我們看看如果 us-east 端點當機會發生什麼事。為了模擬這種情況,讓我們修改 ServiceEntry 並將 us-east 端點設定為無效的連接埠

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: external-svc-dns
spec:
  hosts:
  - mydb.com
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  endpoints:
  - address: dynamodb.us-east-1.amazonaws.com
    locality: us-east1
    ports:
      http: 81 # INVALID - This is purposefully wrong to trigger failover
  - address: dynamodb.us-west-1.amazonaws.com
    locality: us-west
    ports:
      http: 80

再次執行 curl 會顯示,在無法連線到 us-east 端點後,流量會自動容錯移轉到我們的 us-west 區域

$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
upstream connect error or disconnect/reset before headers. reset reason: connection failure
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com

您可以透過執行以下命令來檢查 us-east 端點的異常值狀態

$ istioctl pc endpoints <sleep-pod> | grep mydb
ENDPOINT                         STATUS      OUTLIER CHECK     CLUSTER
52.119.226.80:81                 HEALTHY     FAILED            outbound|80||mydb.com
52.94.12.144:80                  HEALTHY     OK                outbound|80||mydb.com

HTTPS 容錯移轉

為外部 HTTPS 服務設定容錯移轉也很容易。您的應用程式仍然可以繼續使用純 HTTP,您可以讓 Istio 代理執行到 HTTPS 端點的 TLS 起源。

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: external-svc-dns
spec:
  hosts:
  - mydb.com
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
    targetPort: 443
  resolution: DNS
  endpoints:
  - address: dynamodb.us-east-1.amazonaws.com
    locality: us-east1
  - address: dynamodb.us-west-1.amazonaws.com
    locality: us-west

上述 ServiceEntry 在連接埠 80 上定義 mydb.com 服務,並將流量重新導向到連接埠 443 上的實際 DynamoDB 端點。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: mydynamodb
spec:
  host: mydb.com
  trafficPolicy:
    tls:
      mode: SIMPLE
    loadBalancer:
      simple: ROUND_ROBIN
      localityLbSetting:
        enabled: true
        failover:
          - from: us-east1
            to: us-west
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 15s
      baseEjectionTime: 1m

現在,DestinationRule 執行 TLS 起源並設定異常值偵測。該規則還設定了一個 容錯移轉 欄位,您可以在其中指定確切的區域作為容錯移轉目標。當您定義了多個區域時,這很有用。

總結

Istio 的 VirtualServiceDestinationRule API 提供流量路由、故障復原和錯誤注入功能,以便您可以建立具彈性的應用程式。ServiceEntry API 將許多這些功能擴展到不屬於您的服務網格的外部服務。

分享此貼文