跳转至

RUNBOOK — kvm_rocky9_deploy 部署工具运行与使用手册

写给:接手日常运维与值班的人(没接触过本工程也能照着做)。 事实来源:main.py、deployer.py、utils/kvm_utils.py、config_schema.py(行号见各处引用,以实现体为准)。 修订:2026-09-25 首版。

目录

  1. 服务概览
  2. 接入与凭据
  3. 日常速查表
  4. 日常操作
  5. 配置管理
  6. 备份与恢复
  7. 监控与告警
  8. 故障处置
  9. 安全与权限
  10. 容量与性能
  11. 附录
  12. CentOS 7 批次(main_centos7.py)

1. 服务概览

干什么用的:在 KVM 宿主 dell-R620 上按 YAML 配置文件批量创建 Rocky 9 虚机(含磁盘、无人值守安装、SSH 公钥注入、开机自启),并提供只读体检、漂移巡检与整体回滚。

由哪些组件构成:

组件 位置 职责
入口 CLI main.py 参数解析、模式分发、退出码
生命周期编排 deployer.py 门禁、漂移、供给、校验、回滚业务
配置校验 config_schema.py 配置合法性(BLOCK/WARN 两级)
命令与探测 utils/kvm_utils.py subprocess 执行 + 三态探测
共享库 /home/rain/py_public_modules/(经 .pth 挂载) 阶段编排基类、日志
配置 config/*.yaml 每批次一份主机清单

依赖谁:宿主上的 virt-install/virsh/qemu-img/openssl、libvirtd 服务、存储池(hdd-pool/ssd-pool/iso)、桥 br0、安装 ISO /data/kvm/iso/Rocky-9-latest-x86_64-dvd.iso。

异常时的业务影响:本工具只在「创建/回滚主机」时有影响;平时不常驻、不监听端口,坏了不影响已建好的虚机。异常影响的是下一次建机能否进行。

重要性等级:中(建机工具,非生产链路组件;但回滚误操作会不可恢复地销毁虚机与磁盘,故回滚动作按高危对待)。

执行模型:单机本机执行(virsh qemu:///system,不走 SSH 到宿主);进程锁 logs/kvm_rocky9_deploy.lock 保证同时只有一个实例。


2. 接入与凭据

接入:登录 KVM 宿主 dell-R620(工程目录 /home/rain/Documents/kvm/kvm_rocky9_deploy),所有命令在工程根目录执行,需要 root(门禁第一项就查 root 身份)。

账号清单:

账号 用途
宿主 root(sudo) 执行 main.py 全部模式、virsh
新建虚机的 root 运维登录虚机;口令与公钥见下

凭据存放与取用(凭据不写入本文档,只给取用命令):

凭据 位置 取用命令
各批次虚机 root 口令 config/credentials*.yaml(0600,已 gitignore) sudo cat config/credentials-<批次>.yaml
SSH 公钥(注入虚机的) config/ssh.pubkey_file 指向 /home/rain/.ssh/id_ed25519.pub cat /home/rain/.ssh/id_ed25519.pub

客户端接入示例(虚机就绪后,用宿主私钥登录):

ssh -i /home/rain/.ssh/id_ed25519 root@192.168.31.28   # <ip> 换成目标节点配置里的 ip
# 预期:直接登录成功(配置默认禁用口令认证,仅公钥可用)
# 若被拒:确认该批次配置 disable_password_auth 与 pubkey_file,见第 8 章场景 4

3. 日常速查表

以下均在工程根目录执行;<cfg> 换成 config/ 下的配置文件(清单见第 5 章)。

# 目的 命令 预期
1 只读体检(能不能建) sudo .venv/bin/python main.py --precheck --config <cfg> 退出码 0=可建;2=有阻断(逐项 [阻断] 已列出)
2 预演(将改什么,零改动) sudo .venv/bin/python main.py --dry-run --config <cfg> 每条变更一行 [dry-run] 将执行变更: …;计划落 build/plans/
3 真实创建 sudo .venv/bin/python main.py --config <cfg> 末行 状态: success(或 skipped);退出码 0
4 漂移巡检(现状 vs 期望) sudo .venv/bin/python main.py --drift --config <cfg> 0=无漂移;4=有漂移;5=探测不完整
5 查全部虚机 virsh --connect qemu:///system list --all 列出全部域与状态
6 查执行日志 tail -n 50 logs/kvm-rocky9-deploy.log 最近执行的阶段与结果
7 查最近体检/巡检报告 ls -t build/reports/ \| head; cat build/reports/<最新文件> 报告含结论与逐项明细
8 高危:销毁本配置全部虚机 sudo .venv/bin/python main.py --rollback --force --config <cfg> 不可恢复;预演用 --dry-run --rollback

回滚(第 8 行)是唯一不可逆操作:销毁所选配置里列出的虚机与磁盘,不影响其它批次。

CentOS 7 批次用完全相同的子命令,只需把入口换成 main_centos7.py、配置换成 config/hosts-20260928-centos7.yaml、日志看 logs/kvm-centos7-deploy.log;差异与专属故障场景见第 12 章。


4. 日常操作

4.1 标准建机流程(新建一批主机)

# ① 准备配置(复制模板改,见第 5 章)
cp config/deploy.yaml.example config/<新配置>.yaml && vi config/<新配置>.yaml

# ② 只读体检:环境 + 配置
sudo .venv/bin/python main.py --precheck --config config/<新配置>.yaml
# 预期输出尾行:门禁检查:共 N 项(通过 a、告警 b、阻断 c)
#   全通过 → "预检查通过:全部检查项达标",退出码 0
#   有阻断 → "门禁未通过:N 项阻断,终止执行",退出码 2,按逐项 [阻断] 修复

# ③ 预演:不改任何系统状态
sudo .venv/bin/python main.py --dry-run --config config/<新配置>.yaml
# 预期:"状态巡检:发现 N 项待变更" + 每项 [dry-run] 将执行变更: …
#       计划写入 build/plans/plan-<配置名>-<时间戳>.yaml

# ④ 真实执行
sudo .venv/bin/python main.py --config config/<新配置>.yaml
# 预期(单台约 10–15 分钟,安装等待上限 runtime.install_timeout_sec=2400s):
#   "状态巡检:发现 N 项待变更" → "开始处理 N 台节点" → "[完成] <name>"
#   → "节点校验结果:" 每台 状态=running SSH=… 自启=… → "全部节点校验通过"
#   末行:"状态: success | 耗时: …s"

# ⑤ 验证
sudo .venv/bin/python main.py --drift --config config/<新配置>.yaml   # 预期退出码 0:"未发现漂移"
ssh -i /home/rain/.ssh/id_ed25519 root@<节点ip> 'hostname'            # 预期:返回主机名

4.2 幂等复跑

同一命令重复执行是安全的:已达标的项逐条跳过(日志形如 卷已存在,跳过:…、域已存在,跳过创建:…、自启已开启,跳过:…),全部达标时整体 状态: skipped、退出码 0。复跑不会更换已生成的 root 口令(口令复用既有凭据文件,deployer.py:1040-1060)。

4.3 停止 / 启动单台虚机(不走本工具)

virsh --connect qemu:///system shutdown <name>   # 优雅关机
virsh --connect qemu:///system start <name>      # 启动
virsh --connect qemu:///system console <name>    # 进控制台(排障用,退出:Ctrl+])

4.4 回滚(销毁整批)

# 先预演,看将销毁什么(零改动)
sudo .venv/bin/python main.py --dry-run --rollback --config <cfg>
# 预期:逐台 "[dry-run] 将销毁域与磁盘:<name>",末行 "[dry-run] 未执行任何销毁动作"

# 高危:真实销毁。两种确认方式二选一——
sudo .venv/bin/python main.py --rollback --force --config <cfg>   # 非交互:显式 --force
sudo .venv/bin/python main.py --rollback --config <cfg>           # 交互:输入 YES
# 预期:"【高危】回滚:将销毁…" 横幅 → "已销毁域与磁盘" → "回滚完成"
# 未加 --force 且非交互 → "[已取消] 未执行回滚",退出码 1

销毁顺序与保护(deployer.py:853-921):逐台探测域 → 不存在则跳过;探测 UNKNOWN 则跳过不删(防误删)→ running 先 virsh destroy → virsh undefine --remove-all-storage --nvram。


5. 配置管理

5.1 配置文件清单

文件 管什么 状态
config/deploy.yaml.example 模板(全部可选项带注释),新批次从它复制 —
config/deploy.yaml 默认配置(--config 缺省值) 既有
config/hosts-20260918.yaml k8s + slurm 批次 既有
config/lustre-20260921.yaml lustre 批次 既有
config/hosts-20260924-lsf.yaml LSF 批次 既有
config/hosts-20260925-rocky9.yaml rocky9-01 既有
config/hosts-20260928-centos7.yaml centos7-01(CentOS 7 临时测试机,入口 main_centos7.py,见第 12 章) 既有
config/hosts-20261001-harbor.yaml harbor-01(学习测试用镜像仓库,4C/8G + 200G 数据盘挂 /data) 既有
config/flexlm-rocky.yaml flexlm license server(规划中) 当前 name/ip 与 rocky9-01 冲突,未修不可执行
config/credentials*.yaml 各批次 root 口令(工具自动生成,0600,gitignore) 只读引用

5.2 修改流程(任何配置改动)

vi config/<cfg>.yaml                                   # ① 改配置
sudo .venv/bin/python main.py --precheck --config config/<cfg>.yaml   # ② 配置+环境校验
sudo .venv/bin/python main.py --dry-run  --config config/<cfg>.yaml   # ③ 预演核对变更明细
sudo .venv/bin/python main.py            --config config/<cfg>.yaml   # ④ 执行
sudo .venv/bin/python main.py --drift    --config config/<cfg>.yaml   # ⑤ 验证退出码 0

改完必须回到 ②;只读改动(如加注释)至少跑一次 ② 确认零告警。

5.3 配置段与易错点

配置段:target(hostname/iso)、storage(system_pool/data_pool)、vm_defaults、network、ssh、host_tuning(可省,省则不碰宿主内核)、nodes、runtime。键名以 config_schema.py:78-95 的已知键表为准。

易错点(按踩坑频率排序):

  1. 跨批次冲突工具查不出来。配置校验只保证同一批次内 name/ip/mac 唯一(config_schema.py:435-457),不做网络占用探测(无 ping/arping)。复制旧配置忘改 name/ip → 同名域创建报错、IP 与既有虚机冲突。改完手工核一遍: bash grep -H -E 'name:|ip:|mac:' config/*.yaml | grep -v credentials # 跨批次人工比对 ping -c 2 -W 1 <拟用ip> # 预期:不通=空闲 virsh --connect qemu:///system list --all | grep <拟用name> # 预期:无输出
  2. 幽灵配置项:写了实现体不认的键 → [告警] …该配置项未被引用,配置后不产生任何效果。按告警删键或先实现。
  3. 既无公钥又禁口令 → 阻断「主机将无任何可用的登录方式」。二者至少留一个。
  4. 凭据文件按批次独立:runtime.credentials_file 指哪个文件,新机口令就写进哪个文件;换新批次建议同步换新文件名(如 config/credentials-flexlm.yaml),工具首次执行自动创建(0600)。
  5. 改 utils/kvm_utils.py(共享能力层)后:必须对全部配置各跑一次 --drift 回归。

6. 备份与恢复

本工具涉及三类"备份":

类型 何时产生 位置
宿主文件备份 配置了 host_tuning 且将改写 sysctl/KSM 单元时,阶段 3 自动 auto_backup 与原文件同目录,<原名>.bak.<时间戳>
批次变更备份 各批次变更时人工备份的配置/文档 config/hosts-*/backup/、*-2026mmdd/backup/,台账见各自 backup/README.md
凭据文件 工具生成口令时同时落盘 config/credentials*.yaml(0600)

