在 Istio 中使用加速卸載連線負載平衡

在 Istio 閘道中使用 DLB 連線負載平衡配置來加速連線平衡。

2023 年 8 月 8 日 | 作者:Loong Dai - Intel

什麼是連線負載平衡?

負載平衡是一種核心網路解決方案,用於在伺服器群中的多個伺服器之間分配流量。負載平衡器可提高應用程式的可用性和響應速度,並防止伺服器過載。每個負載平衡器都位於用戶端裝置和後端伺服器之間,接收並將傳入的請求分配給任何可用的伺服器來滿足這些請求。

對於常見的網頁伺服器,它通常有多個工作執行緒(處理器或執行緒)。如果許多用戶端連線到單一工作執行緒,則該工作執行緒會變得忙碌並導致長尾延遲,而其他工作執行緒則處於空閒狀態,這會影響網頁伺服器的效能。連線負載平衡是解決這種情況的方案,也稱為連線平衡。

Istio 在連線負載平衡方面做了什麼?

Istio 使用 Envoy 作為資料平面。

Envoy 提供一個稱為「精確連線負載平衡器」的連線負載平衡實作。顧名思義,在平衡期間會持有鎖,以便在工作執行緒之間幾乎精確地平衡連線計數。之所以說是「幾乎」精確,是因為連線可能會並行關閉,從而導致計數不正確,但這應該在下一次接受時得到糾正。此平衡器犧牲接受吞吐量來換取準確性,並且應該在連線數量很少且很少循環時使用,例如,服務網格 gRPC 出口。

顯然,它不適用於入口閘道,因為入口閘道會在短時間內接受數千個連線,並且鎖定的資源成本會導致吞吐量大幅下降。

現在,Envoy 整合了 Intel® Dynamic Load Balancing (Intel®DLB) 連線負載平衡,以加速在類似入口閘道這樣的高連線計數情況下的運作。

Intel® Dynamic Load Balancing 如何加速 Envoy 中的連線負載平衡

Intel DLB 是一個由硬體管理的佇列和仲裁器系統,連接生產者和消費者。它是一個 PCI 裝置,預計會位於伺服器 CPU 的非核心中,並且可以與在核心上運行的軟體以及可能與其他裝置互動。

Intel DLB 實作了以下負載平衡功能

有三種類型的負載平衡佇列

預計入口閘道會盡可能快地處理盡可能多的資料,因此 Intel DLB 連線負載平衡會使用未排序的佇列。

如何在 Istio 中使用 Intel DLB 連線負載平衡

在 1.17 版本中,Istio 正式支援 Intel DLB 連線負載平衡。

以下步驟說明如何在 SPR (Sapphire Rapids) 機器中的 Istio 入口閘道中使用 Intel DLB 連線負載平衡,假設 Kubernetes 叢集正在執行。

步驟 1:準備 DLB 環境

請依照Intel DLB 驅動程式官方網站上的說明安裝 Intel DLB 驅動程式。

使用以下命令安裝 Intel DLB 裝置外掛程式

$ kubectl apply -k https://github.com/intel/intel-device-plugins-for-kubernetes/deployments/dlb_plugin?ref=v0.26.0

有關 Intel DLB 裝置外掛程式的更多詳細資訊,請參閱Intel DLB 裝置外掛程式首頁

您可以檢查 Intel DLB 裝置資源

$ kubectl describe nodes | grep dlb.intel.com/pf
  dlb.intel.com/pf:   2
  dlb.intel.com/pf:   2
...

步驟 2:下載 Istio

在本部落格中,我們使用 1.17.2。讓我們下載安裝檔案

$ curl -L https://istio.dev.org.tw/downloadIstio | ISTIO_VERSION=1.17.2 TARGET_ARCH=x86_64 sh -
$ cd istio-1.17.2
$ export PATH=$PWD/bin:$PATH

您可以檢查版本是否為 1.17.2

$ istioctl version
no running Istio pods in "istio-system"
1.17.2

步驟 3:安裝 Istio

為 Istio 建立安裝配置,請注意,我們為入口閘道分配了 4 個 CPU 和 1 個 DLB 裝置,並將並發性設定為 4,這等於 CPU 數量。

