【集群】云原生批调度实战:调度器测试与监控工具 kube-scheduling-perf 注意事项说明

【集群】云原生批调度实战:调度器测试与监控工具 kube-scheduling-perf 注意事项说明

Fre5h1nd Lv6

本系列《云原生批调度实战:Volcano 深度解析》计划分为以下几篇,点击查看其它内容。

  1. 云原生批调度实战:Volcano 深度解析(一)批处理背景需求与Volcano特点
  2. 云原生批调度实战:Volcano 深度解析(二)Volcano调度流程与调度状态
  3. 云原生批调度实战:Volcano 安装与初试
  4. 云原生批调度实战:调度器测试与监控工具 kube-scheduling-perf
  5. 云原生批调度实战:调度器测试与监控工具 kube-scheduling-perf 注意事项说明
  6. 云原生批调度实战:调度器测试监控结果

💡简介

📖 文档定位:本文为 kube-scheduling-perf 项目的实际部署篇,与 理论介绍文档 形成互补。理论介绍文档重点解析项目的架构设计和自动化原理,而本文则专注于解决实际部署过程中的各种技术难题。

适用场景:如果您已经阅读了理论介绍文档,并计划在实际环境中部署和使用 kube-scheduling-perf 工具,那么本文档将为您提供必要的技术支持和故障排除指南。

🖼️背景

为什么需要这份注意事项文档?

kube-scheduling-perf 项目虽然提供了完善的自动化测试框架,但在实际部署过程中,由于以下因素,用户往往会遇到各种技术障碍:

1. 环境差异

  • 网络环境:国内用户访问海外镜像仓库时经常遇到网络超时问题
  • 系统版本:不同Linux发行版和内核版本对Docker、Kubernetes的支持程度不同
  • 硬件配置:老旧服务器可能无法运行最新版本的容器和工具

2. 权限和配置问题

  • 用户权限:Docker容器运行时的用户权限配置不当
  • 目录权限:自动生成的目录和文件所有权问题
  • 系统配置:内核参数、cgroup配置等系统级设置

3. 版本兼容性

  • Go版本:不同Go版本对测试代码的兼容性差异
  • Docker版本:容器运行时版本与Kubernetes版本的匹配问题
  • Kubernetes版本:API版本变化导致的兼容性问题

文档价值

本文档基于实际部署经验总结,提供了:

  • 系统性的问题分类:将常见问题按类型进行归类
  • 详细的解决方案:每个问题都提供具体的解决步骤
  • 预防性建议:帮助用户提前避免可能遇到的问题
  • 故障排除指南:快速定位和解决部署过程中的技术难题

希望通过本文档,帮助大家避免重复踩坑,提高部署效率,顺利运行测试工具~

🔨注意事项

注意1:加速镜像拉取

在国内环境下需要使用CDN加速镜像拉取[2]

Go 相关包

Makefile文件中替换GOPROXY ?= https://proxy.golang.org,directGOPROXY ?= https://mirrors.aliyun.com/goproxy/,direct

Docker 相关包

在执行 make 命令时,由于需要从海外服务器拉取镜像,频繁出现超时错误:

1
2
Error response from daemon: Head "https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/kwok/kwok/manifests/v0.6.1": dial tcp 142.250.157.82:443: i/o timeout
Error response from daemon: Get "https://registry.k8s.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

DaoCloud 镜像仓库提供了非常方便的解决方案,感恩!使用 DaoCloud 镜像加速,只需要在镜像前加上前缀 m.daocloud.io/

修改内容

1. Makefile 配置

1
2
3
4
5
# 修改前
IMAGE_PREFIX ?=

# 修改后
IMAGE_PREFIX ?= m.daocloud.io/

2. 脚本配置
hack/local-registry-with-load-images.sh 中:

1
2
3
4
5
# 修改前
IMAGE_PREFIX="${IMAGE_PREFIX:-}"

# 修改后
IMAGE_PREFIX="${IMAGE_PREFIX:-m.daocloud.io/}"

工作原理

  • 镜像处理流程:所有镜像通过 hack/local-registry-with-load-images.sh 脚本处理
  • DaoCloud 加速:脚本会自动从 m.daocloud.io/ 拉取镜像,然后推送到本地仓库 localhost:5001/
  • 容器内 Docker:即使使用容器内的 Docker,也会通过 IMAGE_PREFIX 环境变量传递镜像前缀

注意2:内核版本适配

问题说明