手工备份配置(改配置前):

ts=$(date +%Y%m%d-%H%M%S); cp -a config/<cfg>.yaml config/<cfg>.yaml.bak.$ts   # 改前备份

恢复步骤:

# 宿主参数被改坏(配了 host_tuning 时)
sudo cp -a /etc/sysctl.d/<文件>.bak.<时间戳> /etc/sysctl.d/<文件> && sudo sysctl --system   # 还原并生效
# 配置改坏
cp -a config/<cfg>.yaml.bak.<时间戳> config/<cfg>.yaml
# 虚机被回滚销毁 —— 无法"恢复数据",只能重新创建:重跑该批次 --config 命令(磁盘与安装全新重建)

恢复后验证:sudo .venv/bin/python main.py --drift --config <cfg> 退出码 0。

清理:备份文件对照各 backup/README.md 台账,由用户确认后自行删除;Agent 不主动删。


7. 监控与告警

本工具无常驻监控;退出码就是告警信号,建议纳入定期巡检脚本。

入口 查法
执行日志 logs/kvm-rocky9-deploy.log(按天切割、保留 30 份、文件级 DEBUG)
日志行格式 [时间] [模块] [LEVEL] [HOST: …] [CMD: …] [RET: …] message
体检/巡检报告 build/reports/precheck-<配置>-<时间戳>.txt、drift-<配置>-<时间戳>.txt
变更计划 build/plans/plan-<配置>-<时间戳>.yaml

