04.KVM实现自动化创建虚拟机.md
1、查看支持的os的两个cli
virt-install --osinfo list
osinfo-query os

这是win2016 2008这下👇


2、无GUI安装过程
2.1 宿主机网卡配置好
你的目标拓扑(最终形态)
外网
|
em1
|
br1 <---- 宿主外网 IP
/ \
vnet0 宿主
|
vm001(外网)
--------------------------------
内网
|
em2
|
br2 <---- 宿主内网 IP
/ \
vnet1 宿主
|
vm001(内网)
① 外网桥 br1(宿主拿外网 IP)
[root@phy001 system-connections]# cat /etc/NetworkManager/system-connections/br1.nmconnection
[connection]
id=br1
uuid=这里使用uuidgen生成,在vim里输入:r!uuidgen即可
type=bridge
interface-name=br1
autoconnect=true
[bridge]
stp=false
[ipv4]
method=auto
[ipv6]
method=ignore
② em1 作为 br1 从口(不拿 IP)
[root@phy001 system-connections]# cat /etc/NetworkManager/system-connections/em1.nmconnection
[connection]
id=em1
uuid=这里使用uuidgen生成,在vim里输入:r!uuidgen即可
type=ethernet
interface-name=ens33
autoconnect=true
master=br1
slave-type=bridge
[ethernet]
[ipv4]
method=disabled
[ipv6]
method=ignore
[proxy]
③ 内网桥 br2(宿主拿内网 IP)
[root@phy001 system-connections]# cat /etc/NetworkManager/system-connections/br2.nmconnection
[connection]
id=br2
uuid=这里使用uuidgen生成,在vim里输入:r!uuidgen即可
type=bridge
interface-name=br2
autoconnect=true
[bridge]
stp=false
[ipv4]
method=manual
addresses=10.100.1.1/24
[ipv6]
method=ignore
④ em2 加入 br2(不拿 IP)
[root@phy001 system-connections]# cat /etc/NetworkManager/system-connections/em2.nmconnection
[connection]
id=em2
uuid=这里使用uuidgen生成,在vim里输入:r!uuidgen即可
type=ethernet
interface-name=ens36
master=br2
slave-type=bridge
autoconnect=true
[ethernet]
[ipv4]
method=disabled
[ipv6]
method=ignore
[proxy]
⑤ 修改网卡文件的权限
chmod 600 /etc/NetworkManager/system-connections/*
🔁 激活顺序(非常重要)
⚠️ 建议 本地控制台操作,不要 SSH
nmcli connection reload
nmcli connection up br1
nmcli connection up em1
nmcli connection up br2
nmcli connection up em2
检查:
ip a
brctl show # 没有就:dnf install bridge-utils
你应该看到:
br1有外网 IPbr2有内网 IPem1/em2没有 IPvnetX自动挂在对应 bridge
2.2 ks文件和iso准备好
[root@localhost data]# pwd
/data
[root@localhost data]# tree
.
├── isos
│ └── Rocky-10.1-x86_64-minimal.iso
└── ks
└── ks-rocky10.cfg
2 directories, 2 files
[root@localhost data]#
[root@localhost data]# cat /data/ks/ks-rocky10.cfg
# ===============================
# 基础安装方式
# ===============================
text
reboot
cdrom
# ===============================
# 语言 / 键盘 / 时区
# ===============================
lang en_US.UTF-8
keyboard us
timezone Asia/Shanghai
# ===============================
# 网络(DHCP,安装后可改静态IP)
# ===============================
network --bootproto=dhcp --device=eth0 --onboot=on
# ===============================
# Root 密码
# ===============================
rootpw --plaintext ChangeMe123!
# ===============================
# SELinux / 防火墙
# ===============================
selinux --disabled
firewall --disabled
# ===============================
# 启动器
# ===============================
bootloader --location=mbr
# ===============================
# 磁盘分区(LVM) 注意vda跟总线的关系
# ===============================
zerombr
ignoredisk --only-use=vda
clearpart --all --initlabel
part biosboot --fstype=biosboot --size=1
part /boot --fstype=xfs --size=1024
part /boot --fstype=xfs --size=1024
part swap --size=2048
part pv.01 --grow
volgroup vg0 pv.01
logvol / --vgname=vg0 --percent=100 --name=root --fstype=xfs
# ===============================
# 软件包
# ===============================
%packages --ignoremissing
@^minimal-environment
@core
curl
bash-completion
net-tools
chrony
rsyslog
lsof
-audio
-plymouth
%end
# ===============================
# 安装后配置
# ===============================
%post --log=/root/ks-post.log
# 设置时钟
systemctl enable chronyd
systemctl start chronyd
# 启用串口控制台 (KVM console)
systemctl enable serial-getty@ttyS0.service
# SSH 基础加固
sed -i 's/^#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
sed -i 's/^GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
# 提高文件句柄
cat >> /etc/security/limits.conf <<EOF
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65535
* hard nproc 65535
EOF
# sysctl 常用优化
cat > /etc/sysctl.d/99-prod.conf <<EOF
net.ipv4.ip_forward = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.core.somaxconn = 65535
fs.file-max = 2097152
vm.swappiness = 10
EOF
sysctl --system
%end
带注释版👇
1️⃣检查ks文件

yum -y install pykickstart

2️⃣ 创建一个小 ISO 文件,只包含 KS 文件
root@localhost ~]#
[root@localhost ~]# tree /data/
/data/
├── isos
│ └── Rocky-10.1-x86_64-minimal.iso
└── ks
├── ks-rocky10.cfg
└── ks-rocky10.iso
2 directories, 3 files
KS 文件在宿主机 /data/ks/ks-rocky10.cfg:
mkdir -p /tmp/ks-iso
cp /data/ks/ks-rocky10.cfg /tmp/ks-iso/
# 创建 ISO,挂载点为根目录,“inst.ks=cdrom:/ks-rocky10.cfg”
genisoimage -output /data/ks/ks-rocky10.iso -volid ks -joliet -rock /tmp/ks-iso

参数解析
genisoimage- 生成 ISO 文件的命令,相当于把一个目录打包成光盘镜像。
- Rocky 10 / RHEL 10 的安装器可以识别 ISO 上的 KS 文件。
-output /data/ks/ks-rocky10.iso- 指定生成的 ISO 文件路径和文件名。
- 这里会在宿主机
/data/ks/下生成ks-rocky10.iso。
-volid ks- 设置 ISO 卷标(volume ID),类似光盘的名字。
- 可以随便取,但最好简短,不要有空格。
-joliet- 允许 ISO 文件中使用 Windows 风格长文件名(最多 64 个字符),兼容性更好。
- 对 Linux 安装来说可选,但加上没有坏处。
-rock- 开启 Rock Ridge 扩展,让 ISO 支持 Linux 的文件权限和长文件名。
- 保证 Linux 虚拟机可以正确读取文件权限。
/tmp/ks-iso- 指定要打包的源目录,这里是你存放
ks-rocky10.cfg的目录。 - ISO 会把这个目录下的文件作为光盘根目录打包进去。
- 指定要打包的源目录,这里是你存放
2.3 安装命令完全离线版:
virt-install \
--name vm001-192.168.126.130 \
--memory 2048 \
--vcpus 2 \
--cpu host \
--disk path=/var/lib/libvirt/images/vm001.qcow2,size=15,bus=virtio,cache=none \
--os-variant rocky10 \
--network bridge=br1,model=virtio \
--network bridge=br2,model=virtio \
--graphics none \
--console pty,target_type=serial \
--location /data/isos/Rocky-10.1-x86_64-minimal.iso \
--disk path=/data/ks/ks-rocky10.iso,device=cdrom \
--extra-args "inst.ks=cdrom:/ks-rocky10.cfg net.ifnames=0 biosdevname=0 inst.text console=ttyS0,115200n8"
virt-install \
--name vm001-192.168.126.130 \
--memory 2048 \
--vcpus 2 \
--cpu host \
--disk path=/var/lib/libvirt/images/vm001.qcow2,size=15,bus=virtio,cache=none \
--os-variant rocky10 \
--network bridge=br1,model=virtio \
--network bridge=br2,model=virtio \
--graphics none \
--console pty,target_type=serial \
--location /data/isos/Rocky-10.1-x86_64-minimal.iso \
--disk path=/data/ks/ks-rocky10.iso,device=cdrom \
--extra-args "inst.ks=cdrom:/ks-rocky10.cfg inst.text console=ttyS0,115200n8"
注意:vm的时间、网卡eth0
关键点:
- 第二个
--disk把 KS ISO 作为 CD-ROM 挂载到虚拟机。 inst.ks=cdrom:/ks-rocky10.cfg→ 路径是 ISO 根目录下的 KS 文件名。inst.text→ 文本模式安装。console=ttyS0,115200n8→ 串口输出。
以上的安装命令配合上面ks,实操成功,关键阶段截图如下,注不同的系统安装ks可能不同。






输入ctrl + ]退到宿主机层面 再次进入vish console <虚拟机的名称>就可以了
3、虚拟机初始化(网络桥接)
🖥️ 虚拟机 vm001 怎么桥接
- 网卡1 → bridge =
br1 - 网卡2 → bridge =
br2
好的,我帮你整理一下 KVM 下编辑 VM(以 vm001 为例)桥接网卡的完整步骤,适用于命令行和 virt-manager 两种方式。
方法一:命令行配置(virsh / XML)
- 查看虚拟机当前网络
virsh domiflist vm001
bridge link
输出示例:可以看到forwarding状态,其实宿主机哪里br已经关闭stp了,所以必然是forwarding了。

cp -a /etc/
这里可能要借助gui进到vm001里配置IP地址

[root@vm001 system-connections]# cp -a enp1s0.nmconnection enp7s0.nmconnection
[root@vm001 system-connections]# ll
total 8
-rw-------. 1 root root 229 Dec 12 03:30 enp1s0.nmconnection
-rw-------. 1 root root 229 Dec 12 03:30 enp7s0.nmconnection
[root@vm001 system-connections]# vi enp7s0.nmconnection
[root@vm001 system-connections]# cat enp7s0.nmconnection
[connection]
id=enp7s0
uuid=b8696dcd-ecd1-4463-a56a-38c35f31c43e
type=ethernet
autoconnect=true
interface-name=enp7s0
[ethernet]
[ipv4]
method=manual
addresses=123.1.1.2/24
dns=1.1.1.1
[ipv6]
addr-gen-mode=eui64
method=auto
[proxy]
[root@vm001 system-connections]#
[root@vm001 system-connections]# nmcli conn reload
[root@vm001 system-connections]# nmcli conn up enp7s0
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
[root@vm001 system-connections]# nmcli conn
NAME UUID TYPE DEVICE
enp1s0 8ff79451-b5b0-3351-8f96-e5390579b2cc ethernet enp1s0
enp7s0 b8696dcd-ecd1-4463-a56a-38c35f31c43e ethernet enp7s0
lo 9a306733-1a3d-446c-bc83-739178574d38 loopback lo
Wired connection 1 51a49b21-e774-3cb6-b0bd-fbe9196eb95c ethernet --
[root@vm001 system-connections]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:3b:74:51 brd ff:ff:ff:ff:ff:ff
altname enx5254003b7451
inet 192.168.126.130/24 brd 192.168.126.255 scope global dynamic noprefixroute enp1s0
valid_lft 1522sec preferred_lft 1522sec
inet6 fe80::5054:ff:fe3b:7451/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:5a:a1:87 brd ff:ff:ff:ff:ff:ff
altname enx5254005aa187
inet 123.1.1.2/24 brd 123.1.1.255 scope global noprefixroute enp7s0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe5a:a187/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@vm001 system-connections]# ping 123.1.1.2
PING 123.1.1.2 (123.1.1.2) 56(84) bytes of data.
64 bytes from 123.1.1.2: icmp_seq=1 ttl=64 time=0.407 ms
^C
[root@vm001 system-connections]# nmcli conn delete 'Wired connection 1'
Connection 'Wired connection 1' (51a49b21-e774-3cb6-b0bd-fbe9196eb95c) successfully deleted.
[root@vm001 system-connections]# nmcli conn
NAME UUID TYPE DEVICE
enp1s0 8ff79451-b5b0-3351-8f96-e5390579b2cc ethernet enp1s0
enp7s0 b8696dcd-ecd1-4463-a56a-38c35f31c43e ethernet enp7s0
lo 9a306733-1a3d-446c-bc83-739178574d38 loopback lo
[root@vm001 system-connections]#
# 查看双网卡双路由。
[root@vm001 system-connections]# ip route show
default via 192.168.126.2 dev enp1s0 proto dhcp src 192.168.126.130 metric 100
123.1.1.0/24 dev enp7s0 proto kernel scope link src 123.1.1.2 metric 101
192.168.126.0/24 dev enp1s0 proto kernel scope link src 192.168.126.130 metric 100
🧪 验证你顺序对不对(一个命令)
bridge link
你会看到:
ens33 master br1 state forwarding
ens36 master br2 state forwarding
如果顺序错了,状态会是:
disabledblocking- 或反复 flap
✅ 最佳实践(你可以记住这一条)
凡是 master / slave 结构(bridge、bond、team):
永远先 up master,再 up slave
🧠 再补一句(运维经验)
在生产上我们一般:
nmcli conn reload
nmcli conn up br1
nmcli conn up br2
# 确认没问题
nmcli conn up em1
nmcli conn up em2
中间留 几秒观察,避免“全网一把梭”。