Apache YuniKorn 1.10.0 Docker Compose 部署指南

使用 Docker Compose 一键部署单节点 Apache YuniKorn 1.10.0 环境,涵盖镜像选型、数据持久化、常用环境变量与配置参数、等价 docker run 与运维命令,完整栈经真实环境实测拉起。

Apache YuniKornApache YuniKorn2026/10/12

Apache YuniKorn 1.10.0 Docker Compose 部署指南

一、环境信息

项目值
宿主机操作系统Linux x86_64(内核 6.x)
Docker 版本29.8.0(实测;建议 24 及以上)
Docker Compose 版本v5.5.1(实测;建议 v2 及以上)
YuniKorn 版本1.10.0(官方最新稳定版)
k3s 版本v1.36.5+k3s1(rancher/k3s:v1.36.5-k3s1)
引导工具 imagedtzar/helm-kubectl:3.16.4
暴露端口9889(Web UI,宿主机可达)
部署目录/opt/yunikorn-compose
执行账号root

YuniKorn 是运行在 Kubernetes 之上的调度器,本方案用 Docker Compose 在单台服务器上编排一套完整环境:k3s 承担 Kubernetes 角色,一个一次性服务把 YuniKorn 三组件 image 导入 k3s 的 image 存储,再由引导服务通过 Helm 完成 YuniKorn 安装并把 Web UI 端口暴露到宿主机。整个栈已在真实环境完整拉起并验证。

二、镜像选型说明

image版本用途来源
rancher/k3sv1.36.5-k3s1单节点 Kubernetes 集群服务Docker Hub 官方
apache/yunikornscheduler-1.10.0调度器核心Docker Hub 官方 apache 仓库
apache/yunikornadmission-1.10.0准入控制器Docker Hub 官方 apache 仓库
apache/yunikornweb-1.10.0Web UIDocker Hub 官方 apache 仓库
rancher/mirrored-pause3.10.2k3s 节点基础 Pod 所需的 pause imageDocker Hub 官方
dtzar/helm-kubectl3.16.4Helm 与 kubectl 引导工具Docker Hub 社区维护

选型要点:

  1. YuniKorn 三组件 image 版本号统一固定为 1.10.0,与 Chart 版本一致,避免组件间版本漂移。
  2. rancher/mirrored-pause 必须与 YuniKorn image 一起预导入 k3s,否则首个 Pod 调度时节点上没有 pause image 会导致启动异常。
  3. 网络受限的服务器,rancher/k3s 与 dtzar/helm-kubectl 两个 image 也建议提前在能联网的机器上 docker pull 后 docker save 打包带过来,用 docker load 导入。