关键日志与阈值:

tail -n 50 logs/kvm-rocky9-deploy.log                          # 最近状态
grep -E '\[ERROR\]|阻断|失败|中止' logs/kvm-rocky9-deploy.log | tail -n 30   # 只看问题行

重点盯的信号:

信号 含义 动作
门禁未通过:N 项阻断 环境或配置不达标 按逐项 [阻断] 建议修复
状态探测不可用(N 项),已中止变更 libvirtd/存储池/网络通道故障 见第 8 章场景 2
存在未达标节点,请检查日志 后置校验失败(域/SSH/自启) 见第 8 章场景 3
检测到并发实例(PID=x) 进程锁冲突 确认无他人在跑;孤儿锁会自动清理
退出码 4/5 漂移/探测不完整 逐项看 drift 报告

日志排查常用级别:--log-level DEBUG 会把每条执行的命令与返回值打进日志([CMD: …] [RET: …])。


8. 故障处置

场景 1:--precheck 退出码 2(门禁阻断)

症状:命令尾行 门禁未通过:N 项阻断,终止执行,退出码 2。

诊断

sudo .venv/bin/python main.py --precheck --config <cfg>    # 预期:逐项 [阻断] 名称:实测 X,期望 Y;建议 …
cat build/reports/precheck-<cfg>-<最新时间戳>.txt          # 同样内容落盘,含结论

