☰
Kubernetes 节点性能基准测试镜像解析:基于 NAS 并行基准套件 Integer Sort(NPB-IS)的实践指南
2026/10/31 18:57:38 网站建设 项目流程

Kubernetes 节点性能基准测试镜像解析:基于 NAS 并行基准套件 Integer Sort(NPB-IS)的实践指南

【免费下载链接】kubernetesProduction-Grade Container Scheduling and Management项目地址: https://gitcode.com/GitHub_Trending/kuber/kubernetes

本文聚焦 Kubernetes 仓库 test/images/node-perf/npb-is/README.md 所描述的容器镜像——NPB Integer Sort(IS)基准测试负载。该镜像面向 Kubernetes 节点性能(Node Performance)测试场景,用于量化节点 CPU、内存子系统在计算密集型负载下的调度与运行表现。读完本文,你将掌握该镜像的目录组成、镜像构建原理(含 arm64 交叉构建细节)、一键构建与发布流程,以及它在节点 e2e 测试中如何作为标准负载被调度执行、如何从日志中提取性能指标。

一、为什么需要 NPB-IS 这样的计算密集型镜像

Kubernetes 的 Node Performance Testing(见 test/e2e_node/node_perf_test.go)是一组**串行(Serial)、慢速(Slow)**的节点端到端测试,其目的是在真实工作负载下观测 kubelet 所在节点的表现。这类测试需要三类覆盖不同计算特征的负载,在 test/e2e_node/perf/workloads/workloads.go#L52-L54 中统一定义:

var NodePerfWorkloads = []NodePerfWorkload{npbISWorkload{}, npbEPWorkload{}, pytorchWideDeepWorkload{}}

其中npbISWorkload{}对应的正是 NPB Integer Sort 基准。IS 基准的核心计算特征是大整数桶排序(bucket sort)——它通过大量随机数生成、桶分配与排序操作,对节点的整数运算能力、内存带宽与 Cache 行为产生持续高强度的压力。相比 EP(Embarrassingly Parallel,高度并行、几乎无通信)负载,IS 包含真实的数据依赖与访存模式,能让节点性能测试覆盖到更贴近实际计算任务的场景。因此,该镜像的定位不是"演示用容器",而是被 e2e 框架当作标准可重复的计算探针。

二、镜像目录构成:一份镜像所需的最小文件集合

npb-is镜像的完整上下文位于仓库根目录相对路径 test/images/node-perf/npb-is/ 下,共四个文件,每个文件各司其职:

文件作用
Dockerfile多阶段构建脚本,负责编译 NPB IS 并组装运行镜像
VERSION镜像版本号,当前为1.7.0
BASEIMAGE各架构基础镜像映射,支持多架构构建
README.md镜像用途与发布命令说明

BASEIMAGE 明确了多架构基础镜像策略(文件内容):

linux/amd64=debian:bookworm-slim linux/arm64=arm64v8/debian:bookworm-slim

VERSION并非装饰性文件。镜像注册信息位于 test/utils/image/manifest.go#L186-L187 与 #L230,它把NodePerfNpbIs这个镜像常量解析为完整的镜像拉取地址:

// NodePerfNpbIs image NodePerfNpbIs ... configs[NodePerfNpbIs] = Config{list.PromoterE2eRegistry, "node-perf/npb-is", "1.7.0"}

也就是说,e2e 测试实际拉取的镜像是registry.k8s.io/e2e-test-images/node-perf/npb-is:1.7.0(list.PromoterE2eRegistry即e2e-test-images仓库)。发布镜像时必须同步更新VERSION与manifest.go中的版本号,否则 e2e 拉取的仍是旧镜像。

三、深入 Dockerfile:从源码编译到可执行负载的完整链路

Dockerfile 采用多阶段构建(multi-stage build),完整还原了从 NASA NPB 源码到单二进制负载镜像的过程:

3.1 构建阶段:下载并编译 NPB 3.3.1

