Apache YuniKorn 1.10.0 Docker Compose 部署指南
使用 Docker Compose 一键部署单节点 Apache YuniKorn 1.10.0 环境,涵盖镜像选型、数据持久化、常用环境变量与配置参数、等价 docker run 与运维命令,完整栈经真实环境实测拉起。
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) |
| 引导工具 image | dtzar/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/k3s | v1.36.5-k3s1 | 单节点 Kubernetes 集群服务 | Docker Hub 官方 |
| apache/yunikorn | scheduler-1.10.0 | 调度器核心 | Docker Hub 官方 apache 仓库 |
| apache/yunikorn | admission-1.10.0 | 准入控制器 | Docker Hub 官方 apache 仓库 |
| apache/yunikorn | web-1.10.0 | Web UI | Docker Hub 官方 apache 仓库 |
| rancher/mirrored-pause | 3.10.2 | k3s 节点基础 Pod 所需的 pause image | Docker Hub 官方 |
| dtzar/helm-kubectl | 3.16.4 | Helm 与 kubectl 引导工具 | Docker Hub 社区维护 |
选型要点:
- YuniKorn 三组件 image 版本号统一固定为 1.10.0,与 Chart 版本一致,避免组件间版本漂移。
rancher/mirrored-pause必须与 YuniKorn image 一起预导入 k3s,否则首个 Pod 调度时节点上没有 pause image 会导致启动异常。- 网络受限的服务器,
rancher/k3s与dtzar/helm-kubectl两个 image 也建议提前在能联网的机器上docker pull后docker save打包带过来,用docker load导入。
三、前置条件
- 宿主机已安装 Docker 与 Compose 插件,Docker 服务运行中。
- 端口 9889 未被占用。
- 已准备好两个资源文件:
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
- 确认 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:
编排设计说明:
import-images通过与 k3s 共享的containerd-sock卷,用ctr命令把离线 image 包直接导入 k3s 的 image 存储,是典型的离线导入路径。yunikorn-bootstrap使用network_mode: "service:k3s"复用 k3s 的网络命名空间,kubeconfig 中的127.0.0.1:6443服务地址因此可直接访问。- 引导命令链为: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/k3s | k3s 集群全部状态,含集群数据、image 存储数据、YuniKorn 的 ConfigMap 等资源 | 持久;down 后再 up 保留 |
| containerd-sock | /run/k3s/containerd | k3s 内置 image 存储套接字与数据 | 持久;导入的 image 保存在 k3s-data |
| kubeconfig | /output 与 /kubeconfig | k3s 生成的 kubeconfig 文件 | 持久 |
| ./chart、./images(bind 挂载) | 宿主机目录 | Chart 包与 image 离线包 | 随宿主机目录 |
说明:docker compose down 默认不删除 named volume,因此集群状态与已导入的 image 都会保留;若执行 docker compose down -v,全部数据将被清除,下次 up 会重新走一遍 image 导入与 Helm 安装流程。
六、常用环境变量表
| 环境变量 | 所在服务 | 默认值 | 说明 |
|---|---|---|---|
| K3S_KUBECONFIG_OUTPUT | k3s | /output/kubeconfig.yaml | k3s 将 kubeconfig 写出到共享卷 |
| K3S_KUBECONFIG_MODE | k3s | 644 | kubeconfig 文件权限,便于引导服务读取 |
| KUBECONFIG | yunikorn-bootstrap | /kubeconfig/kubeconfig.yaml | 引导服务使用的 kubeconfig 路径 |
k3s 服务本身支持通过环境变量传递安装参数(K3S_ 前缀),本栈将 k3s 启动参数直接写在 command 中,二者等价。
七、常用配置参数说明
7.1 Helm 安装参数
引导服务的 helm 命令可通过 --set 追加参数调整 YuniKorn 部署形态,常用项:
| 参数 | 默认值 | 说明 |
|---|---|---|
| image.pullPolicy | Always | 调度器 image 拉取策略,离线环境必须设为 IfNotPresent |
| admissionController.image.pullPolicy | Always | 准入控制器 image 拉取策略,离线环境设为 IfNotPresent |
| web.image.pullPolicy | Always | Web UI image 拉取策略,离线环境设为 IfNotPresent |
| resources.requests.memory | 1Gi | 调度器内存请求 |
| resources.limits.memory | 2Gi | 调度器内存限额 |
| goMemoryLimitPercentage | 80 | GOMEMLIMIT 占内存限额的百分比 |
| goGC | 100 | Go 垃圾回收目标百分比 |
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 内部端口不需要任何改动。
八、配置文件持久化
- Chart 包与 image 离线包以 bind 挂载方式固定在宿主机
chart/与images/目录,重建容器不丢失,且以只读方式挂载防止误改。 - YuniKorn 的队列配置保存在 k3s-data 卷内的集群状态中(ConfigMap
yunikorn-defaults),docker compose down重启后依然生效。 - 若需要固化自定义队列配置,推荐把
--set参数固化进 docker-compose.yml 的引导命令,或将自定义queues.yaml的写入步骤固化到引导命令中执行,保证重建后配置可复现。 - 该 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 参数。
十二、参考链接
- YuniKorn 官方安装文档:
https://yunikorn.apache.org/docs/next/deployment/scheduler - YuniKorn 官方 Helm Chart 仓库:
https://github.com/apache/yunikorn-release - k3s 官方文档:
https://docs.k3s.io/ - Docker Compose 官方文档:
https://docs.docker.com/compose/ - GitHub Release v1.10.0:
https://github.com/apache/yunikorn-release/releases/tag/v1.10.0