Skip to content

01 · Harvester v1.8.2 ISO 无人值守装机实施手册

适用范围:在 KVM/libvirt 宿主机上用 netboot 方式自动化安装 3 节点 Harvester OS 一体机集群。 本文所有命令、字段、耗时均在真实环境实测通过;失败案例与根因见 02-故障排查与修复记录.md,凭据专题见 03-凭据与首登认证.md,可直接运行的资料在 deploy/


1. 方案与架构

1.1 为什么用 netboot 而不是挂载 ISO

方式交互性可否全自动说明
挂载 ISO 引导需要人工走安装向导除非配 harvester.install.automatic 且仍要处理引导菜单
libvirt 直接内核引导(本方案)<kernel> + <initrd> + <cmdline> 直接注入,等效 iPXE 的 kernel/initrd 加载

关键收益:引导参数与装机配置全部由宿主机脚本控制,虚拟机开机即进入自动安装, 装完 poweroff,宿主机再把域定义切成硬盘启动并 autostart——全程零人工。

1.2 引导链路(实测)

宿主机 /mnt/xfs/harvester/
  boot/    vmlinuz + initrd + rootfs.squashfs + ISO     ← 00-download.sh 从 releases.rancher.com 拉取
    │ (符号链接)
  http/    python3 -m http.server  绑定 192.168.150.1:8080   ← 20-http-server.sh
    │        ├── harvester-v1.8.2-vmlinuz-amd64
    │        ├── harvester-v1.8.2-initrd-amd64
    │        ├── harvester-v1.8.2-rootfs-amd64.squashfs   (root=live:http://...)
    │        ├── harvester-v1.8.2-amd64.iso               (install.iso_url,装机时再取)
    │        └── configs/config-nodeNN.yaml               (install.config_url)

libvirt 域 harvester-NN(UEFI/OVMF)
    │ ① 直接内核引导 → dracut 取 rootfs → 进入 live 安装环境
    │ ② harvester-installer 读 config_url → 应用网络/分区/装机
    │ ③ elemental install → 格式化 data 盘 → 取 ISO → 预加载镜像 → 写 GRUB
    ▼ poweroff(install.poweroff=true)
宿主机 60-deploy.sh:切 disk 模式重定义 + virsh autostart + 开机

Harvester OS 启动 → RKE2 起 → node01 create 出集群;node02/03 用 server_url+token join

harvester-promote-node-controller 自动把 join 节点提升为 control-plane,etcd

kube-vip 承载 VIP 192.168.150.200 → Dashboard 可用

1.3 介质清单(实测字节数,可用于完整性核对)

文件字节数用途
harvester-v1.8.2-vmlinuz-amd6415,227,376引导内核
harvester-v1.8.2-initrd-amd64108,951,900initramfs(dracut)
harvester-v1.8.2-rootfs-amd64.squashfs1,176,158,208live 根文件系统(root=live:
harvester-v1.8.2-amd64.iso8,232,370,176装机镜像源(install.iso_url

下载基址:https://releases.rancher.com/harvester/v1.8.2,合计约 9.5 GB

ISO 完整性核对要点(02 案例 5):文件大小是 2048 的整数倍;PVD 魔数 CD001、卷标 COS_LIVEHEAD 请求返回的 x-goog-stored-content-length 不是真实对象大小,不能作为校验依据。


2. 目录结构

/mnt/xfs/harvester/
├── boot/        # 安装介质实体:vmlinuz / initrd / rootfs squashfs / ISO
├── disks/       # data 盘实体文件(400GiB qcow2,机械盘)
│                # + os 盘符号链接 → /home/<user>/harvester-disks/(NVMe,见 02 案例 7)
├── nvram/       # 每节点 UEFI 变量存储(*_VARS.fd + .bak),保留安装后生成的 EFI 启动项
├── http/        # HTTP 服务根目录:介质符号链接 + configs/ + images/
│   └── configs/ # config-node01.yaml(create) / config-node02,03.yaml(join)
├── configs/     # 虚拟机 XML(probe/install/disk 三态)、token.txt、credentials.txt(600)
├── logs/        # deploy.log / deploy-all.log / deploy.status / progress.log
│                # / harvester-NN-console.log(+.prev) / download/
├── import/      # 独立的镜像导入工作流(RHEL 9.6 审计/预处理,未纳入部署链路)
└── scripts/     # 19 个自动化脚本(见 §6)

http/ 下的介质都是符号链接指向 boot/,所以 00-download.sh 重下介质不需要重建 HTTP 目录。


3. 网络引导原理(cmdline 逐项)

libvirt 域 XML 的 <os> 段直接指定内核引导(实测原文,单行):

xml
<kernel>/mnt/xfs/harvester/boot/harvester-v1.8.2-vmlinuz-amd64</kernel>
<initrd>/mnt/xfs/harvester/boot/harvester-v1.8.2-initrd-amd64</initrd>
<cmdline>ip=dhcp rd.neednet=1 net.ifnames=1 rd.cos.disable rd.noverifyssl
  console=ttyS0,115200n8
  root=live:http://192.168.150.1:8080/harvester-v1.8.2-rootfs-amd64.squashfs
  harvester.install.automatic=true
  harvester.install.config_url=http://192.168.150.1:8080/configs/config-node01.yaml
  harvester.install.skipchecks=true
  harvester.install.tty=ttyS0,115200n8</cmdline>
<boot dev='hd'/>
参数作用不写会怎样
ip=dhcpdracut 早期网络用 DHCP 取地址initramfs 无网络,拉不到 rootfs
rd.neednet=1强制 initramfs 阶段建网同上(root=live:http:// 依赖它)
net.ifnames=1启用可预测网卡名引导期叫 eth0、安装后叫 enp1s0,配置里的接口名对不上
rd.cos.disable官方 PXE 安装要求的 dracut 参数COS 的 dracut 模块接管,引导流程与官方不一致
rd.noverifyssl不校验 SSLHTTPS 源会失败(本例是 HTTP,属照抄官方要求)
console=ttyS0,115200n8内核与 systemd 输出到串口无法录制安装全过程,失败不可复盘
root=live:http://…squashfslive 根文件系统来自 HTTP无根文件系统
harvester.install.automatic=true进入自动安装停在交互式安装向导
harvester.install.config_url=…指定装机配置自动安装无参数可用
harvester.install.skipchecks=true跳过硬件最小要求检查虚拟机(8C/32G/250G)不满足生产级门槛,安装被拒
harvester.install.tty=ttyS0,115200n8安装器自身 TTY安装器输出跑到 VNC,串口日志缺失

install.poweroff: true 写在 config.yaml 里而非 cmdline:安装完成后关机而非重启, 避免再次进入网络安装循环;随后由 60-deploy.shdisk 模式重定义域并设 autostart


4. 虚拟机定义要点

完整域定义见 deploy/configs/vm/harvester-01-install.xml (netboot 装机态)与 harvester-01-disk.xml(硬盘启动态)。 两者只差 <os> 段:disk 态去掉 kernel/initrd/cmdline

配置项取值为什么必须这样
<memory>33554432 KiB(32 GiB)Harvester 生产门槛;配合 skipchecks 才能过
<vcpu> / topology8,sockets=1 dies=1 cores=8 threads=1固定拓扑,避免 guest 内 CPU 计数漂移
<cpu mode>host-passthrough + check='none' + migratable='off'migratable='on'过滤掉 vmx,guest 内 KubeVirt 就无法跑虚机(02 案例 6)
<machine>pc-q35-6.2与 libvirt 8.0 兼容的固定机型
<loader> + <nvram>OVMF_CODE_4M.fd(readonly/pflash)+ 每节点独立 nvram/harvester-NN_VARS.fdv1.8 强制 UEFI;NVRAM 必须独立,否则三节点共享 EFI 变量会互相覆盖启动项
<on_poweroff>destroy装机 poweroff 后域进入 shut off,编排器据此判断安装结束
<on_reboot>restart96-install-retry.shvirsh reboot 重跑装机;netboot 参数在域定义里不变,重启即重新自动安装
<disk> cachewriteback装机期大量写入(18GB 镜像预加载),默认 cache 太慢
PCI 地址固定网卡 bus=0x01、os 盘 bus=0x02、data 盘 bus=0x03★ 保证 guest 内命名确定为 enp1s0/vda/vdb,装机配置才能写死设备名
<serial> / <console>type='pty'type='file' 会被 libvirt 置为 root:root 600,普通用户读不到日志(02 案例 3)
<rng model='virtio'>backend /dev/urandom装机期大量加密运算(拉取/校验/证书),缺熵会显著拖慢
<graphics type='vnc'>port='-1' autoport='yes' listen='0.0.0.0'兜底人工介入通道:virsh vncdisplay harvester-NN

4.1 三态域定义(40-define-vm.sh <NN> <mode>

模式用途特征
probe探测引导:确认 guest 内真实网卡名/盘名rd.debug不带 root=(不落盘、不装机)
installnetboot 自动装机注入 kernel/initrd/cmdline
disk装完后从硬盘正常启动移除引导注入,只留 <boot dev='hd'/>

网卡名不要猜:先用 bash scripts/40-define-vm.sh 01 probe 跑一次探测引导, 从串口日志实测得到 enp1s0 再写进装机配置(02 案例 1)。

4.2 libvirt 兼容性注意(本机 libvirt 8.0)

  • 不支持 driver discard='unpin' → 已从 XML 移除。
  • UEFI 域 virsh undefine 必须加 --keep-nvram,否则报 cannot undefine domain with nvram
  • 未先 undefine 就重复 virsh define 会报 domain 'harvester-01' already exists with uuid ...

5. 装机配置(config-nodeNN.yaml)逐字段说明

50-gen-configs.sh 生成,样本见 deploy/configs/config-node01.yaml(create)与 config-node02.yaml(join)。

yaml
scheme_version: 1
server_url: "https://192.168.150.200:443"     # 仅 join;★ 顶层键,不是 install.server_url
token: <三节点必须一致,存于 configs/token.txt>  # ★ RKE2 集群加入令牌,不是 Dashboard API token
os:
  hostname: harvester-NN
  password: "xxx"                   # ★ OS/SSH 密码,不是 dashboard 密码
                                               #   dashboard 密码是**另一个值**(50 号脚本的
                                               #   DASHBOARD_PW),由 75 号脚本设定,见 03
  ssh_authorized_keys: ["<宿主机公钥>"]          # 注入后可免密 SSH(rancher 用户)
  modules: [kvm, nvme]                         # kvm: 嵌套虚拟化必需
  dns_nameservers: [192.168.150.1]             # ★ 只写宿主 dnsmasq,勿并列公网 DNS(02 案例 24)
  ntp_servers: [ntp.aliyun.com, 0.suse.pool.ntp.org, 1.suse.pool.ntp.org]
install:
  mode: create | join
  automatic: true
  skipchecks: true                             # 虚拟机不满足生产硬件门槛
  silent: true
  force_efi: true                              # v1.8 强制 UEFI
  device: /dev/vda                             # 系统盘:ESP/COS_STATE/COS_RECOVERY/COS_PERSISTENT
  data_disk: /dev/vdb                          # Longhorn 数据盘
  iso_url: http://192.168.150.1:8080/harvester-v1.8.2-amd64.iso
  tty: ttyS0,115200n8
  poweroff: true                               # 装完关机,避免再次进入网络安装循环
  management_interface:
    interfaces:
      - name: enp1s0
        hwAddr: "52:54:00:15:01:NN"            # ★ 必须与域 XML 的 MAC 完全一致
    method: dhcp
    default_route: true                        # 位于 management_interface 下
    bond_options: {mode: active-backup, miimon: 100, mtu: 1500}
  vip: 192.168.150.200                         # ★ 仅 create 节点
  vip_mode: static                             # ★ 仅 create 节点
system_settings:
  auto-disk-provision-paths: ""                # 关闭自动纳管,避免误把 /dev/vda 交给 Longhorn

5.1 create 与 join 的差异(只有 3 处)

字段node01(create)node02/03(join)
install.modecreatejoin
server_url无(自己就是 server)https://192.168.150.200:443(指向 VIP)
install.vip / vip_mode192.168.150.200 / static不写
os.hostname / hwAddr各自的值各自的值
token三节点完全一致三节点完全一致

5.2 字段位置的三个易错点(对照官方 v1.8《Harvester Configuration》《PXE Boot Installation》核对)

  1. server_url 是顶层键,写成 install.server_url 会被静默忽略 → join 节点找不到集群。
  2. default_routebond_options 位于 install.management_interface,不是 install 直下。
  3. hwAddr 大小写与冒号格式必须与 MAC 一致,Harvester 靠它挑管理网卡; 写错会导致 bond mgmt-bo / bridge mgmt-br 建在错误接口上。

5.3 ★ 装机配置不能设定 Dashboard 密码(实测证明)

rootfs.squashfs 内的 /usr/bin/harvester-installer 做字符串统计:

字符串出现次数结论
scheme_version1该二进制确实解析装机配置(对照组,证明方法有效)
admin_password0无此配置能力
admin_token0无此配置能力
server_url0由其他组件处理,不在 installer 二进制内

所以全新集群的 Dashboard 初始状态只能是引导密码 xxx + mustChangePassword=xxx 必须由脚本在装完后补一次首登改密。完整根因链、验证数据与修复脚本见 [03-凭据与首登认证.md`](03-凭据与首登认证.md)。


6. 脚本清单与编排状态机

6.1 19 个脚本(deploy/scripts/ 内含全部可直接运行副本)

脚本作用
00-download.shreleases.rancher.com 下载 vmlinuz/initrd/rootfs/ISO(断点续传、并行)
10-prepare.sh创建 qcow2 磁盘、NVRAM、HTTP 目录符号链接、DHCP 静态保留(MAC→IP→主机名)
20-http-server.sh192.168.150.1:8080 启动 HTTP 引导服务并自检(已监听则直接退出)
30-console-capture.sh <NN> start|stop|statusvirsh console + pty 后台录制串口;FIFO 支持向控制台注入按键
40-define-vm.sh <NN> <probe|install|disk>生成并 virsh define 三态域定义
50-gen-configs.sh生成 3 份 config.yamltoken.txtcredentials.txt
60-deploy.sh <node01|node02|node03|verify>单节点编排:网络安装 → 等 poweroff(含卡死自愈探测)→ 切硬盘启动 → autostart → 等 SSH/API/Ready
61-autostart-after-iso.sh等 ISO 下载完成后自动 exec 60-deploy.sh node01(首次部署接力用)
65-deploy-all.sh总编排:等 node01 退出 → 确保切硬盘启动并开机 → 等 Ready → node02/node03 → 改密 → 整体验证
70-verify.sh集群验证(节点/Pod/Longhorn/网络/VIP/Dashboard/SSH)
75-set-admin-password.sh★ 自动完成 Dashboard 首登改密(幂等,见 03
80-smoke-vm.sh <create|status|delete>端到端验证:在 Harvester 上建测试 VM(KubeVirt + Longhorn + 嵌套虚拟化)
90-progress.sh后台每 30s 记录各节点 VM 状态/磁盘写入量/控制台末行到 logs/progress.log
95-rescue-image-preload.sh <NN> detect|run|log检测/修复安装期"镜像预加载卡死"(02 案例 7/8/15)
95-rescue-image-preload-guest.sh上一脚本推进 guest 内执行的救援体(不由宿主机直接调用)
96-install-retry.sh检测"安装器已报错卡死"并 virsh reboot 自动重试(每节点≤3 次,间隔≥120s)
97-installer-netfix.shSSH 一可用就把 nm-online 兜底包装注入 live 环境(窗口仅数秒)
98-nm-online-wrapper.sh被注入的包装体:短超时反复重试真 nm-online02 案例 13)
99-rancher-internal-net.sh check|apply|rollback接入内网 Rancher:A~F 六步(跨网桥放行 + libvirt hook 持久化 + 内网 DNS + 节点 DNS 收敛 + containerd 私仓 certs.d + containerd-registry 设置),详见 05

6.2 编排状态机

单节点编排 60-deploy.sh <nodeNN>install_node()):

清理上轮自愈标记(rescue-NN.done / retry-NN.count / .stamp / .lock)
  → 40-define-vm.sh NN install        # 定义 netboot 域
  → 30-console-capture.sh NN start    # 开始录串口
  → virsh start
  → setsid 97-installer-netfix.sh NN &   # ★ 后台抢注入 nm-online 包装(窗口仅数秒)
  → wait_poweroff NN 540              # 预算 540×10s = 90 分钟,基于"截止时间"而非固定轮数
  │    每 3 轮(≈30s)做两类自愈探测:
  │      a) 95-rescue-image-preload.sh detect → run   (镜像预加载卡死)
  │      b) 96-install-retry.sh                      (安装器报错卡死 → virsh reboot)
  │         命中重试则**等待预算顺延** 90 分钟,避免重试反而更容易超时
  → 30-console-capture.sh NN stop
  → 40-define-vm.sh NN disk           # 切硬盘启动定义
  → virsh autostart NN                # 宿主机重启后自动拉起
  → 30-console-capture.sh NN start
  → virsh start
  → wait_ssh NN                       # 30 分钟预算
  → (node01) wait_api:VIP /ping 返回 200|401|404
  → (node02/03) wait Ready:awk '$1==name && $2 ~ /^Ready(,|$)/'

总编排 65-deploy-all.sh

等 `60-deploy.sh node01` 进程退出(pgrep 轮询)
  → ensure_booted_from_disk 01        # 50 分钟预算,见下方四态处理
  → wait_ssh 01
  → 等 VIP /ping 响应(200|401|403|404)
  → wait_node_ready 01
  → for n in 02 03:
       60-deploy.sh nodeNN            # 非 0 退出**不中断**,交给恢复逻辑
       ensure_booted_from_disk NN
       wait_ssh NN
       wait_node_ready NN
       任一步失败 → 记 ERROR + 计入 FAILED + continue 下一个节点
  → 若 FAILED 非空:跳过整体验证,exit 1
  → 75-set-admin-password.sh          # ★ 首登改密(失败只 WARN,不中断)
  → 70-verify.sh
  → ALL DONE

ensure_booted_from_disk()四态处理(这是自愈的核心,旧版有两个致命缺陷见 02 案例 9):

域状态域定义动作
shut off<kernel>(netboot)安装已完成但没切盘 → 停录 → 40-define-vm diskautostart → 开录 → virsh start
shut off不含 <kernel>(disk)已是硬盘定义但没开机 → virsh start(旧版此处直接 return 0,节点永不开机)
running不含 <kernel>已从硬盘运行 → 返回成功
running<kernel>仍在安装 → 每 3 轮做 95/96 两类自愈探测
XML 读不到(空)先判空再继续等(旧版 ! grep -q '<kernel>' 在 virsh 偶发返回空时误判成"已从硬盘运行")

7. 完整实施流程(含每阶段验收点)

阶段 0 · 宿主机前置条件

bash
# 需要:KVM 可用、libvirt、qemu-img、python3、sshpass、curl、jq(75 号脚本用)
ls -l /dev/kvm                                  # 必须存在
sudo virsh net-list --all                       # libvirt 正常
grep -c vmx /proc/cpuinfo                       # >0,嵌套虚拟化前提
df -h /mnt/xfs /home                            # os 盘实体放 NVMe,data 盘放 /mnt/xfs
验收点判据
KVM 可用/dev/kvm 存在,当前用户在 kvm
磁盘布局正确os 盘实体在 NVMe(否则触发 02 案例 7 的预加载卡死);data 盘在大容量机械盘
VIP 未被占用arping -I virbr10 192.168.150.200 无应答
端口未被占用ss -lnt | grep 192.168.150.1:8080 为空

阶段 1 · 下载介质(约 9.5 GB)

bash
bash scripts/00-download.sh                     # 断点续传 + 并行;日志在 logs/download/
ls -l boot/                                     # 核对 4 个文件字节数(见 §1.3)

若想在下载完成前就排好后续动作,可用 61-autostart-after-iso.sh:它轮询 ISO 到位后 自动 exec 60-deploy.sh node01

阶段 2 · 准备磁盘 / NVRAM / DHCP 保留

bash
bash scripts/10-prepare.sh
sudo virsh net-dumpxml harvester | grep -A3 '<host mac'    # 验收:3 条 MAC→IP→hostname 保留
ls -l disks/ nvram/                                        # 验收:3×os(符号链接) 3×data 3×VARS.fd

DHCP 静态保留是关键:MAC 决定 IP,IP 决定主机名,这样装机配置里的 hwAddrserver_url、脚本里的 node_ip() 才能全部写死。

阶段 3 · 起 HTTP 引导服务 + 生成装机配置

bash
bash scripts/20-http-server.sh
curl -sI http://192.168.150.1:8080/harvester-v1.8.2-rootfs-amd64.squashfs | head -1   # 200
bash scripts/50-gen-configs.sh
cat configs/token.txt; ls -l configs/credentials.txt       # 验收:token 一致、凭据文件 600

阶段 4 · (可选但强烈建议)探测引导确认设备名

bash
bash scripts/40-define-vm.sh 01 probe
bash scripts/30-console-capture.sh 01 start && virsh start harvester-01
grep -oE 'enp[0-9a-z]+|vd[ab]' logs/harvester-01-console.log | sort -u    # 验收:enp1s0 / vda / vdb
virsh destroy harvester-01

阶段 5 · 一键无人值守部署

bash
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 &
pgrep -af '60-deplo[y]|65-deplo[y]'     # 验收:各自**只有一个**实例
tail -f logs/deploy-all.log

setsid 完全脱离当前会话:终端关闭或父进程被信号波及,都不会连带杀掉编排器。

验收点(按日志顺序)期望
harvester-01: running from disknode01 已从硬盘运行
VIP https://192.168.150.200 respondingkube-vip 起来了
harvester-01: Ready首节点入集群
harvester-02: powered off after install (~1006s)装机完成关机(≈17 分钟)
harvester-02 is Ready / harvester-03 is Readyjoin 成功
admin 密码已是目标值xxx密码修改成功首登改密完成
=== ALL DONE ===全流程结束

阶段 6 · 验证与收尾

bash
bash scripts/70-verify.sh                       # 集群体检
bash scripts/80-smoke-vm.sh create              # 端到端 VM(当前受 02 案例 23 阻塞)
sudo bash scripts/99-rancher-internal-net.sh apply   # 可选:打通到 Rancher 网段

8. 耗时基线(实测,可用于判断"是否卡住")

健康一轮(2026-09-06 08:03:50 → 08:45:08):

阶段实测耗时日志依据
node01(已装完)从硬盘运行 → ssh up~10sharvester-01: ssh up (~10s)
VIP 响应~10sVIP https://192.168.150.200 responding (~10s)
node01 Ready~10sharvester-01: Ready (~10s)
node02 netboot 装机 → poweroff~1006s(16.8 分钟)powered off after install (~1006s)
node02 硬盘启动 → ssh up~50sharvester-02 (…12): ssh is up (~50s)
node02 → Ready~50sharvester-02 is Ready (~50s)
node03 装机 → Ready 全程~22 分钟08:22:33 → 08:44:57
三节点总编排(node01 已就绪起算)42 分钟=== ALL DONE === 08:45:08
介质下载 9.5 GB~44 分钟20:03 → 20:47

判卡阈值:单节点装机 >25 分钟仍未 powered off 就该介入看串口日志; >30 分钟基本可断定踩中镜像预加载死线(02 案例 7),因为 chroot 内引导用 rke2 会在 启动约 30 分钟后自杀。

失败样本(供对照,都是修复前的真实记录):

时间事件耗时根因
09-05 20:49 → 21:29node01 装机 TIMEOUT40 分钟OS 盘在机械盘 → 预加载 ~34 分钟越线(案例 7)
09-05 23:00 → 09-06 00:31node02 装机 TIMEOUT90 分钟nm-online 亚秒竞态致安装器报错卡死(案例 13);期间还被误触发一次救援(案例 15)
09-06 08:03 → 08:45三节点全部成功42 分钟OS 盘迁 NVMe + 97/98 注入 + 96 自动重试后

9. 三层自愈机制(无人值守的关键)

脚本触发判据(全部满足)动作防误伤设计
L1 网络竞态97-installer-netfix.sh + 98-nm-online-wrapper.shSSH 一可用就开始(开机 +47~55s),从 virsh start 起每 0.5s 轮询把兜底 nm-online 包装注入 live 环境的 /usr/local/bin//usr/sbin/三次 SSH 往返压成一次(实测 1.4s 完成注入);没赶上由 L3 兜底
L2 预加载卡死95-rescue-image-preload.sh + -guest.sh/run/cos/target 已挂载 + images-lists 存在 + ctr-check-images.sh 已跑 >300s + containerd 不在 + 真正的引导用 rke2 不在①用与 harv-install 完全相同的参数重启 containerd ②逐列表比对,缺哪个就 zstd -d + ctr images import --no-unpack ③起名为 rke2诱饵进程让收尾的 pkill rke2 返回 0 ④核对结束就停 containerd模式串一律用 [x] 括号写法避免 pgrep -f 自匹配;mkdir 原子锁防两个看门狗同秒重复救援;guest 侧前置校验不满足就什么都不做直接退出
L3 安装器卡死96-install-retry.shlevel=error 出现在最后 5 行非空行内 ②harv-install/elemental/ctr-check-images/rsync/mkfs/qemu-img/parted 等干活进程全都不在 ③日志静默 ≥60svirsh reboot(域定义 <on_reboot>restart</on_reboot> + netboot 参数不变 → 自动安装重跑)每节点**≤3 次**、两次间隔**≥120s**;重启后重新调 L1 注入(live 环境是内存 overlay,重启即失效)

L1 为什么必须抢时间(实测时间线,来自 guest 内 /var/log/console.log):

15:02:04.938  manager: disable requested -> NetworkManager state is now ASLEEP
15:02:05      level=error msg="exit status 1\rConnecting...............   30s [offline]\n"
15:02:05.31   dhcp4 (mgmt-br): activation: beginning transaction
15:02:05.44   device (mgmt-br): Activation: successful, device activated
15:02:06.90   manager: NetworkManager state is now CONNECTED_GLOBAL

网络其实 0.5 秒后就完全就绪,安装器却已报错并永久停在错误界面 (harvester-installer / start-installer.sh 两个进程会一直挂着,磁盘一个字节都没写)。

⚠️ L3 的判据绝不能用"日志里存在 level=error":健康安装也有无害错误, 实测 node02 就有 unable to determine NIC speed from /sys/class/net/enp1s0/speed (got -1)。 该判据已双向验证:对健康安装中的节点返回 1(不触发);对真失败的归档日志能命中。


10. 验证方法

10.1 70-verify.sh 的 9 个检查段

#检查段判据
1虚拟机状态(libvirt)3 个域 running,且 Autostart: enable
2VIP 连通性 / Dashboardarp 有条目;/ping200/dashboard/200;能取到 <title>
3节点kubectl get nodes -o wide 三行且 STATUSReady*
4Harvester 版本 / 节点角色harvesterhci.io/node-role 标签、osImagekubeletVersion
5系统 Pod 异常统计Running/Completed/Succeeded 的行应为空
6Longhorn 存储nodes.longhorn.ioReadydisksget sc 含默认 harvester-longhorn
7Harvester 管理网络vlanconfigsnetworks.harvesterhci.io
8各节点登录验证三个 IP 均 OK <hostname> <kernel>(密钥认证)
9凭据打印 configs/credentials.txt

10.2 手工深度核对(本次实测通过的命令)

bash
K='sudo /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml'
H='ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null rancher@192.168.150.11'

# ① 三节点角色与 etcd quorum(HA 的硬指标)
$H "$K get nodes -o wide"
$H "$K -n kube-system get pods | grep '^etcd-'"          # 期望 3 个 etcd-harvester-0N Running

# ② kube-vip 是否三节点都有
$H "$K -n kube-system get pods -o wide | grep kube-vip"

# ③ Longhorn 默认盘是否可调度(虚机存储的地基)
$H "$K -n longhorn-system get nodes.longhorn.io -o json | \
    jq -r '.items[] | .metadata.name as \$n | .spec.disks | to_entries[] |
           \"\(\$n) \(.key) schedulable=\(.value.schedulable)\"'"

# ④ Dashboard 凭据是否真的可用(不能只看 HTTP 200,见 03 号文档)
curl -sk -o /dev/null -w '%{http_code}\n' https://192.168.150.200/ping        # 200 + pong
bash scripts/75-set-admin-password.sh                                          # 幂等,短路即 OK

实测健康基线(2026-09-06 09:19)

harvester-01 Ready control-plane,etcd
harvester-02 Ready control-plane,etcd
harvester-03 Ready control-plane,etcd
etcd 成员: 3      异常 Pod: 0
test-vm-disk0  Bound  20Gi  RWO  harvester-longhorn     ← smoke test 残留(02 案例 23)