Skip to content

Harvester v1.8.2 三节点 HCI 集群(ISO 无人值守装机)文档集

形态:Harvester OS 一体机——用 KVM/libvirt 起 3 台 UEFI 虚拟机,通过 netboot(vmlinuz + initrd + rootfs squashfs)+ HTTP 托管 config.yaml 完成 v1.8.2 无人值守安装(等效官方 PXE/iPXE 自动安装流程),节点自带 RKE2 + Longhorn + KubeVirt。

与同目录级的 ../harvester-container/(Helm 装进既有 RKE2) 是两种不同形态,排错结论不可互相套用,对照见 §5。

本目录所有结论、命令、耗时均来自真实环境实测,日期 2026-09-05 ~ 09-06。

1. 环境信息

Harvesterv1.8.2(v1.8 起 PXE 安装强制 UEFI,不再支持 Legacy BIOS)
承载平台KVM / libvirt 8.0,3 台 UEFI 虚拟机(OVMF OVMF_CODE_4M.fd + 每节点独立 NVRAM)
单节点规格8 vCPU(host-passthrough + migratable='off',透传 vmx 支持嵌套虚拟化)/ 32 GiB / pc-q35-6.2
系统盘250 GiB qcow2 → guest /dev/vda实体文件在 NVMedisks/ 下为符号链接,原因见 02 案例 7)
数据盘400 GiB qcow2 → guest /dev/vdb(机械盘 /mnt/xfs,Longhorn 默认盘)
网卡virtio,PCI 地址显式固定 → guest 接口名确定为 enp1s0
节点内核6.12.0-160000.36-default
KubernetesRKE2 v1.35.7+rke2r1(Harvester 内置)
libvirt 网络harvester / bridge virbr10,NAT + DHCP,192.168.150.0/24(宿主/网关 .1
DHCP 动态池192.168.150.100 - 199;三节点用 MAC→IP→主机名 静态保留
管理 VIP192.168.150.200vip_mode: static,池外空闲地址,kube-vip 承载)
HTTP 引导服务http://192.168.150.1:8080/python3 -m http.server
Dashboardhttps://192.168.150.200/(自签证书)
节点 DNS 192.168.150.1(宿主 dnsmasq);★ 不并列公网 DNS,否则 CoreDNS policy=random 会间歇把内网域名解析到公网(02 案例 24)
Rancher 接入已导入为集群 harvester-hci(id c-vd78lprovider=harvesterstate=activenodeCount=3),详见 05
节点MACIP(DHCP 保留)安装模式最终角色
harvester-0152:54:00:15:01:01192.168.150.11createcontrol-plane,etcd
harvester-0252:54:00:15:01:02192.168.150.12joincontrol-plane,etcd(自动提升)
harvester-0352:54:00:15:01:03192.168.150.13joincontrol-plane,etcd(自动提升)

PCI 地址被显式固定(网卡 0x01、os 盘 0x02、data 盘 0x03),因此 guest 内 vda/vdb/enp1s0 命名完全确定,安装配置里可以安全地写死设备名——这是本方案能全自动的前提。

2. 文档导航

文档内容
01-实施手册-ISO无人值守装机.md架构与引导原理、目录结构、19 个脚本职责与执行顺序、装机配置逐字段说明、完整实施流程、耗时基线、验证方法
02-故障排查与修复记录.md23 个实测案例:现象 → 定位过程 → 根因 → 修复 → 验证,含排障方法论
03-凭据与首登认证.mdDashboard 登录凭据、"密码正确却 401" 根因链、首登改密全流程、API 调用要点、凭据文件纠错
04-运维手册-巡检重置与网络打通.md日常巡检命令、集群重置/重建、节点自动提升机制、HA 与 quorum、故障速查表
05-接入Rancher与内外网分离解析.md被 Rancher 导入并纳入 Virtualization Management:三件事缺一不可、A~F 六步修复、导入 API 步骤、验证命令、UI 数据面代理路径
deploy/一键部署文档 + 全部资料run-all.sh 一键入口、19 个已实测脚本、3 份真实装机配置、libvirt 网络与域定义、验收清单、参数定制指南
deploy/public-access/公网访问方案https://ai-ear.cn:9443/ 的 frp 隧道 + Traefik TLS 终止实现、3 个可回滚脚本、10 层端到端验证清单