ARG BASEIMAGE FROM $BASEIMAGE AS build_node_perf_npb_is RUN apt-get update && apt-get install -y build-essential gfortran ADD http://www.nas.nasa.gov/assets/npb/NPB3.3.1.tar.gz . RUN tar xzf NPB3.3.1.tar.gz && chmod -R a+rX NPB3.3.1

要点说明:

  • BASEIMAGE通过ARG注入,实际取值来自上文BASEIMAGE文件(由image-util.sh构建脚本按目标架构传递);
  • NPB 的 IS 基准主体由 Fortran/MPI 与 OpenMP 版本构成,因此构建阶段安装gfortran(Fortran 编译器)与build-essential;这里的版本是NPB3.3.1发行版;
  • chmod -R a+rX修正文件权限,是为了配合QEMU 模拟的交叉构建(例如在 amd64 宿主机上构建 arm64 镜像)。

3.2 针对交叉构建的兼容性修补

WORKDIR ./NPB3.3.1/NPB3.3-OMP # Add missing shebangs to shell scripts - required for cross-build with QEMU emulation # Without shebangs, dash (default /bin/sh on Debian) fails to execute these scripts via make RUN sed -i '1i#!/bin/sh' sys/print_header sys/print_instructions

构建使用OpenMP 版 IS(NPB3.3-OMP),需要先运行make的打印头/打印指令脚本。上游发布的sys/print_header与sys/print_instructions缺少 shebang,在原生 glibc 环境下可能尚能执行,但在 QEMU 模拟的交叉构建环境下 Debian 默认/bin/sh(dash)会拒绝执行这类脚本,因此用sed在文件首行注入#!/bin/sh。这是"容器可复现构建"中典型的兼容性修补案例。

3.3 按架构生成编译配置

RUN if [ $(arch) = "aarch64" ]; then \ sed 's/-mcmodel=medium/-mcmodel=large -fno-PIE -mno-outline-atomics/g' config/NAS.samples/make.def.gcc_x86 > config/make.def; \ else \ cp config/NAS.samples/make.def.gcc_x86 config/make.def; \ fi RUN make IS CLASS=D

NPB 使用config/make.def作为编译配置,上游随包提供了config/NAS.samples/make.def.gcc_x86模板。这里按目标架构分支处理:

  • x86_64(amd64):直接复制gcc_x86模板即可;
  • aarch64(arm64):需把编译器选项-mcmodel=medium替换为-mcmodel=large -fno-PIE -mno-outline-atomics。原因在 Dockerfile 注释中已说明:-mcmodel=large使用大代码模型以容纳超出默认寻址范围的大型二进制;-fno-PIE关闭与 large model 不兼容的位置无关可执行文件;-mno-outline-atomics要求内联原子操作以避免链接期问题——这些都是在 arm64 上编译大体积 Fortran/OpenMP 程序时的实际工程经验。

make IS CLASS=D表示以CLASS=D(最大问题规模)编译 IS 基准,生成的可执行文件为bin/is.D.x。CLASS 是 NPB 的问题规模分级(S/W/A/B/C/D……),CLASS=D 代表大数据集,能对节点产生足够长的饱和计算压力。

3.4 依赖库收集与运行阶段组装

RUN mkdir -p /lib-copy && find /usr/lib -name "*.so.*" -exec cp {} /lib-copy \; FROM $BASEIMAGE COPY --from=build_node_perf_npb_is /NPB3.3.1/NPB3.3-OMP/bin/is.D.x / COPY --from=build_node_perf_npb_is /lib-copy /lib-copy ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/lib-copy" ENTRYPOINT /is.D.x

最终运行阶段只保留最精简的内容:

  • 把编译产物is.D.x复制到根目录/;
  • 把构建阶段收集到的共享库(/usr/lib下所有*.so.*)复制到/lib-copy,并通过LD_LIBRARY_PATH注入——这是为了让is.D.x在未安装gfortran运行库的精简基础镜像(bookworm-slim)中也能正常动态链接执行;
  • 容器启动即运行/is.D.x,基准完成后进程退出(退出码 0),容器状态随之变为 Completed——这一"跑完即退出"的设计正好契合测试框架对 Job 型负载的断言方式。