常见阻断与处置:

阻断项 处置
运行身份非 root 命令前加 sudo
/dev/kvm 缺失 查宿主虚拟化:ls -l /dev/kvm;BIOS 未开虚拟化则重启进 BIOS
缺 virt-install/virsh/qemu-img/openssl dnf install -y libvirt-client virt-install qemu-img openssl
ISO 不存在 ls -l <target.iso>;确认 ISO 已拷到宿主
存储池未运行 virsh pool-start <pool>(建议文案已给出)
kickstart 模板缺失 确认 templates/ks.cfg.tmpl 存在
配置 BLOCK 项 按字段路径改配置(如 nodes[0].ip 不是合法 IPv4)

验证:重跑 --precheck 退出码 0。

场景 2:执行中途 状态探测不可用(N 项),已中止变更

症状:阶段 2(幂等状态巡检)即中止,日志 状态探测不可用(N 项),已中止变更;请先修复探测通道(如 libvirtd、存储池、网络)后重跑。这是保护:UNKNOWN 不当作"需要变更",防止误建误删。

诊断

systemctl is-active libvirtd                                   # 预期:active
virsh --connect qemu:///system pool-list --all                 # 预期:目标池 State=running
virsh --connect qemu:///system list --all                      # 预期:正常列域
sudo .venv/bin/python main.py --drift --config <cfg> ; echo $?  # 预期:退出码 5=探测失败项,报告逐条 [探测失败]

处置:按诊断结果修通道——libvirtd 挂了 systemctl restart libvirtd;池停了 virsh pool-start <pool>;网络不通查 br0 与目标 IP。

验证:--drift 不再出现 [探测失败](退出码 0 或 4),再重跑执行。

场景 3:安装或 SSH 就绪超时

症状:日志 <name> 在 2400s 内未完成安装,请查看 /var/log/libvirt/qemu/<name>.log,或 <name> 在 2400s 内未就绪,请用 'virsh console <name>' 查看控制台;节点标 [失败],整体 状态: failed,退出码 1。

