在 Istio 中使用加速卸載連線負載平衡
在 Istio 閘道中使用 DLB 連線負載平衡配置來加速連線平衡。
什麼是連線負載平衡?
負載平衡是一種核心網路解決方案,用於在伺服器群中的多個伺服器之間分配流量。負載平衡器可提高應用程式的可用性和響應速度,並防止伺服器過載。每個負載平衡器都位於用戶端裝置和後端伺服器之間,接收並將傳入的請求分配給任何可用的伺服器來滿足這些請求。
對於常見的網頁伺服器,它通常有多個工作執行緒(處理器或執行緒)。如果許多用戶端連線到單一工作執行緒,則該工作執行緒會變得忙碌並導致長尾延遲,而其他工作執行緒則處於空閒狀態,這會影響網頁伺服器的效能。連線負載平衡是解決這種情況的方案,也稱為連線平衡。
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 實作了對共享佇列的無鎖存取。
- 動態、流量感知負載平衡和重新排序。
- 確保任務的均勻分配和更好的 CPU 核心利用率。如果需要,可以提供基於流量的原子性。
- 在不損失封包順序的情況下,將高頻寬流量分配到多個核心。
- 更好的決定性並避免過多的佇列延遲。
- 使用較少的 IO 記憶體空間並節省 DDR 頻寬。
- 優先順序佇列(最多 8 個級別)— 允許 QOS。
- 對於對延遲敏感的流量,延遲較低。
- 封包中的可選延遲測量。
- 可擴展性
- 允許應用程式動態調整大小、無縫擴展/縮減。
- 感知電源;在負載較輕的情況下,應用程式可以減少工作執行緒以降低功耗狀態。
有三種類型的負載平衡佇列
- 未排序:適用於多個生產者和消費者。任務的順序並不重要,並且每個任務都分配給當前負載最低的處理器核心。
- 已排序:適用於多個生產者和消費者,其中任務的順序很重要。當多個任務由多個處理器核心處理時,它們必須按原始順序重新排列。
- 原子:適用於多個生產者和消費者,其中任務會根據特定規則進行分組。這些任務使用相同的資源集進行處理,並且同一組內任務的順序很重要。
預計入口閘道會盡可能快地處理盡可能多的資料,因此 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 入口閘道官方文件。