四、构建与发布:一条命令完成镜像的编译和推送

test/images/node-perf/npb-is/README.md 给出了两个发布命令,都基于test/images目录下统一的镜像构建体系:

# 构建 $ cd $K8S_ROOT/test/images $ make all WHAT=node-perf/npb-is # 推送 $ cd $K8S_ROOT/test/images $ make all-push WHAT=node-perf/npb-is

这里的$K8S_ROOT指仓库根目录。追踪 test/images/Makefile 可以看到这些 target 的真实行为:

REPO_ROOT:=${CURDIR}/../.. REGISTRY ?= registry.k8s.io/e2e-test-images all: all-container all-container: ./image-util.sh build $(WHAT) "docker" all-push: bash -x ./image-util.sh build $(WHAT) "registry" bash -x ./image-util.sh push $(WHAT) all-build-and-push: ./image-util.sh build_and_push ${WHAT}

几个关键点:

  • WHAT是必需变量:未传WHAT时 Makefile 直接报错(WHAT is a required variable),它的值是test/images下相对目录名,node-perf/npb-is即指向 node-perf 子目录里的npb-is镜像;
  • make all WHAT=node-perf/npb-is只做本地构建(docker驱动),产物可用于本地调试;
  • make all-push WHAT=node-perf/npb-is会先按registry驱动构建(依据 BASEIMAGE 完成多架构构建并推送到注册表),再执行push。最终镜像将推送到默认注册表registry.k8s.io/e2e-test-images/node-perf/npb-is,标签来自 VERSION 的1.7.0;
  • 若需一条命令同时完成构建与推送,也可使用make all-build-and-push WHAT=node-perf/npb-is。

镜像版本演进(1.7.0)需要与 test/utils/image/manifest.go#L230 的注册配置保持一致,否则 e2e 测试引用的镜像与最新发布版本会出现偏差。

五、镜像在节点性能 e2e 测试中的消费方式

镜像本身只是载体,真正的"工作负载定义"在 e2e 侧。理解 test/e2e_node/perf/workloads/npb_is.go 能让你看清楚:一个被拉起的 IS 基准容器,在节点测试里究竟占用多少资源、如何被断言成功。

5.1 工作负载接口:NodePerfWorkload

test/e2e_node/perf/workloads/workloads.go#L28-L50 定义了所有节点性能负载必须实现的接口:

type NodePerfWorkload interface { Name() string // 负载名称,如 "npb-is" PodSpec() v1.PodSpec // 运行该负载所需的 Pod 规格 Timeout() time.Duration // 预期完成时间 KubeletConfig(old *kubeletconfig.KubeletConfiguration) (new ..., err error) // 负载所需的 kubelet 配置 PreTestExec() error // 重启 kubelet 前的逻辑 PostTestExec() error // 负载完成后的逻辑 ExtractPerformanceFromLogs(logs string) (perf time.Duration, err error) // 从日志解析性能 }

npbISWorkload(npb_is.go)完整实现了该接口:

  • Name()返回"npb-is";
  • Timeout()为4 分钟(4 * time.Minute);
  • KubeletConfig/PreTestExec/PostTestExec均返回空操作,说明 IS 负载不依赖特殊 kubelet 配置(与需要 CPU Manager 介入的某些负载不同)。

5.2 资源规格:一份需要大节点的负载

npbISWorkload.PodSpec()(npb_is.go#L41-L65)声明了非常明确且严格的资源账本:

ctn := v1.Container{ Name: fmt.Sprintf("%s-ctn", w.Name()), Image: imageutils.GetE2EImage(imageutils.NodePerfNpbIs), Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("15000m"), v1.ResourceName(v1.ResourceMemory): resource.MustParse("48Gi"), }, Limits: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("15000m"), v1.ResourceName(v1.ResourceMemory): resource.MustParse("48Gi"), }, }, Command: []string{"/bin/sh"}, Args: []string{"-c", "/is.D.x"}, }