3. 30 秒速览(TL;DR)

最省事的一条路(推荐)——前置检查 + 按序调用已实测脚本:

bash
bash /mnt/xfs/harvester/scripts/run-all.sh --preflight      # 8 项前置检查(不改状态)
setsid bash /mnt/xfs/harvester/scripts/run-all.sh </dev/null >/tmp/run-all.log 2>&1 &
tail -f /tmp/run-all.log                                    # 全程约 42 分钟(不含介质下载)

等价的原始编排方式run-all.sh 内部就是按序调用这些):

bash
cd /mnt/xfs/harvester

# 一次性准备(介质 9.5GB + 磁盘 + DHCP 保留 + HTTP 服务 + 装机配置)
bash scripts/00-download.sh && bash scripts/10-prepare.sh
bash scripts/20-http-server.sh && bash scripts/50-gen-configs.sh

# ★ 无人值守:node01 装机 → 自动接力 node02/node03 → 改密 → 验证
setsid bash scripts/60-deploy.sh node01 </dev/null >/dev/null 2>&1 &
setsid bash scripts/65-deploy-all.sh    </dev/null >/dev/null 2>&1 &
tail -f logs/deploy-all.log          # 全程约 42 分钟(每节点 17~22 分钟)

每个编排器只能启动一次:重复实例会同时对同一台 VM 执行 virsh destroy/define/start 互相打断。怀疑被杀时先 pgrep -af '60-deplo[y]|65-deplo[y]' 确认再重启。

4. 能力矩阵(实测)

