在 Istio 中使用加速卸载连接负载均衡
使用 Istio 网关中的 DLB 连接负载均衡配置加速连接均衡。
什么是连接负载均衡?
负载均衡是用于将流量分布到服务器场中多个服务器的核心中网络解决方案。负载均衡器提高了应用程序的可用性和响应能力,并防止服务器过载。每个负载均衡器都位于客户端设备和后端服务器之间,接收传入请求,然后将请求分发到任何能够满足请求的可用服务器。
对于常见的 Web 服务器,它通常具有多个工作进程(处理器或线程)。如果许多客户端连接到单个工作进程,则此工作进程会变得繁忙并带来长尾延迟,而其他工作进程处于空闲状态,从而影响 Web 服务器的性能。连接负载均衡是针对这种情况的解决方案,也称为连接均衡。
Istio 对连接负载均衡做了什么?
Istio 使用 Envoy 作为数据平面。
Envoy 提供了一种称为精确连接均衡器的连接负载均衡实现。顾名思义,在均衡期间会保持锁定,因此连接计数在工作进程之间几乎完全均衡。它在“几乎”精确的意义上是,连接可能会并行关闭,从而使计数不正确,但这应该在下一个接受时得到纠正。此均衡器牺牲接受吞吐量以换取准确性,应该在连接数量很少且很少循环的情况下使用,例如服务网格 gRPC 出站。
显然,它不适用于入口网关,因为入口网关在很短的时间内接受数千个连接,锁定的资源成本会导致吞吐量大幅下降。
现在,Envoy 集成了英特尔® 动态负载均衡 (英特尔®DLB) 连接负载均衡,以在入口网关等高连接计数的情况下加速。
英特尔® 动态负载均衡如何在 Envoy 中加速连接负载均衡
英特尔 DLB 是一个硬件管理的队列和仲裁系统,用于连接生产者和消费者。它是一个 PCI 设备,设想在服务器 CPU 非核心 中运行,并且可以与在核心上运行的软件以及可能与其他设备交互。
英特尔 DLB 实现以下负载均衡功能
- 从软件中卸载队列管理 - 在存在大量基于队列的成本的情况下很有用。
- 尤其是在多生产者/多消费者场景和将入队批处理到多个目标的情况下。
- 软件中访问共享队列需要开销锁。英特尔 DLB 实现对共享队列的无锁访问。
- 动态、流感知负载均衡和重新排序。
- 确保任务的平均分配和更好的 CPU 核心利用率。如果需要,可以提供基于流的原子性。
- 在不丢失数据包顺序的情况下,将高带宽流分布到多个核心。
- 更好的确定性和避免过度的排队延迟。
- 使用更少的 IO 内存占用并节省 DDR 带宽。
- 优先级队列(最多 8 级) - 允许 QoS。
- 对延迟敏感的流量的延迟更低。
- 数据包中可选的延迟测量。
- 可扩展性
- 允许应用程序的动态调整大小,无缝扩展/缩减。
- 电源感知;应用程序可以在负载较轻的情况下降低工作进程以降低功耗。
有三种类型的负载均衡队列
- 无序:对于多个生产者和消费者。任务的顺序并不重要,每个任务都被分配到当前负载最低的处理器核心。
- 有序:对于多个生产者和消费者,其中任务的顺序很重要。当多个任务由多个处理器核心处理时,它们必须以原始顺序重新排列。
- 原子:对于多个生产者和消费者,其中任务根据某些规则进行分组。这些任务使用同一组资源进行处理,并且同一组内任务的顺序很重要。
预计入口网关会尽可能快地处理尽可能多的数据,因此英特尔 DLB 连接负载均衡使用无序队列。
如何在 Istio 中使用英特尔 DLB 连接负载均衡
在 1.17 版本中,Istio 正式支持英特尔 DLB 连接负载均衡。
以下步骤展示了如何在 SPR(Sapphire Rapids)机器中的 Istio 入口网关 中使用英特尔 DLB 连接负载均衡,假设 Kubernetes 集群正在运行。
步骤 1:准备 DLB 环境
按照 英特尔 DLB 驱动程序官方网站上的说明 安装英特尔 DLB 驱动程序。
使用以下命令安装英特尔 DLB 设备插件
$ kubectl apply -k https://github.com/intel/intel-device-plugins-for-kubernetes/deployments/dlb_plugin?ref=v0.26.0
有关英特尔 DLB 设备插件的更多详细信息,请参阅 英特尔 DLB 设备插件主页。
您可以检查英特尔 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.ac.cn/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
标志将主机 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 入口网关官方文档。