如之前KIND安装博客所述,本人所使用服务器内核版本过低(3.10.0-1160.71.1.el7.x86_64),无法运行较高版本的Kubernetes和Kind,权衡之计是进行版本降级以解决兼容性问题。

  • 降级之后,仍然会收到报错:✗ Preparing nodes 📦 ; Command Output: WARNING: Your kernel does not support cgroup namespaces. Cgroup namespace setting discarded.
    • 具体分析后发现 Kind 自动添加 cgroupns 参数:从日志中可以看到,kind 在创建集群时自动添加了 –cgroupns=private 参数,这是较新版本 kind 的默认行为。
    • 解决方案:修改 kind 配置,./hack/kind-with-local-registry.sh中,在kind create ...之前增加以下代码:
      1
      2
      3
      4
      5
      6
      7
      ...
      # 新增以下代码:Disable cgroup namespaces for older kernels
      export KIND_EXPERIMENTAL_DISABLE_CGROUP_NAMESPACES=true

      # Create kind cluster with containerd registry configuration
      kind create cluster --config "${KIND_CONFIG:-}" --name "${KIND_CLUSTER_NAME:-kind}"
      ...

版本降级目标

  • Go版本: 1.24 → 1.23.10
  • Kind版本: v0.27.0 → v0.19.0
  • Kubernetes版本: v1.25.3 → v1.27.1

修改列表

Go

  • go.mod中:go 1.24go 1.23.10
  • Makefile中:GO_IMAGE ?= $(IMAGE_PREFIX)docker.io/library/golang:1.24GO_IMAGE ?= $(IMAGE_PREFIX)docker.io/library/golang:1.23.10

Kind

  • go.mod中:sigs.k8s.io/kind v0.27.0sigs.k8s.io/kind v0.19.0

节点Kubernetes:

  • go.mod中:修改k8s配置 v0.32.1v0.27.1
    1
    2
    3
    4
    5
    k8s.io/api v0.27.1
    k8s.io/apimachinery v0.27.1
    k8s.io/apiextensions-apiserver v0.27.1 // indirect
    k8s.io/client-go v0.27.1 // indirect
    k8s.io/component-base v0.27.1 // indirect
  • ./cluster目录下的kueuevolcanoyunikornoverview四个目录中修改kind.yaml文件:docker.io/kindest/node:v1.32.2docker.io/kindest/node:v1.27.1

go.sum 版本管理文件[3]

  • 修改go.mod后,需要删除go.sum并执行go mod tidy以重新生成go.sum以匹配新的依赖版本。
  • 必要时开启CDN镜像加速export GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
  • 如果一直出现奇怪的错误,例如go: github.com/wzshiming/kube-scheduling-perf/gopath/pkg/mod/github.com/pkg/errors@v0.9.1: import path "github.com/wzshiming/kube-scheduling-perf/gopath/pkg/mod/github.com/pkg/errors@v0.9.1" should not have @version,可能是因为已安装的旧版本未删除,应该删除旧的 gopath 并重新构建,以确保参数生效:
    1
    2
    sudo rm -rf gopath
    make

其它

  • 之后./hack/local-registry-with-load-images.sh会自动提前拉取镜像。
  • 注意:如果你是通过 Makefile 自动构建 bin/kind,请务必删除旧的 bin/kind 并重新构建,以确保新参数生效:
    1
    2
    sudo rm -f bin/kind
    make bin/kind
  • 注意:同理,如果修改版本前已经下载了相关go包,也应该删除旧的 gopath 并重新构建,以确保参数生效:
    1
    2
    sudo rm -rf gopath
    make

注意3:Go 版本兼容性问题

问题说明

降级 Go 版本后,测试代码中出现编译错误:

1
test/yunikorn/batch_job_test.go:10:29: t.Context undefined (type *"testing".T has no field or method Context, but does have unexported field context)

原因分析

t.Context() 方法在 Go 1.23.10 中可能不被完全支持或存在兼容性问题,导致测试代码无法编译。

解决方案

将所有测试文件中的 t.Context() 替换为 context.Background()

修改文件

1. test/yunikorn/batch_job_test.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 修改前
import (
"testing"
"github.com/wzshiming/kube-scheduling-perf/test/utils"
)

func TestInit(t *testing.T) {
err := provider.AddNodes(t.Context())
// ...
}

// 修改后
import (
"context"
"testing"
"github.com/wzshiming/kube-scheduling-perf/test/utils"
)

func TestInit(t *testing.T) {
err := provider.AddNodes(context.Background())
// ...
}

2. test/volcano/batch_job_test.go

  • 同样添加 "context" 导入
  • 将所有 t.Context() 替换为 context.Background()

3. test/kueue/batch_job_test.go

  • 同样添加 "context" 导入
  • 将所有 t.Context() 替换为 context.Background()

注意4:Docker 容器权限问题

问题说明

执行 make 命令时出现权限错误:

1
mv: 无法将"./logs" 移动至"./tmp/logs": 权限不够

检查发现多个目录(./logs./bin./gopath./registry-data)的归属者是 root,而不是当前用户(当使用非 root 用户时)。

原因分析

Makefile 中的 GO_IN_DOCKER 命令使用 Docker 容器执行,容器内进程默认以 root 用户运行,导致创建的文件/目录归属 root。

解决方案

1. 修改 Makefile,让容器以当前用户身份运行