能力状态关键条件 / 说明
无人值守装机(netboot + HTTP config)3/3 节点全自动完成;含"安装器卡死自动重启重试"自愈
三节点 HA(etcd quorum)节点由 harvester-promote-node-controller 自动提升control-plane,etcd;实测 etcd 成员 3/3
管理 VIPvip_mode: static + kube-vip(3 节点各 1 个 Pod);curl -sk https://VIP/pingpong
Dashboard UI 登录\1xxx\2(★ 与 SSH 密码故意不同值),由 75-set-admin-password.sh 自动完成改密;实测 mustChangePassword=xxx 0302` 案例 28)
Longhorn 默认盘3 块 default-disk × 400 GiB,schedulable=true,无告警;默认 SC harvester-longhorn
SSH 免密 + kubectl装机配置注入宿主公钥;kubectl 必须用绝对路径02 案例 11)
串口全程录制30-console-capture.sh + pty + script,失败可复盘(旧日志轮转为 .prev
节点就绪判定✅(已修)grep Ready 会把 NotReady 当就绪;改为精确节点名 + ^Ready(,|$)02 案例 19)
接入 Rancher已导入为 harvester-hciprovider=harvesterstate=activenodeCount=3),纳入 Virtualization Management;靠 99 号脚本 A~F 六步 + cluster-registration-url 设置(详见 05
内网 DNS 解析稳定性✅(已修)节点 DNS 收敛为单一宿主 dnsmasq;此前 CoreDNS policy=random 导致约 50% 概率解析到公网(02 案例 24)
私仓镜像分发✅(已修)通过 containerd-registry 设置渲染各节点 registries.yaml(266B);手写该文件会被控制器回收02 案例 26)
端到端 VM(smoke test)⚠️ 未完成KubeVirt 准入拒绝:doc is missing path: /spec/template/spec/domain/cpu/maxSockets02 案例 23)
虚机镜像导入(import/⚠️ 进行中RHEL 9.6 镜像(c1/c2/c3,各 ~6GB)经内网 HTTP + CDI 导入;node03 死锁曾使 c2/c3 导入卡死 21h,硬重启后已恢复 Running(02 案例 29)
离线镜像分发(docker.io mirror)✅ 已验证containerd-registry 设置docker.io → 内网 Harbor mirror;控制器逐节点重写 registries.yaml滚动重启 rke2-server;实测 fleet-agent 拉取 138ms 成功(02 案例 30)

健康基线(2026-09-08 03:10 UTC 复测 · harvester-03 硬死锁恢复后):3 节点 Ready control-plane,etcd | etcd 成员 3 | kube-vip 3/3 | harvester/harvester-webhook/rancher 均 3/3 | Longhorn 3 盘 schedulable、原 faulted 卷已回 healthydegraded 卷副本自动重建中)| VIP /ping+/dashboard/ 200 | 异常 Pod 0fleet-agent 已于 03:53 用 docker.io → 私仓 mirror 修好,02 案例 30)。 上一版基线为 2026-09-06 09:19(异常 Pod 0);期间发生 node03 guest 硬死锁(2026-09-07 05:02 → 09-08 03:02,挂 22 小时,硬重启恢复),全过程见 02 案例 29 与 04 §4.4, 证据留档 /mnt/xfs/harvester/logs/postmortem-node03/

5. 两种 Harvester 形态对照(别把结论互相套用)

维度本目录:ISO 一体机../harvester-container/:Helm 装进既有 RKE2
节点 OSHarvester OS( Elemental 不可变系统 )既有 RKE2 节点的任意 OS
K8s 来源装机自带 RKE2 v1.35.7+rke2r1既有集群 RKE2 v1.34.4-rc11+rke2r1
访问入口VIP + kube-viphttps://192.168.150.200/Service NodePort 32735 + SNI
装机配置config.yamlscheme_version: 1,HTTP 托管)Helm values.yaml + promote 模式
首登密码配置无法指定admin/admin + mustChangePassword03由 Rancher/Harvester chart 逻辑决定
节点角色自动提升为 control-plane+etcd(HA quorum 3/3)取决于既有集群
典型坑nm-online 竞态、镜像预加载 >30min 卡死feature gate Snapshot(单数)、RWX 数据面

6. 访问与凭据

Dashboard 地址 : https://192.168.150.200/     (自签证书,浏览器需放行)
公网访问地址   : https://ai-ear.cn:9443/      (frp 隧道 + 公网 Traefik 正式证书,浏览器**无告警**)
                                             实现与排障见 deploy/public-access/README.md
用户名         : xxx
密码           : xxx             (dashboard 专用,由 scripts/75-set-admin-password.sh 设定)
                                              ★ 与下面的 SSH 密码**故意不同值**(见 02 案例 28)

SSH            : rancher@192.168.150.11 / .12 / .13
SSH 密钥       : /home/xxx/.ssh/id_rsa       (装机配置已注入,免密)
SSH 密码       : xxx               (即装机配置的 os.password,≠ dashboard 密码)

kubectl(节点内,必须绝对路径):
  sudo /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml get nodes -o wide

rke2 token : xxx   (configs/token.txt,**不是** Dashboard API token)
VNC            : virsh vncdisplay harvester-01
串口日志       : tail -f logs/harvester-01-console.log

实测认证状态(2026-09-06 10:15 复核)admin/xxx 登录返回 201/v3/users?me=true 返回 200mustChangePassword=xxx 引导密码 xxx与原 dashboard 密码xxx` 均已 401 失效

公网入口实测(2026-09-07 07:33 复核)deploy/public-access/30-verify-public.sh 14/14 全通过—— https://ai-ear.cn:9443/ping200 且证书链 Verify return code: 0 (ok)CN=ai-ear.cn,有效期至 2026-10-15,浏览器无告警); GET /302 Location: /dashboard/(相对路径,响应头不泄露内网 VIP/隧道端口); SPA 骨架 200 + index.*.js 1.5MB 资源 200(不白屏);POST login201 拿到 token; GET /v3/users?me=true200;WebSocket /v1/subscribe101 Switching Protocols(UI 实时刷新与 VM 控制台依赖)。

⚠️ 以上是实验环境凭据。凭据文件的三个标签曾被写错(把 RKE2 加入令牌标成 API token、 把 SSH 密码标成 dashboard 密码),纠错过程与正确语义见 03-凭据与首登认证.md

7. 遗留事项(Follow-up)

