在 Istio 中使用加速卸载连接负载均衡

使用 Istio 网关中的 DLB 连接负载均衡配置加速连接均衡。

2023 年 8 月 8 日 | 作者:戴龙 - 英特尔

什么是连接负载均衡?

负载均衡是用于将流量分布到服务器场中多个服务器的核心中网络解决方案。负载均衡器提高了应用程序的可用性和响应能力,并防止服务器过载。每个负载均衡器都位于客户端设备和后端服务器之间,接收传入请求,然后将请求分发到任何能够满足请求的可用服务器。

对于常见的 Web 服务器,它通常具有多个工作进程(处理器或线程)。如果许多客户端连接到单个工作进程,则此工作进程会变得繁忙并带来长尾延迟,而其他工作进程处于空闲状态,从而影响 Web 服务器的性能。连接负载均衡是针对这种情况的解决方案,也称为连接均衡。

Istio 对连接负载均衡做了什么?

Istio 使用 Envoy 作为数据平面。

Envoy 提供了一种称为精确连接均衡器的连接负载均衡实现。顾名思义,在均衡期间会保持锁定,因此连接计数在工作进程之间几乎完全均衡。它在“几乎”精确的意义上是,连接可能会并行关闭,从而使计数不正确,但这应该在下一个接受时得到纠正。此均衡器牺牲接受吞吐量以换取准确性,应该在连接数量很少且很少循环的情况下使用,例如服务网格 gRPC 出站。

显然,它不适用于入口网关,因为入口网关在很短的时间内接受数千个连接,锁定的资源成本会导致吞吐量大幅下降。

现在,Envoy 集成了英特尔® 动态负载均衡 (英特尔®DLB) 连接负载均衡,以在入口网关等高连接计数的情况下加速。

英特尔® 动态负载均衡如何在 Envoy 中加速连接负载均衡

英特尔 DLB 是一个硬件管理的队列和仲裁系统,用于连接生产者和消费者。它是一个 PCI 设备,设想在服务器 CPU 非核心 中运行,并且可以与在核心上运行的软件以及可能与其他设备交互。

英特尔 DLB 实现以下负载均衡功能

有三种类型的负载均衡队列

预计入口网关会尽可能快地处理尽可能多的数据,因此英特尔 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 入口网关官方文档

分享这篇文章