三、前置条件

  1. 宿主机已安装 Docker 与 Compose 插件,Docker 服务运行中。
  2. 端口 9889 未被占用。
  3. 已准备好两个资源文件:
    • chart/yunikorn-1.10.0.tgz:Chart 包,由 helm pull yunikorn/yunikorn --version 1.10.0 获得(需先 helm repo add yunikorn https://apache.github.io/yunikorn-release);
    • images/yunikorn-stack.tar:YuniKorn 组件 image 离线包,由以下命令打包:
docker pull apache/yunikorn:scheduler-1.10.0
docker pull apache/yunikorn:admission-1.10.0
docker pull apache/yunikorn:web-1.10.0
docker pull rancher/mirrored-pause:3.10.2
docker save -o yunikorn-stack.tar apache/yunikorn:scheduler-1.10.0 apache/yunikorn:admission-1.10.0 apache/yunikorn:web-1.10.0 rancher/mirrored-pause:3.10.2
  1. 确认 Docker 与 Compose 版本:
docker compose version

实测回显(运行环境参考):

Docker Compose version v5.5.1

四、部署步骤

4.1 建立目录结构

mkdir -p /opt/yunikorn-compose/chart /opt/yunikorn-compose/images

将 yunikorn-1.10.0.tgz 上传至 chart/ 目录,yunikorn-stack.tar 上传至 images/ 目录。完成后结构如下:

/opt/yunikorn-compose
├── chart
│   └── yunikorn-1.10.0.tgz
├── docker-compose.yml
└── images
    └── yunikorn-stack.tar

4.2 编写 docker-compose.yml

在 /opt/yunikorn-compose/docker-compose.yml 写入以下内容(本文件为实测通过的完整版本):

services:
  k3s:
    image: rancher/k3s:v1.36.5-k3s1
    container_name: yunikorn-k3s
    privileged: true
    command: server --disable=traefik --disable=metrics-server --disable=servicelb --disable=local-storage --disable=coredns --write-kubeconfig-mode=644
    environment:
      K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml
      K3S_KUBECONFIG_MODE: "644"
    volumes:
      - kubeconfig:/output
      - containerd-sock:/run/k3s/containerd
      - k3s-data:/var/lib/rancher/k3s
    healthcheck:
      test: ["CMD-SHELL", "KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl get nodes | grep -w Ready"]
      interval: 10s
      timeout: 10s
      retries: 30
      start_period: 60s
    ports:
      - "9889:9889"

  import-images:
    image: rancher/k3s:v1.36.5-k3s1
    depends_on:
      - k3s
    volumes:
      - containerd-sock:/run/k3s/containerd
      - ./images:/images:ro
    entrypoint: ["sh", "-c", "until [ -S /run/k3s/containerd/containerd.sock ]; do echo waiting-socket; sleep 2; done; ctr --address /run/k3s/containerd/containerd.sock -n k8s.io images import /images/yunikorn-stack.tar && echo import-done"]

  yunikorn-bootstrap:
    image: dtzar/helm-kubectl:3.16.4
    depends_on:
      k3s:
        condition: service_healthy
      import-images:
        condition: service_completed_successfully
    volumes:
      - kubeconfig:/kubeconfig:ro
      - ./chart:/chart:ro
    environment:
      KUBECONFIG: /kubeconfig/kubeconfig.yaml
    network_mode: "service:k3s"
    command: ["sh", "-c", "helm upgrade --install yunikorn /chart/yunikorn-1.10.0.tgz -n yunikorn --create-namespace --set image.pullPolicy=IfNotPresent --set admissionController.image.pullPolicy=IfNotPresent --set web.image.pullPolicy=IfNotPresent && until kubectl wait --for=condition=available deploy --all -n yunikorn --timeout=300s; do sleep 5; done; until kubectl port-forward -n yunikorn svc/yunikorn-service 9889:9889 --address=0.0.0.0; do echo retry-port-forward; sleep 5; done"]

volumes:
  kubeconfig:
  containerd-sock:
  k3s-data:

编排设计说明:

  1. import-images 通过与 k3s 共享的 containerd-sock 卷,用 ctr 命令把离线 image 包直接导入 k3s 的 image 存储,是典型的离线导入路径。
  2. yunikorn-bootstrap 使用 network_mode: "service:k3s" 复用 k3s 的网络命名空间,kubeconfig 中的 127.0.0.1:6443 服务地址因此可直接访问。
  3. 引导命令链为:Helm 幂等安装、等待全部组件 Available、最后前台保持 port-forward,把 9889 端口透传到 k3s 服务的 9889 端口,再由 compose 的 ports 映射到宿主机。

4.3 启动整个栈

cd /opt/yunikorn-compose && docker compose up -d

启动过程约 1 至 2 分钟(k3s 就绪、image 导入、Helm 安装、Pod 拉起)。确认服务状态:

docker compose ps

实测回显:

NAME                        IMAGE                       COMMAND                  SERVICE              CREATED          STATUS                    PORTS
work-yunikorn-bootstrap-1   dtzar/helm-kubectl:3.16.4   "sh -c 'helm upgrade…"   yunikorn-bootstrap   27 minutes ago   Up 27 minutes
yunikorn-k3s                rancher/k3s:v1.36.5-k3s1    "/bin/k3s server --d…"   k3s                  27 minutes ago   Up 27 minutes (healthy)   0.0.0.0:9889->9889/tcp, [::]:9889->9889/tcp

k3s 显示 healthy 即集群就绪。

4.4 验证部署结果

进入 k3s 容器查看节点:

docker exec yunikorn-k3s kubectl get nodes

实测回显(首次部署应为单个 Ready 节点;多次重建容器可能残留历史节点,处理方式见常见问题):

NAME           STATUS   ROLES           AGE   VERSION
45f7ef281c3e   Ready    control-plane   41m   v1.36.5+k3s1

查看 YuniKorn 组件:

docker exec yunikorn-k3s kubectl -n yunikorn get pods

实测回显:

NAME                                             READY   STATUS    RESTARTS   AGE
yunikorn-admission-controller-5545d5475b-6kd82   1/1     Running   0          41m
yunikorn-scheduler-796754f677-nx47v              2/2     Running   0          35m

验证 Web UI 已暴露到宿主机 9889 端口:

curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9889/

实测回显:

200
curl -s http://127.0.0.1:9889/ | grep -o "<title>[^<]*</title>"

实测回显:

<title>YuniKorn UI</title>

浏览器访问 http://<服务器IP>:9889 即可打开 YuniKorn 调度界面。

五、数据持久化说明

卷挂载点作用生命周期
k3s-data/var/lib/rancher/k3sk3s 集群全部状态,含集群数据、image 存储数据、YuniKorn 的 ConfigMap 等资源持久;down 后再 up 保留
containerd-sock/run/k3s/containerdk3s 内置 image 存储套接字与数据持久;导入的 image 保存在 k3s-data
kubeconfig/output 与 /kubeconfigk3s 生成的 kubeconfig 文件持久
./chart、./images(bind 挂载)宿主机目录Chart 包与 image 离线包随宿主机目录

说明:docker compose down 默认不删除 named volume,因此集群状态与已导入的 image 都会保留;若执行 docker compose down -v,全部数据将被清除,下次 up 会重新走一遍 image 导入与 Helm 安装流程。

六、常用环境变量表

环境变量所在服务默认值说明
K3S_KUBECONFIG_OUTPUTk3s/output/kubeconfig.yamlk3s 将 kubeconfig 写出到共享卷
K3S_KUBECONFIG_MODEk3s644kubeconfig 文件权限,便于引导服务读取
KUBECONFIGyunikorn-bootstrap/kubeconfig/kubeconfig.yaml引导服务使用的 kubeconfig 路径

k3s 服务本身支持通过环境变量传递安装参数(K3S_ 前缀),本栈将 k3s 启动参数直接写在 command 中,二者等价。

七、常用配置参数说明

7.1 Helm 安装参数

引导服务的 helm 命令可通过 --set 追加参数调整 YuniKorn 部署形态,常用项:

参数默认值说明
image.pullPolicyAlways调度器 image 拉取策略,离线环境必须设为 IfNotPresent
admissionController.image.pullPolicyAlways准入控制器 image 拉取策略,离线环境设为 IfNotPresent
web.image.pullPolicyAlwaysWeb UI image 拉取策略,离线环境设为 IfNotPresent
resources.requests.memory1Gi调度器内存请求
resources.limits.memory2Gi调度器内存限额
goMemoryLimitPercentage80GOMEMLIMIT 占内存限额的百分比
goGC100Go 垃圾回收目标百分比

7.2 调度队列配置

队列与配额通过 ConfigMap yunikorn-defaults 的 queues.yaml 键下发,修改后热加载生效。以热调整日志级别为例:

docker exec yunikorn-k3s kubectl -n yunikorn patch cm yunikorn-defaults -p '{"data":{"log.level":"DEBUG"}}'

实测回显:

configmap/yunikorn-defaults patched

7.3 端口调整

宿主机侧只需修改 k3s 服务的 ports 映射即可更换对外端口,例如改为 "18989:9889" 后从 18989 访问 UI;k3s 内部端口不需要任何改动。

八、配置文件持久化

  1. Chart 包与 image 离线包以 bind 挂载方式固定在宿主机 chart/ 与 images/ 目录,重建容器不丢失,且以只读方式挂载防止误改。
  2. YuniKorn 的队列配置保存在 k3s-data 卷内的集群状态中(ConfigMap yunikorn-defaults),docker compose down 重启后依然生效。
  3. 若需要固化自定义队列配置,推荐把 --set 参数固化进 docker-compose.yml 的引导命令,或将自定义 queues.yaml 的写入步骤固化到引导命令中执行,保证重建后配置可复现。
  4. 该 ConfigMap 带 helm.sh/resource-policy: keep 注解,卸载 Chart 时不会被删除,为配置持久化提供了额外保障。

九、等价 docker run 运行方式

不使用 Compose 时,以下三条命令与整个栈等价(按顺序执行):

启动 k3s 服务:

docker run -d --name yunikorn-k3s --privileged \
  -p 9889:9889 \
  -v yunikorn-kubeconfig:/output \
  -v yunikorn-sock:/run/k3s/containerd \
  -v yunikorn-k3sdata:/var/lib/rancher/k3s \
  rancher/k3s:v1.36.5-k3s1 \
  server --disable=traefik --disable=metrics-server --disable=servicelb --disable=local-storage --disable=coredns --write-kubeconfig-mode=644

导入 YuniKorn image 离线包:

docker run --rm \
  -v yunikorn-sock:/run/k3s/containerd \
  -v /opt/yunikorn-compose/images:/images:ro \
  rancher/k3s:v1.36.5-k3s1 \
  sh -c "until [ -S /run/k3s/containerd/containerd.sock ]; do sleep 2; done; ctr --address /run/k3s/containerd/containerd.sock -n k8s.io images import /images/yunikorn-stack.tar"

安装 YuniKorn 并保持端口转发(复用 k3s 的网络命名空间):

docker run -d --name yunikorn-bootstrap \
  --network container:yunikorn-k3s \
  -v yunikorn-kubeconfig:/kubeconfig:ro \
  -v /opt/yunikorn-compose/chart:/chart:ro \
  -e KUBECONFIG=/kubeconfig/kubeconfig.yaml \
  dtzar/helm-kubectl:3.16.4 \
  sh -c "helm upgrade --install yunikorn /chart/yunikorn-1.10.0.tgz -n yunikorn --create-namespace --set image.pullPolicy=IfNotPresent --set admissionController.image.pullPolicy=IfNotPresent --set web.image.pullPolicy=IfNotPresent && kubectl wait --for=condition=available deploy --all -n yunikorn --timeout=300s && kubectl port-forward -n yunikorn svc/yunikorn-service 9889:9889 --address=0.0.0.0"

与 Compose 版本的差异:docker run 方式需要手工保证执行顺序(k3s 就绪后再导入与安装),Compose 通过 depends_on 条件自动编排,生产使用推荐 Compose 方式。

十、常用运维命令

docker compose ps

查看服务状态(k3s 应为 healthy)。

docker compose logs -f yunikorn-bootstrap

跟踪引导服务日志,可看到 Helm 安装输出与 port-forward 建立过程。

docker compose restart k3s

重启 Kubernetes 服务,YuniKorn 组件随之自动恢复。

docker compose down

停止整个栈(保留数据卷,重新 up 后配置与 image 均保留)。

docker exec yunikorn-k3s kubectl -n yunikorn get pods

查看 YuniKorn 组件运行状态。

docker exec yunikorn-k3s kubectl -n yunikorn get cm yunikorn-defaults -o yaml

查看当前下发的调度配置。

十一、常见问题

Q1:进入 k3s 容器执行 k3s kubectl 报 unknown command?

rancher/k3s 镜像内置的 k3s kubectl 子命令存在兼容问题(实测报 unknown command kubectl)。解决方式:改用镜像内自带的独立 kubectl 并显式指定 kubeconfig,即 KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl get nodes;docker exec 进入容器后同理。本方案的 healthcheck 与引导服务均已按此方式编写。

Q2:import-images 服务一直输出 waiting-socket?

该服务在等待 k3s 的 image 存储套接字文件出现,属于正常启动阶段;k3s 容器 healthy 后套接字即出现,导入完成会输出 import-done 并正常退出。若长时间卡住,检查 k3s 容器日志(docker compose logs k3s)确认集群是否启动成功。

Q3:kubectl get nodes 出现 NotReady 的历史节点,新 Pod 可能调度失败?

多次重建 k3s 容器(更换过容器名或数据卷)会残留陈旧的 Node 对象,实测新组件 Pod 可能被调度到已不存在的节点上长期 Pending。删除陈旧节点即可自愈:

docker exec yunikorn-k3s kubectl delete node <陈旧节点名>

实测删除后组件 Pod 重新调度成功。全新部署不存在该问题。

Q4:Web UI 打不开或 port-forward 起不来?

引导服务的 port-forward 前置了 kubectl wait --for=condition=available,组件未就绪时会每 5 秒重试(日志出现 retry-port-forward),属正常现象。若长期失败,依次检查:组件 Pod 是否 Running(docker exec yunikorn-k3s kubectl -n yunikorn get pods)、是否存在 Q3 的陈旧节点、宿主机 9889 端口是否被占用。

Q5:组件镜像拉取失败 ImagePullBackOff?

Chart 默认 pullPolicy 为 Always,会强制回源拉取。本方案的引导命令已把三个组件全部设为 IfNotPresent,配合 import-images 导入的离线包即可完全离线运行;若自行修改了 helm 命令,务必保留这三个 --set 参数。

十二、参考链接

  1. YuniKorn 官方安装文档:https://yunikorn.apache.org/docs/next/deployment/scheduler
  2. YuniKorn 官方 Helm Chart 仓库:https://github.com/apache/yunikorn-release
  3. k3s 官方文档:https://docs.k3s.io/
  4. Docker Compose 官方文档:https://docs.docker.com/compose/
  5. GitHub Release v1.10.0:https://github.com/apache/yunikorn-release/releases/tag/v1.10.0