$ cat > config.yaml << EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: default
  components:
    ingressGateways:
    - enabled: true
      name: istio-ingressgateway
      k8s:
        overlays:
          - kind: Deployment
            name: istio-ingressgateway
        podAnnotations:
          proxy.istio.io/config: |
            concurrency: 4
        resources:
          requests:
            cpu: 4000m
            memory: 4096Mi
            dlb.intel.com/pf: '1'
          limits:
            cpu: 4000m
            memory: 4096Mi
            dlb.intel.com/pf: '1'
        hpaSpec:
          maxReplicas: 1
          minReplicas: 1
  values:
    telemetry:
      enabled: false
EOF

使用 istioctl 進行安裝

$ istioctl install -f config.yaml --set values.gateways.istio-ingressgateway.runAsRoot=true -y
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete                                                                                                                                                                                                                                                                       Making this installation the default for injection and validation.

Thank you for installing Istio 1.17.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/hMHGiwZHPU7UQRWe9

步驟 4:設定後端服務

由於我們想要在 Istio 入口閘道中使用 DLB 連線負載平衡,因此我們需要先建立後端服務。

我們將使用 Istio 提供的範例來測試,httpbin

$ kubectl apply -f samples/httpbin/httpbin.yaml
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  # The selector matches the ingress gateway pod labels.
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
EOF
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

您現在已為 httpbin 服務建立虛擬服務配置,其中包含兩個允許路徑 /status 和 /delay 流量的路由規則。

閘道清單指定僅允許通過您的 httpbin-gateway 的請求。所有其他外部請求將被拒絕,並返回 404 響應。

步驟 5:啟用 DLB 連線負載平衡

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: dlb
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: LISTENER
    match:
      context: GATEWAY
    patch:
      operation: MERGE
      value:
        connection_balance_config:
            extend_balance:
              name: envoy.network.connection_balance.dlb
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.network.connection_balance.dlb.v3alpha.Dlb
EOF

預計如果您檢查入口閘道 pod istio-ingressgateway-xxxx 的記錄,您將看到類似以下的記錄項目

$ export POD="$(kubectl get pods -n istio-system | grep gateway | awk '{print $1}')"
$ kubectl logs -n istio-system ${POD} | grep dlb
2023-05-05T06:16:36.921299Z     warning envoy config external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:46        dlb device 0 is not found, use dlb device 3 instead     thread=35

Envoy 將自動偵測並選擇 DLB 裝置。

步驟 6:測試

$ export HOST="<YOUR-HOST-IP>"
$ export PORT="$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')"
$ curl -s -I -HHost:httpbin.example.com "http://${HOST}:${PORT}/status/200"
HTTP/1.1 200 OK
server: istio-envoy
...

請注意,您使用 -H 標誌將 Host HTTP 標頭設定為 httpbin.example.com,因為您現在沒有該主機的 DNS 繫結,並且只是將您的請求傳送到入口 IP。

您也可以在 /etc/hosts 中新增 DNS 繫結並移除 -H 標誌

$ echo "$HOST httpbin.example.com" >> /etc/hosts
$ curl -s -I "http://httpbin.example.com:${PORT}/status/200"
HTTP/1.1 200 OK
server: istio-envoy
...

存取任何其他未明確公開的 URL。您應該會看到 HTTP 404 錯誤

$ curl -s -I -HHost:httpbin.example.com "http://${HOST}:${PORT}/headers"
HTTP/1.1 404 Not Found
...

您可以開啟除錯記錄層級以查看更多 DLB 相關記錄

$ istioctl pc log ${POD}.istio-system --level debug
istio-ingressgateway-665fdfbf95-2j8px.istio-system:
active loggers:
  admin: debug
  alternate_protocols_cache: debug
  aws: debug
  assert: debug
  backtrace: debug
...

執行 curl 發送一個請求,您將看到如下所示的內容

$ kubectl logs -n istio-system ${POD} | grep dlb
2023-05-05T06:16:36.921299Z     warning envoy config external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:46        dlb device 0 is not found, use dlb device 3 instead     thread=35
2023-05-05T06:37:45.974241Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:269   worker_3 dlb send fd 45 thread=47
2023-05-05T06:37:45.974427Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:286   worker_0 get dlb event 1        thread=46
2023-05-05T06:37:45.974453Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:303   worker_0 dlb recv 45    thread=46
2023-05-05T06:37:45.975215Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:283   worker_0 dlb receive none, skip thread=46

有關 Istio 入口閘道的更多詳細資訊,請參閱Istio 入口閘道官方文件

分享此文章