优先级事项参考
节点内核无自愈,且已实测复发kernel.softlockup_panic=0 + hung_task_panic=0 + hung_task_timeout_secs=0 → soft lockup 只告警不 panic,节点可无限期挂着(node03 实挂 22h)。恢复后 45 分钟内 node03 又打出同一套签名(03:45–03:55 EXT4 … Detected aborted journal + limit=0,comm virt-cdi-import)。建议开 softlockup_panic=1(已有 kernel.panic=10 → 10s 自动重启);代价是重载期"误杀"重启,待决策02 案例 29(含"复发信号"小节)、04 §4.4 第 5 步
已解决cattle-fleet-local-system/fleet-agent 长期 ErrImagePull:已于 2026-09-08 03:52 UTC 用方案 A修复——给 Harvester containerd-registry 设置追加 docker.iohttp://192.168.122.156:30000 mirror,harvester-node-manager 逐节点重写 registries.yaml 并滚动重启 rke2-server;03:53:08 Successfully pulled … in 138ms,Pod 1/1 Running异常 Pod 归零02 案例 30
单副本卷 + 大写入导入是高危组合harvester-longhorn-r1 的唯一副本与导入 I/O 同节点,超时即 faulted → 设备被拆 → guest 连锁死锁。导入类负载建议改用 3 副本 SC02 案例 29
node03 I/O 过载(导入并发过高):8 vCPU 上同时跑 2 个 CDI 导入(各写 127GiB / 3 副本 scratch,经 tgtd/iSCSI 网络写三份)+ Longhorn 副本重建 + 控制面 → load 3542% wajbd2/sda-8/jbd2/vdb-8 长期 D 状态 → 副本心跳超时、引擎断连拆设备 → ImportFailed 重来(25h 内 16 次,正反馈)。处置:导入类负载串行化、别都压同一节点;只读监控 logs/postmortem-node03/import-watch.log(每 120s)02 案例 29"复发信号"
VM rhel96 处于 Pausedkubectl get vm -n defaultPaused,VMI READY=False);rhel96-c2/c3-disk-0 PVC 仍 Pending,需等对应 CDI 导入完成后才会绑定本次巡检
VM test-vm-01virtualmachine 对象已不存在(2026-09-08 03:13 UTC 前后优雅停止并删除 VMI,非本次恢复操作所为);数据盘 PVC test-vm-01-disk-0 仍 Bound 完好,对应卷 detached/unknown 属正常。需要时 bash scripts/100-create-test-vm.sh apply 重建(§6 凭据不变)本次巡检
CDI scratch 卷反复换代pvc-45e7d22e/pvc-65a31c5cpvc-64291252/pvc-e2d5b613 → c3 再换 pvc-2e80f9a4),当前 2 卷 degradedpvc-2e80f9a4-r-1ea6c780 在 node02 重建中);node03 Longhorn 盘本身健康(Ready/Schedulable,可用 768G/844G,df 用 10%)。属导入临时卷,导入完成后应随之清理,若仍残留再查。pvc-b4800aff(=test-vm-01-disk-0)、pvc-cacb6efb(=test-vm-disk0) 的 robustness=unknown 与 longhorn-manager 每 30s Failed to get purge status for engine …detached 卷、引擎未运行的正常噪声,不是孤儿卷(PVC 均 Bound)本次巡检
smoke VM 创建被 KubeVirt 准入拒绝(maxSockets 补丁路径缺失),且残留一个空的 Bound PVC test-vm-disk002 案例 23
deploy/run-all.sh 只完成了 preflight 与参数分支验证(含机械盘/NVMe 双向验证),未做"从零到集群"的端到端重跑——它只是按序调用已实测脚本,不含新逻辑deploy §2、§2.2
smoke VM 与介质下载均走公网 URL;生产环境应先内网镜像化02 案例 23、deploy §9
logs/deploy-all.log 末尾仍是旧版凭据块(08:44 那次运行由旧 50-gen-configs.sh 生成),下次部署会自动刷新;configs/credentials.txt 为准03 §6.2
/mnt/xfs/harvester 曾被整体回滚到旧快照,编辑前先核对 mtime/体积02 案例 18