在线服务与视频转码应用混部

在线服务与离线计算应用混部在同一节点的场景下,您可以在ACK集群中通过ack-koordinator组件开启差异化SLO能力。本文介绍如何使用ack-koordinator实现在线服务与视频转码应用的混部。

本文将在 ACK 集群中部署在线服务 Nginx,并在同一节点混部离线视频转码应用 FFmpeg,以充分利用集群中已申请但未使用的物理资源。通过启用ack-koordinator的资源隔离功能,可以确保在线服务稳定运行的同时,避免离线应用受到干扰。

前提条件

  • 已在ACK托管集群Pro中创建2个节点用于构建混部环境。

    • 测试机:一个节点用于运行NginxFFmpeg的混部测试。

      为了充分使用ack-koordinator提供的混部优化能力,建议测试机使用神龙裸金属服务器,操作系统选择Alibaba Cloud Linux

    • 压测机:一个节点用于运行客户端的wrk,向Nginx请求Web服务,制造压测请求。

  • 已参见快速入门安装ack-koordinator(ack-slo-manager)并开启相关混部策略。

    本文以ack-koordinator v0.8.0版本为例。

  • 在压测机上,执行以下命令,部署压测工具wrk。

    yum install -y unzip
    wget -O wrk-4.2.0.tar.gz https://github.com/wg/wrk/archive/refs/tags/4.2.0.tar.gz && tar -xvf wrk-4.2.0.tar.gz
    cd wrk-4.2.0 && make && chmod +x ./wrk

应用部署架构

本文将在 ACK 集群中运行 Nginx 作为在线服务,并与视频解码应用 FFmpeg 混部。其中,Nginx Pod 的 QoS 等级为高优先级的Latency Sensitive型(LS);FFmpeg Pod为低优先级的Best Effort型(BE)。本文将对比不同混部配置下 Nginx 应用的性能表现。

在离线混部过程中主要使用的功能特性:

本文将进行三组实验,分别采用以下三种应用部署模式,对比不同混部模式下在线应用的性能表现和节点的资源利用率。

部署方式

说明

在线应用独立部署(基线)

在测试机上仅部署在线应用 Nginx,不部署离线视频转码应用 FFmpeg。使用压测机上的 wrk 工具向 Nginx 发起请求,模拟未混部场景,测试 Nginx 在无离线应用干扰下的性能表现及节点资源利用率。

K8s默认混合部署(对照组)

在测试机上混合部署在线应用 Nginx 和离线视频转码应用 FFmpeg。使用压测机上的 wrk 工具向 Nginx 发起请求。FFmpeg 应用采用Best Effort 模式部署,其 Pod 不设置 Requests 和 Limits。通过调整进程数将节点 CPU 使用率控制为 65%,模拟 K8s 默认混部场景,测试 Nginx 的性能表现及节点资源利用率。

ACK差异化SLO混部(实验组)

在测试机上混合部署在线应用 Nginx 和离线视频转码应用 FFmpeg。使用压测机上的 wrk 工具向 Nginx 发起请求。FFmpeg 应用采用差异化 SLO 的 BE 模式部署,其 Pod 启用动态资源超卖扩展资源。测试机开启 启用CPU资源弹性限制能力启用容器CPU QoS启用容器L3 Cache及内存带宽隔离等 SLO 功能,模拟SLO 混部场景,测试 Nginx 的性能表现及节点资源利用率。

image

操作步骤