诊断

ls -l /var/log/libvirt/qemu/<name>.log && tail -n 30 /var/log/libvirt/qemu/<name>.log   # qemu 层报错
virsh --connect qemu:///system domstate <name>                 # 预期:running(安装中)或 shut off
virsh --connect qemu:///system console <name>                  # 进控制台看安装进度/报错,退出 Ctrl+]
ping -c 2 -W 1 <节点ip>                                        # 网络层是否已通

处置:

  1. 控制台显示安装报错(kickstart 失败、磁盘错误)→ 修配置或模板后,先清理残局再重跑: bash # 高危:销毁半成品域与磁盘(确认不再需要后执行) sudo .venv/bin/python main.py --rollback --force --config <cfg> sudo .venv/bin/python main.py --config <cfg> # 重新创建
  2. 提示 <name> 仍在以安装期定义运行(该定义会重新进入安装器) → 按提示 virsh destroy <name> 后重跑。
  3. 装完了但 SSH 不通 → 查虚机内网络:控制台里 ip a 确认拿到配置的静态 IP。

验证:末行 状态: success,--drift 退出码 0,ssh -i <私钥> root@<ip> 'hostname' 返回主机名。

场景 4:SSH 登录被拒

症状:ssh root@<ip> 报 Permission denied (publickey)。

诊断

ls -l /home/rain/.ssh/id_ed25519.pub                    # 公钥存在
grep -A3 '^ssh:' config/<cfg>.yaml                      # pubkey_file 指向、disable_password_auth
sudo cat config/credentials-<批次>.yaml                 # 口令兜底(0600,需 root)

处置:确认配置的 pubkey_file 与你本地私钥配对;不符则改配置后对该机重跑创建(公钥注入在供给阶段)。仅公钥登录是既定安全策略,不要改回口令登录。

验证:ssh -i /home/rain/.ssh/id_ed25519 root@<ip> 'hostname' 成功。

场景 5:回滚取消或失败

症状:[已取消] 未执行回滚(退出码 1)——非交互环境忘了 --force,加上即可;或 【高危】域名探测失败,跳过以免误操作——故意不删,防误销毁。

诊断/处置:virsh --connect qemu:///system list --all 人工确认域状态;探测通道恢复后重跑。任何"跳过"都意味着对应虚机仍存在,不要手工强删,回到诊断流程。

验证:重跑 --dry-run --rollback,清单符合预期后再真实执行。

场景 6:命令刚启动就 Traceback(PermissionError,漏加 sudo)

症状:任意模式(--precheck / --drift / --rollback …)一执行就抛 Traceback,栈尾停在 python3.12/logging/handlers.py 的 open(),报 PermissionError: [Errno 13] Permission denied。

根因:命令漏加 sudo。logs/ 目录与日志文件由历次 sudo 运行创建,属主为 root,普通用户打不开日志文件——程序在 log_manager.setup_all() 阶段(业务逻辑之前)即退出。

诊断

ls -ld logs; ls -l logs/kvm-centos7-deploy.log   # 预期属主 root:root

处置:命令前补 sudo 重跑。 关键判据:输出中没有任何 【高危】 / [dry-run] 行 → 尚未进入业务逻辑,属无害失败,不存在「半执行」中间态(回滚没跑、虚机仍在),补 sudo 即可,无需任何清理。

验证:重跑后应看到正常日志头(初始化模块: kvm_rocky9_deploy)或 【高危】 横幅。


9. 安全与权限

  • 执行权限:全部模式需 root(门禁第一项);工程不改 /etc/sudoers,不静默提权。
  • 虚机登录:默认仅公钥登录、禁用口令认证(ssh.disable_password_auth: true);公钥取自宿主 rain 用户。
  • 凭据:config/credentials*.yaml 含明文 root 口令(0600,gitignore 规则 config/credentials*.yaml),禁止提交或外传;文档、日志、对话中只写"从哪里取",不写口令本身。
  • 高危动作:--rollback 销毁虚机与磁盘不可恢复,需 --force 或交互输入 YES;--force 只做确认,不跳过任何校验(main.py:16-18)。
  • 不碰的边界:不重启宿主、不改 br0/物理网卡/netplan;宿主上有调度作业(Slurm/LSF)时不在该节点做变更动作;未配 host_tuning 时不触碰宿主内核参数与 KSM。
  • 日志脱敏:凭据/口令类信息落盘或贴出前打码;执行日志本身不含口令(口令只进 credentials 文件)。