1
2
3
4
5
6
7
8
9
10
# 修改前
GO_IN_DOCKER = docker run --rm --network host \
-v $(shell pwd):/workspace/ -w /workspace/ \
-e GOOS=$(GOOS) -e CGO_ENABLED=0 -e GOPATH=/workspace/gopath/ -e GOPROXY=$(GOPROXY) $(GO_IMAGE)

# 修改后
GO_IN_DOCKER = docker run --rm --network host \
-u $(shell id -u):$(shell id -g) \
-v $(shell pwd):/workspace/ -w /workspace/ \
-e GOOS=$(GOOS) -e CGO_ENABLED=0 -e GOPATH=/workspace/gopath/ -e GOPROXY=$(GOPROXY) $(GO_IMAGE)

2. 创建目录权限修复脚本

hack/ensure-directories.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

DIR="$(dirname "${BASH_SOURCE[0]}")"
ROOT_DIR="$(realpath "${DIR}/..")"

# Function to ensure directory has correct ownership
ensure_directory() {
local dir="$1"
local owner=$(stat -c '%U' "$dir" 2>/dev/null || echo "none")

if [[ "$owner" == "root" ]]; then
echo "Removing root-owned directory: $dir"
sudo rm -rf "$dir"
fi

mkdir -p "$dir"
chmod 755 "$dir"
echo "Created/updated directory: $dir"
}

# Create all necessary directories
for d in logs bin gopath registry-data output results tmp; do
ensure_directory "${ROOT_DIR}/${d}"
done

3. 在 Makefile 中集成权限修复

1
2
3
4
5
6
7
8
9
10
11
.PHONY: ensure-directories
ensure-directories:
./hack/ensure-directories.sh

.PHONY: default
default: ensure-directories
# ... existing content ...

.PHONY: serial-test
serial-test: ensure-directories bin/kind
# ... existing content ...

4. 修改镜像处理脚本

hack/local-registry-with-load-images.sh 中确保 registry-data 目录正确创建:

1
2
# Ensure registry-data directory exists with correct permissions
mkdir -p "${ROOT_DIR}/registry-data"

验证方法

1
2
3
4
5
# 运行权限修复脚本
./hack/ensure-directories.sh

# 检查目录权限
ls -la | grep -E "(logs|bin|gopath|registry-data)"

注意5:目录结构说明

核心目录

  • hack/: 存放辅助脚本,如权限修复、镜像处理、结果保存等

    • ensure-directories.sh: 确保目录权限正确
    • local-registry-with-load-images.sh: 处理镜像拉取和本地仓库
    • save-result-images.sh: 保存测试结果和监控图表
    • kind-with-local-registry.sh: 创建带本地仓库的 kind 集群
  • clusters/: 各调度器的集群配置和生命周期管理

    • kueue/: Kueue 调度器集群配置
    • volcano/: Volcano 调度器集群配置
    • yunikorn/: YuniKorn 调度器集群配置
    • overview/: 监控集群配置(Prometheus + Grafana)
  • test/: 测试代码和测试用例

    • utils/: 通用测试工具和辅助函数
    • kueue/: Kueue 调度器测试代码
    • volcano/: Volcano 调度器测试代码
    • yunikorn/: YuniKorn 调度器测试代码

生成目录

  • bin/: 自动生成的二进制文件
    • kind: 用于创建 Kubernetes 集群的工具
    • test-kueue: Kueue 测试可执行文件
    • test-volcano: Volcano 测试可执行文件
    • test-yunikorn: YuniKorn 测试可执行文件
  • gopath/: Go 模块缓存和依赖
    • pkg/mod/: Go 模块缓存
    • src/: 源代码(如果使用 GOPATH 模式)

数据目录

  • logs/: 审计日志和测试日志
    • kube-apiserver-audit.*.log: Kubernetes API 服务器审计日志
    • 其他测试过程中生成的日志文件
  • registry-data/: 本地 Docker 仓库数据
    • 存储从远程仓库拉取的镜像
    • 供 kind 集群使用的本地镜像仓库
  • output/: 测试输出和监控数据
    • panel-*.png: Grafana 监控图表
    • 其他测试输出文件
  • results/: 测试结果归档
    • 按时间戳组织的测试结果目录
    • 包含环境变量、日志、输出等完整信息
  • tmp/: 临时文件目录
    • 测试过程中的临时文件
    • 结果归档前的临时存储


  • 希望这篇博客对你有帮助!如果你有任何问题或需要进一步的帮助,请随时提问。
  • 如果你喜欢这篇文章,欢迎动动小手给我一个follow或star。

🗺参考文献

[1] Github - kube-scheduling-perf

[2] Go 国内加速镜像

[3] 深入理解 Go Modules 的 go.mod 与 go.sum

  • 标题: 【集群】云原生批调度实战:调度器测试与监控工具 kube-scheduling-perf 注意事项说明
  • 作者: Fre5h1nd
  • 创建于 : 2025-06-30 11:17:44
  • 更新于 : 2025-06-30 12:11:42
  • 链接: https://freshwlnd.github.io/2025/06/30/k8s/k8s-scheduler-performance-test-debug/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论