在线应用独立部署示例

  1. 在测试机上部署在线应用Nginx。

    1. 使用以下YAML内容,创建ls-nginx.yaml文件。

      展开查看YAML详情

      ---
      # nginx应用配置
      apiVersion: v1
      data:
        config: |-
          user  nginx;
          worker_processes  80; # NginxWorker个数,影响Nginx Server的并发。
      
          events {
              worker_connections  1024;  # 默认值为1024。
          }
      
          http {
              server {
                  listen  8000;
      
                  gzip off;
                  gzip_min_length 32;
                  gzip_http_version 1.0;
                  gzip_comp_level 3;
                  gzip_types *;
              }
          }
      
          #daemon off;
      kind: ConfigMap
      metadata:
        name: nginx-conf
      
      ---
      # Nginx实例,作为在线类型服务应用。
      apiVersion: v1
      kind: Pod
      metadata:
        labels:
          koordinator.sh/qosClass: LS
          app: nginx
        name: nginx
      spec:
        containers:
          - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            imagePullPolicy: IfNotPresent
            name: nginx
            ports:
              - containerPort: 8000
                hostPort: 8000 # 压测请求访问的端口。
                protocol: TCP
            resources:
              limits:
                cpu: '80'
                memory: 10Gi
              requests:
                cpu: '80'
                memory: 10Gi
            volumeMounts:
              - mountPath: /etc/nginx/
                name: config
        hostNetwork: true
        restartPolicy: Never
        volumes:
          - configMap:
              items:
                - key: config
                  path: nginx.conf
              name: nginx-conf
            name: config
        nodeName: cn-beijing.192.168.2.93  # 请替换为您的测试机的节点名称。
    2. 执行以下命令,部署Nginx应用。

      kubectl apply -f ls-nginx.yaml
    3. 执行以下命令,查看Nginx应用的Pod状态。

      kubectl get pod -l app=nginx -o wide

      预期输出:

      NAME    READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES
      nginx   1/1     Running   0          43s    11.162.XXX.XXX   cn-beijing.192.168.2.93   <none>           <none>

      由预期输出得到,Pod的状态为Running ,表示Nginx应用已在测试机上正常运行。

  2. 使用压测工具wrk,向Nginx应用发起压测请求。

    # node_ip填写测试机的IP地址,用于wrk向测试机发起压测;8000Nginx暴露到测试机的端口。
    ./wrk -t6 -c54 -d60s --latency http://${node_ip}:8000/

    预期输出:

      Running 1m test @ http://${node_ip}:8000/
      6 threads and 54 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   402.18us    1.07ms  59.56ms   99.83%
        Req/Sec    24.22k     1.12k   30.58k    74.15%
      Latency Distribution
         50%  343.00us
         75%  402.00us
         90%  523.00us
         99%  786.00us
      8686569 requests in 1.00m, 6.88GB read
    Requests/sec: 144537.08
    Transfer/sec:    117.16MB

    RT指标是本次衡量在线服务Nginx应用在不同场景下运行性能的关键指标。由预期输出得到,Latency Distribution部分包含了wrk请求在Nginx应用上响应时间RT(Response Time)的分布。例如,90% 523.00us表示本次压测中RT90分位值(P90)为523.00us。Nginx应用在未混部场景下压测得到的RT-P50、RT-P90、RT-P99分别为343us、523us、786us。

  3. 执行以下命令,获取测试机的节点CPU平均利用率。

    kubectl top node

    预期输出:

    NAME                      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
    cn-beijing.192.168.2.93   29593m       29%    xxxx            xxxx
    cn-beijing.192.168.2.94   6874m        7%     xxxx            xxxx

    由预期输出得到,压测中测试机的平均CPU资源利用率约为29%