10. 容量与性能

当前水位基线(2026-09-25):

项 基线
宿主内存 117 GiB total;20 台虚机在跑(气球 + 稀疏分配兜底)【已确认】
在跑域 openwrt 1、k8s 4、slurm 5、lustre 2、lsf 5、rocky9-01 1(另 k8s-master-02/03 shut off)
存储池 hdd-pool(系统盘)、ssd-pool(数据盘)、iso,均 active;系统盘稀疏 qcow2
单台典型规格 2–8 vCPU / 2–4 GiB / 20–50 GiB 系统盘

IP / MAC 段分配(第五字节 / 末段):

批次 MAC 第五字节 IP 段
k8s 0a .10–15
slurm 0b .16–20
lustre 0c .21–22
lsf 0d .23–27
rocky9 0e .28(0e:01 已用)
flexlm(规划) 0e 起顺延(0e:02 可用) .29 起顺延(.29 ping 空闲【已确认】;未核 DHCP 池)

扩容触发条件与操作:

  • 段内 IP 耗尽 → 在上表开新段,改配置 nodes 即可(工具无全局 IP 注册表,段规划靠本表人工维护)。
  • 宿主内存/磁盘吃紧 → 虚机规格只在创建时定义,扩容=回滚重建或另立批次;先 virsh dominfo <name> 与 df -h 看水位。

已知瓶颈:安装串行等待(install_max_concurrent 控制并发,默认 1,单台约 10–15 分钟);系统盘落 hdd-pool(HDD)IO 偏慢,IO 敏感批次考虑放 ssd-pool(配置 storage.system_pool 或数据盘 pool)。


11. 附录

A. 退出码表

码 含义
0 成功 / 无漂移 / 预检查无阻断(含仅告警;skipped 也算 0)
1 部署或回滚失败(含回滚确认被取消)
2 参数用法错误(argparse)或 --precheck 有阻断项(同码两义,看输出区分)
3 配置文件缺失
4 --drift 检测到漂移
5 --drift 存在探测失败项,结论不完整

B. 执行阶段(真实执行时的日志顺序)

进程锁 → 阶段0 初始化(配置解析完成…)→ 阶段1 门禁(门禁检查:共 N 项…)→ 阶段2 幂等状态巡检(状态巡检:发现 N 项待变更,计划落 build/plans/)→ 阶段3 前置备份(仅 host_tuning)→ 阶段4 核心变更([开始] 供给 <name> → 安装 → [完成] <name>)→ 阶段5 后置校验(节点校验结果:…)→ 收尾摘要(状态: … | 成功: … | 失败: …)。 短路规则:门禁失败不进阶段2-5;探测 UNKNOWN 在阶段2中止;变更失败不进阶段5。

C. 三态探测语义

ProbeState(DONE/PENDING/UNKNOWN)(utils/kvm_utils.py:29-41):DONE=已达标(幂等跳过);PENDING=确需变更(执行);UNKNOWN=探测不到(一律中止变更或阻断,绝不折平为"需要变更")。SSH 探测是纯 TCP connect(非 SSH 协议):连通=DONE,拒绝=PENDING,超时/不可达=UNKNOWN。

D. 相关文档

文档 管什么
docs/HANDOFF.md 交接快照:当前状态与下一步
rocky9-20260925/SOP.md rocky9-01 创建变更档案
lsf-20260924/SOP.md LSF 批次变更档案(CLI 最全,历史文档 CLI 漂移以其为准)
docs/SOP.md、docs/SOP-hosts-20260918.md k8s/slurm 旧 SOP(CLI 已过时,--rollback 现需 --force)
config/deploy.yaml.example 配置模板
各批次 backup/README.md 备份台账

E. 修订记录

日期 修改人 内容
2026-09-25 (本次) 首版:按 writing-ops-change-sop 技能 RUNBOOK 11 章产出,事实取自实现体行号
2026-09-28 (本次) 新增第 12 章 CentOS 7 批次;速查表与 5.1 配置清单各补一行