关键工程含义:

  • 15 个 CPU(15000m)与 48Gi 内存,且 Requests 与 Limits 相等——这是一份 Guaranteed QoS 的"大胃口"负载,要求被测节点拥有至少 15 核可用 CPU 与 48Gi 以上可分配内存。这也解释了为什么测试运行前要执行资源预检(见下文 5.4);
  • 启动命令并非直接执行ENTRYPOINT的/is.D.x,而是经/bin/sh -c "/is.D.x"包一层,便于在真实 Pod 环境中捕获子进程输出到容器日志;
  • RestartPolicy: Never:基准是一次性计算任务,跑完即 Pod 成功退出,不允许重启重试,避免污染性能读数。

5.3 性能指标提取:从日志中解析"Time in seconds"

NPB 基准运行结束会在标准输出打印Time in seconds = xxx。ExtractPerformanceFromLogs(npb_is.go#L83-L93)从 Pod 日志里精确取出该行,把=后的数值拼接成 Go 可解析的时长字符串(例如"42.35s"),再用time.ParseDuration转成time.Duration返回——这就是该轮节点性能测试的最终指标:完成 IS(D) 基准所消耗的墙钟时间。

5.4 测试主流程:从资源预检到指标落盘

test/e2e_node/node_perf_test.go 完整串联了镜像负载与测试框架的交互:

  1. 资源预检(BeforeEach,L146-L159):读取被测节点的 Allocatable CPU 与内存,若低于 15 核或 48Gi 则直接 Skip 该用例,避免在小节点上误报失败;
  2. Kubelet 配置装载:JustBeforeEach依次执行PreTestExec→ 读取当前 kubelet 配置 → 应用负载所需配置 → 必要时停止并重启 kubelet(IS 负载无需改动,走空路径);
  3. 创建并等待 Pod(runWorkload,L113-L144):以npb-is-pod命名创建 Pod,在 4 分钟超时内轮询等待 Pod 进入Succeeded或Failed状态;失败时主动抓取容器日志辅助排查;
  4. 提取并记录性能:调用ExtractPerformanceFromLogs得到time.Duration,通过framework.Logf输出Time to complete workload npb-is: ...;
  5. 清理:删除 Pod 并等待 15 秒让 CPU Manager 等组件完成收尾,再恢复原始 kubelet 配置。

从测试组织方式看,npb-is与npb-ep、pytorch-wide-deep并列为三组It用例(L161-L187),共同组成Node Performance Testing这一 Slow/Serial 测试套件。

六、快速自查清单与适用前提

结合前文,使用或复现 npb-is 镜像时建议按以下清单核对:

  1. 目录上下文齐全:npb-is/下必须同时存在Dockerfile、VERSION、BASEIMAGE与README.md,缺一不可;
  2. 版本同步:修改VERSION后需同步更新 test/utils/image/manifest.go#L230 中的版本常量,确保 e2e 引用一致;
  3. 构建环境:构建阶段需访问外网以下载 NASA NPB3.3.1 源码包;若目标为 arm64 且宿主为 x86_64,需具备 QEMU 模拟能力(Dockerfile 已内置相关兼容处理);
  4. 运行环境:直接运行该镜像需要节点提供约 15 核 CPU 与 48Gi 内存(Guaranteed 级);资源不足时 e2e 用例会跳过而非失败;
  5. 结果判定:容器正常退出即代表 IS(D) 基准跑完,性能参考值为日志中Time in seconds对应的时长,越短代表该节点在同类计算负载下完成基准越快。

总体上,test/images/node-perf/npb-is/ 呈现了一个"上游 HPC 基准 → 容器化 → 被 e2e 框架标准化消费"的完整范例:既适合作为理解 Kubernetes 多架构镜像构建流水线的入门样本(多阶段构建、QEMU 交叉编译、动态库收集),也为节点性能测试体系的负载设计提供了可参照的实现范式。

【免费下载链接】kubernetesProduction-Grade Container Scheduling and Management项目地址: https://gitcode.com/GitHub_Trending/kuber/kubernetes

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询