K8s默认混合部署示例

  1. 在测试机上部署在线应用Nginx。

    1. 使用以下YAML内容,创建ls-nginx.yaml文件。

      展开查看YAML详情

      ---
      # nginx应用配置
      apiVersion: v1
      data:
        config: |-
          user  nginx;
          worker_processes  80; # NginxWorker个数,影响Nginx Server的并发。
      
          events {
              worker_connections  1024;  # 默认值为1024。
          }
      
          http {
              server {
                  listen  8000;
      
                  gzip off;
                  gzip_min_length 32;
                  gzip_http_version 1.0;
                  gzip_comp_level 3;
                  gzip_types *;
              }
          }
      
          #daemon off;
      kind: ConfigMap
      metadata:
        name: nginx-conf
      
      ---
      # Nginx实例,作为在线类型服务应用。
      apiVersion: v1
      kind: Pod
      metadata:
        labels:
          koordinator.sh/qosClass: LS
          app: nginx
        name: nginx
      spec:
        containers:
          - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            imagePullPolicy: IfNotPresent
            name: nginx
            ports:
              - containerPort: 8000
                hostPort: 8000 # 压测请求访问的端口。
                protocol: TCP
            resources:
              limits:
                cpu: '80'
                memory: 10Gi
              requests:
                cpu: '80'
                memory: 10Gi
            volumeMounts:
              - mountPath: /etc/nginx/
                name: config
        hostNetwork: true
        restartPolicy: Never
        volumes:
          - configMap:
              items:
                - key: config
                  path: nginx.conf
              name: nginx-conf
            name: config
        nodeName: cn-beijing.192.168.2.93  # 请替换为您的测试机的节点名称。
    2. 执行以下命令,部署Nginx应用。

      kubectl apply -f ls-nginx.yaml
    3. 执行以下命令,查看Nginx应用的Pod状态。

      kubectl get pod -l app=nginx -o wide

      预期输出:

      NAME    READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES
      nginx   1/1     Running   0          43s    11.162.XXX.XXX   cn-beijing.192.168.2.93   <none>           <none>

      由预期输出得到,Pod的状态为Running ,表示Nginx应用已在测试机上正常运行。

  2. 在测试机上部署离线应用。

    1. 使用以下YAML内容,创建be-ffmpeg.yaml文件。

      展开查看YAML详情

      # FFmpeg实例,作为离线类型计算应用。
      apiVersion: v1
      kind: Pod
      metadata:
        name: be-ffmpeg
        labels:
          app: ffmpeg
        # 1. 按照K8s默认混合部署模式部署:删除以下koordinator.sh/qosClass=BElabel。
        # 2. 按照ACK差异化SLO混部模式部署:保留以下koordinator.sh/qosClass=BElabel。
          koordinator.sh/qosClass: BE
      spec:
        containers:
          # FFmpeg的进程数量可以根据测试需求调节,进程数越多对应的离线资源使用率越高,默认为25个进程,每个进程有两个线程并发工作。
          - command:
              - start-ffmpeg.sh
              - '25'
              - '2'
              - /apps/ffmpeg/input/HD2-h264.ts
              - /apps/ffmpeg/
            image: 'registry.cn-zhangjiakou.aliyuncs.com/acs/ffmpeg-4-4-1-for-slo-test:v0.1'
            imagePullPolicy: Always
            name: ffmpeg
            resources:
            # 1. 按照K8s默认混合部署模式部署:删除以下扩展资源kubernetes.io/batch-cpukubernetes.io/batch-memory。
            # 2. 按照ACK差异化SLO混部模式部署:保留以下扩展资源kubernetes.io/batch-cpukubernetes.io/batch-memory。
            # 具体资源需求量请按节点规格按需调整。
              limits:
                kubernetes.io/batch-cpu: 70k
                kubernetes.io/batch-memory: 22Gi
              requests:
                kubernetes.io/batch-cpu: 70k
                kubernetes.io/batch-memory: 22Gi
        hostNetwork: true
        restartPolicy: Never
        nodeName: cn-beijing.192.168.2.93  # 请替换为您的测试机的节点名称。
    2. 执行以下命令,部署FFmpeg应用。

      kubectl apply -f be-ffmpeg.yaml
    3. 执行以下命令,查看FFmpeg应用的Pod状态。

      kubectl get pod -l app=ffmpeg -o wide

      预期输出:

      NAME        READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES
      be-ffmpeg   1/1     Running   0          15s    11.162.XXX.XXX   cn-beijing.192.168.2.93   <none>           <none>

      由预期输出得到,Pod的状态为Running ,表示FFmpeg应用已在测试机上正常运行。

  3. 使用压测工具wrk,执行以下命令,向Nginx应用发起压测请求。

    # node_ip填写测试机的IP地址,用于wrk向测试机发起压测;8000Nginx暴露到测试机的端口。
    ./wrk -t6 -c54 -d60s --latency http://${node_ip}:8000/
  4. 执行以下命令,查看测试机的CPU资源利用率。

    kubectl top node

    压测结果请参见实验结果总览

ACK差异化SLO混合部署示例