12. CentOS 7 批次(main_centos7.py)

用途:按需创建 CentOS 7 临时测试机。与 Rocky 9 批次共用同一套生命周期与子命令,只是入口、模板与 SSH 加固写法不同;完整变更档案见 centos7-20260928/SOP.md。

项 Rocky 9 批次 CentOS 7 批次
入口 main.py main_centos7.py
实现体 deployer.py(类 KvmRocky9Deployer) deployer_centos7.py(继承前者,只覆盖模板目录与 SSH 加固片段)
模板 templates/ks.cfg.tmpl templates/centos7/ks.cfg.tmpl
日志 logs/kvm-rocky9-deploy.log logs/kvm-centos7-deploy.log
配置 各批次既有配置 config/hosts-20260928-centos7.yaml
进程锁 logs/kvm_rocky9_deploy.lock 同左(两批次共用,不能并发执行)

命令:把第 3 章速查表里的 main.py 换成 main_centos7.py、<cfg> 换成 config/hosts-20260928-centos7.yaml 即可,参数、退出码、三态语义完全一致。

与 Rocky 9 的三处关键差异(换镜像或改配置前务必先读)

  1. vm_defaults.osinfo 必须填 centos7(libosinfo 条目名);误填 rocky9 会让 virt-install 按 RHEL9 假设建机。
  2. SSH 加固写在 /etc/ssh/sshd_config 末尾,不用 sshd_config.d/:CentOS 7 系的 sshd 默认不加载该目录,写片段会被整体忽略(口令登录静默保持可用)。片段会先 sed 删除同名旧项再追加——sshd 对同名项「首次匹配生效」,CentOS 7 默认文件里的 PasswordAuthentication yes 是未注释行,直接追加会被它压住。
  3. 老版本 OpenSSH 取值:CentOS 7.1 自带 6.6.1,PermitRootLogin 禁口令取值必须是 without-password;写 prohibit-password(7.0 起)会让 sshd 直接启动失败(code=exited, status=255 循环重启)。

故障处置(CentOS 7 批次专属)

  • 症状:安装完成但 SSH 永不可达(探测一直 unknown) 诊断:宿主侧看网卡收发,tx_packets 0 即 guest 网卡未启用(anaconda 未落实 network 行): bash sudo virsh --connect qemu:///system domiflist centos7-01 # 取 vnetN sudo virsh --connect qemu:///system domifstat centos7-01 vnet61 # 预期 rx 有值、tx 非 0 ip neigh | grep 192.168.31.30 # 预期 REACHABLE,而非 INCOMPLETE 处置:确认用的是最新 templates/centos7/ks.cfg.tmpl(其 %post 含按实际网卡名补写 ifcfg 的兜底);仍失败则按下方串口手法进 guest 查 /etc/sysconfig/network-scripts/ifcfg-*。

  • 症状:ping 通、SSH 端口 connection refused(探测长期 pending) 含义:guest 网络正常但 sshd 未监听。诊断(串口): bash PTY=$(sudo virsh ttyconsole centos7-01) timeout 30 sudo cat "$PTY" & # 读取回显到终端 printf 'root\n' | sudo tee "$PTY" # 登录(口令见 config/credentials-centos7.yaml) printf 'sshd -t; systemctl status sshd --no-pager | head -12\n' | sudo tee "$PTY" 预期:sshd -t 无输出、退出码 0;Active: active (running)。 失败判断:unsupported option … → 配置取值与该 OpenSSH 版本不符,修正 deployer_centos7.py 的 _password_auth_post_block 后先回滚再重跑。

  • 症状:SSH 能登但怀疑口令认证没关 诊断:ssh -i <key> root@192.168.31.30 "sshd -T | grep ^passwordauthentication",预期 passwordauthentication no(以 sshd -T 的实际生效值为准,不要只看配置文件末尾)。

串口登录手法(virsh console 需要 TTY,故用 pty 直读直写)同样适用于 Rocky 9 批次:把域名与凭据文件换掉即可。


来源:/home/rain/Documents/kvm/kvm_rocky9_deploy/runbook-20260925/RUNBOOK.md | 最后更新:2026-10-01 02:58(由 build/sync.py 同步,请勿在站点侧修改)