在测试机上以ACK差异化SLOBE Pod的形式部署视频转码应用FFmpeg,测试在线服务在与视频转码应用在差异化SLO混部下的性能数据。

  1. 参考管理混部策略,开启差异化SLO混部。

    相关功能说明如下:

    • 启用动态资源超卖:采用开启后的默认配置。用于合理超卖节点未使用的物理资源,提供给BE Pod调度。

    • 启用CPU资源弹性限制能力cpuSuppressThresholdPercent设置为65,其他采用开启后的默认配置。用于在节点CPU资源利用率超出阈值(65%)时,压制BE应用的CPU使用,以保障LS应用的CPU性能。

    • 启用容器CPU QoS:采用开启后的默认配置。用于启用Alibaba Cloud LinuxCPU Identity能力,在内核调度中优先保障LS应用的CPU调度,避免因BE应用对LS应用运行在同一对SMT超线程上而产生的干扰。

    • 启用容器L3 Cache及内存带宽隔离:采用开启后的默认配置。用于启用裸金属服务器的容器L3 Cache和内存带宽隔离机制,优先保障LS应用的L3 Cache和内存带宽使用,缓解BE应用的资源竞争干扰。

    重要
    • 容器CPU QoS功能仅在节点的操作系统版本为Alibaba Cloud Linux时生效;使用其他操作系统版本时,该功能不会开启。

    • 容器L3 Cache及内存带宽隔离功能仅在节点为裸金属服务器时生效;使用其他服务器类型时,该功能不会开启。

  2. 在测试机上部署在线应用Nginx。

    1. 使用以下YAML内容,创建ls-nginx.yaml文件。

      展开查看YAML详情

      ---
      # nginx应用配置
      apiVersion: v1
      data:
        config: |-
          user  nginx;
          worker_processes  80; # NginxWorker个数,影响Nginx Server的并发。
      
          events {
              worker_connections  1024;  # 默认值为1024。
          }
      
          http {
              server {
                  listen  8000;
      
                  gzip off;
                  gzip_min_length 32;
                  gzip_http_version 1.0;
                  gzip_comp_level 3;
                  gzip_types *;
              }
          }
      
          #daemon off;
      kind: ConfigMap
      metadata:
        name: nginx-conf
      
      ---
      # Nginx实例,作为在线类型服务应用。
      apiVersion: v1
      kind: Pod
      metadata:
        labels:
          koordinator.sh/qosClass: LS
          app: nginx
        name: nginx
      spec:
        containers:
          - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            imagePullPolicy: IfNotPresent
            name: nginx
            ports:
              - containerPort: 8000
                hostPort: 8000 # 压测请求访问的端口。
                protocol: TCP
            resources:
              limits:
                cpu: '80'
                memory: 10Gi
              requests:
                cpu: '80'
                memory: 10Gi
            volumeMounts:
              - mountPath: /etc/nginx/
                name: config
        hostNetwork: true
        restartPolicy: Never
        volumes:
          - configMap:
              items:
                - key: config
                  path: nginx.conf
              name: nginx-conf
            name: config
        nodeName: cn-beijing.192.168.2.93  # 请替换为您的测试机的节点名称。
    2. 执行以下命令,部署Nginx应用。

      kubectl apply -f ls-nginx.yaml
    3. 执行以下命令,查看Nginx应用的Pod状态。

      kubectl get pod -l app=nginx -o wide

      预期输出:

      NAME    READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES
      nginx   1/1     Running   0          43s    11.162.XXX.XXX   cn-beijing.192.168.2.93   <none>           <none>

      由预期输出得到,Pod的状态为Running ,表示Nginx应用已在测试机上正常运行。

  3. 在测试机上部署离线应用。

    1. 使用以下YAML内容,创建be-ffmpeg.yaml文件。

      展开查看YAML详情

      # FFmpeg实例,作为离线类型计算应用。
      apiVersion: v1
      kind: Pod
      metadata:
        name: be-ffmpeg
        labels:
          app: ffmpeg
        # 1. 按照K8s默认混合部署模式部署:删除以下koordinator.sh/qosClass=BElabel。
        # 2. 按照ACK差异化SLO混部模式部署:保留以下koordinator.sh/qosClass=BElabel。
          koordinator.sh/qosClass: BE
      spec:
        containers:
          # FFmpeg的进程数量可以根据测试需求调节,进程数越多对应的离线资源使用率越高,默认为25个进程,每个进程有两个线程并发工作。
          - command:
              - start-ffmpeg.sh
              - '25'
              - '2'
              - /apps/ffmpeg/input/HD2-h264.ts
              - /apps/ffmpeg/
            image: 'registry.cn-zhangjiakou.aliyuncs.com/acs/ffmpeg-4-4-1-for-slo-test:v0.1'
            imagePullPolicy: Always
            name: ffmpeg
            resources:
            # 1. 按照K8s默认混合部署模式部署:删除以下扩展资源kubernetes.io/batch-cpukubernetes.io/batch-memory。
            # 2. 按照ACK差异化SLO混部模式部署:保留以下扩展资源kubernetes.io/batch-cpukubernetes.io/batch-memory。
            # 具体资源需求量请按节点规格按需调整。
              limits:
                kubernetes.io/batch-cpu: 70k
                kubernetes.io/batch-memory: 22Gi
              requests:
                kubernetes.io/batch-cpu: 70k
                kubernetes.io/batch-memory: 22Gi
        hostNetwork: true
        restartPolicy: Never
        nodeName: cn-beijing.192.168.2.93  # 请替换为您的测试机的节点名称。
    2. 执行以下命令,部署FFmpeg应用。

      kubectl apply -f be-ffmpeg.yaml
    3. 执行以下命令,查看FFmpeg应用的Pod状态。

      kubectl get pod -l app=ffmpeg -o wide

      预期输出:

      NAME        READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES
      be-ffmpeg   1/1     Running   0          15s    11.162.XXX.XXX   cn-beijing.192.168.2.93   <none>           <none>

      由预期输出得到,Pod的状态为Running ,表示FFmpeg应用已在测试机上正常运行。

  4. 使用压测工具wrk,执行以下命令,向Nginx应用发起压测请求。

    # node_ip填写测试机的IP地址,用于wrk向测试机发起压测;8000Nginx暴露到测试机的端口。
    ./wrk -t6 -c54 -d60s --latency http://${node_ip}:8000/
  5. 执行以下命令,查看测试机的CPU资源利用率。

    kubectl top node

    预期输出:

    NAME                      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
    cn-beijing.192.168.2.93   65424m       63%    xxxx            xxxx
    cn-beijing.192.168.2.94   7040m        7%     xxxx            xxxx

    由预期输出得到,压测中测试机的平均CPU资源利用率约为63%

  6. 等待wrk运行结束,获取wrk打印的压测结果。

    压测结果请参见实验结果总览

实验结果总览

本实验通过以下指标评估不同混部模式下 Nginx 应用的性能表现及节点资源利用率:

  • 响应时间RT(Response Time)分位值:RT 是衡量在线应用性能的重要指标,数值越低表示服务性能越好。实验中通过 wrk 压测结果获取 RT 数据,反映 Nginx 处理请求的耗时。例如,RT-p50 表示 Nginx 处理前 50% 请求的最大耗时(中位数),RT-p90 表示处理前 90% 请求的最大耗时。

  • 节点CPU平均利用率:该指标反映节点上应用对 CPU 资源的使用情况,数值越高表明物理资源利用越充分。实验中通过 kubectl top node 获取该数据,用于评估不同混部模式下的 CPU 资源使用率。

预期结果如下:

指标/部署模式

基线(在线应用独立部署)

对照组(K8s默认混合部署)

实验组(ACK差异化SLO混部)

Nginx RT-p90(ms)

0.533

0.574(+7.7%)

0.548(+2.8%)

Nginx RT-p99(ms)

0.93

1.07(+16%)

0.96(+3.2%)

节点CPU平均利用率

29.6%

65.1%

64.8%

  • 对比基线和对照组:采用K8s默认的混合部署后,节点CPU平均利用率明显提升(从29.6%变为65.1%),Nginx RT-p90RT-p99明显增大,RT性能出现了长尾现象。

  • 对比基线和实验组:采用ACK差异化SLO混部后,节点CPU平均利用率明显提升(从28.5%变为64.8%),Nginx RT-p90RT-p99相对基线有所增高,但仍属于可接受范围内。

  • 对比对照组和实验组:ACK差异化SLO混部相比K8s默认混部,节点CPU平均利用率相近,Nginx RT-p90RT-p99明显下降,基本与基线数据持平。

综上,在线服务与离线视频转码应用混部场景下,采用ACK差异化SLO混部模式能够有效提升节点CPU资源利用率,抑制资源混部干扰。

后续操作

关于在离线混部功能的更多信息,请参见:

常见问题

在使用wrk压测中,测试结果提示“Socket errors: connect 54,”怎么办?

问题描述

在使用wrk压测中,测试结果提示Socket errors: connect 54,。测试中的wrk ClientNginx Server建立连接失败,测试结果失效。

问题原因

该错误通常是因为客户端的连接数受限,导致客户端建立连接失败。

解决办法

为了避免该错误,请在压测机上检查系统的TCP连接配置,并尝试启用TCP连接重用。

  1. 登录压测机,执行如下命令,查看是否开通TCP连接重用。

    sudo sysctl -n net.ipv4.tcp_tw_reuse

    命令输出为02,说明系统未完全开启TCP连接重用。

  2. 执行如下命令,启用TCP连接重用。

    sudo sysctl -w net.ipv4.tcp_tw_reuse=1
  3. 使用wrk工具再次发起压测请求。

    检查测试结果不再包含Socket errors: connect 54, ...的报错提示,说明测试结果有效。

说明

操作步骤中使用的指令仅在压测机上执行,测试机无需配置。测试完成后,请通过sysctl -w net.ipv4.tcp_tw_reuse恢复原始配置,避免不必要的影响。