在裸机安装redhat
正好我有一块盘上面有GRUB, 于是 新建一个分区, 下载minimum ISO (注意 此处由于GRUB限制, 完整版尺寸过大 无法在GRUB中挂载)
然后按照这个教程完成配置 https://blog.vrqq.org/archives/20/
RHEL的安装程序也是分两段, 先加载一个临时环境, 再从临时环境加载完整安装程序, 其中通过inst.stage2=
指定第二段完整安装程序的位置.
Podman梯子
https://www.redhat.com/en/blog/container-systemd-persist-reboot
没有发现啥好用的, 暂用V2RayA.
在安装时指定了HTTP Proxy 之后想换找不到
起初在网上搜索的是 yum http proxy, 然后在/etc/yum.repos.d/redhat.repo 这个里面找到了proxy=
字样, 尝试删除后重新dnf update
发现依然报代理错误, 好像没改一样.
最后发现在这里改: /etc/rhsm/rhsm.conf proxy_hostname =
安装cockpit
我在局域网中使用的一个证书是基于ED25519的, 然后我基于此签发了一对 certification给cockpit用, 发现用不了.
一通搜索 发现似乎其内部的库不支持EdDSA, 于是新生成了一对RSA4906的根证书给局域网内机器分发, 然后给cockpit-web-server生成了RSA2048的服务器证书, 并签发之.
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_primes:2 -out rhost.key
openssl req -new -key rhost.key -out rhost.csr -config rhost.ini
openssl x509 -req -days 720 -CA ca.crt -CAkey ca.key -CAcreateserial -in rhost.csr -out rhost.crt -extensions req_ext -extfile rhost.ini
openssl x509 -noout -text -in rhost.crt
其中rhost.ini内容如下
req]
default_bits = 4096
distinguished_name = req_distinguished_name
req_extensions = req_ext
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = stateOrProvince Name
stateOrProvinceName_default = ShangHai
#localityName = Locality Name (eg, city)
#localityName_default = ShangHai
organizationName = Organization Name (eg, company)
organizationName_default = vrqq
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = vrqq rhost
[req_ext]
subjectAltName = @alt_names
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
basicConstraints = CA:false
[alt_names]
DNS.1 = rhost
DNS.2 = rhost.local.vrqq.org
IP = 192.168.6.50
此处 DNS.1 是hostname, IP是内网约定的固定IP.
把生成的证书放进/etc/cockpit/ws-certs.d/1-rhost.cer 并配置好权限, 运行/usr/libexec/cockpit-certificate-ensure --check
检查成果.
安装个 windows server 2025 并把显卡通进去
先装个工具dnf install driverctl
, 然后lspci
找到显卡并按教程把它自带的驱动ban了, 用直通驱动.
[root@rhost ~]# lspci -v |grep NVIDIA
81:00.0 VGA compatible controller: NVIDIA Corporation GP107 [GeForce GTX 1050] (rev a1) (prog-if 00 [VGA controller])
81:00.1 Audio device: NVIDIA Corporation GP107GL High Definition Audio Controller (rev a1)
[root@rhost ~]# driverctl set-override 0000:81:00.0 vfio-pci
[root@rhost ~]# driverctl set-override 0000:81:00.1 vfio-pci
检查驱动挂载: lspci -s 81:00.0 -v
以及 lspci -s 81:00.0 -v
, 发现驱动已成功更换.
然后在cockpit控制台中直接选择该设备挂载即可. (cockpit自带了vnc可以直接操作桌面)
高级应用
参考: Linux解锁NVIDIA消费级显卡vGPU功能的入坑记录 https://bytehorizon.net/archives/crystalast/74/
Github: https://github.com/DualCoder/vgpu_unlock
生成mstsc证书
参照上述生成cockpit证书内容, 按照ms文档, 修改ini文件如下字段
keyUsage = critical, digitalSignature, keyEncipherment, dataEncipherment
然后如法炮制生成一对证书后 打包成pfx格式openssl pkcs12 -export -out prism.pfx -inkey prism.key -in prism.crt -certfile ca.crt
然后在宿主机挂载mount -t cifs //192.168.122.223/Users ./prism_shared -ouser=Administrator
把文件粘进去. (windows server自动共享了这个目录, 参见Server Manager-> File and Storage Service)
注意 windows server 2025 没有WMIC了
mmc -> Add Snap-in -> Certificates -> Add 然后选 "Computer Account", 然后把刚才打包的pfx格式, 导入到Persional中. 双击刚才导入的证书, Details -> Thumbprint 把这串值复制下来.
接下来新建mstsc_cert.reg直接修改注册表, 内容如下.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]
"SSLCertificateSHA1Hash"=hex:62,9f,bb,68,32,1e,3c,70,5e,47,10,51,3f,f7,c4,e5,11,3f,40,ed
运行导入, 不用重启, 直接连接发现证书已更新.
Reference: https://vircloud.net/exp/rdp-ssl.html
小插曲 宿主机EFI分区挂了
好在Boot分区没挂, 于是找个GRUB2环境, 按c进入grub command prompt
set root=(hd0,gpt2) # Replace with actual RHEL boot partition
linuxefi /vmlinuz-<version> root=/dev/sdX ro quiet # 'root=' could be ignored if unknown
initrdefi /initramfs-<version>.img
boot
我当时不知道root=
怎么填 就先空着了, 然后进入了initramfs环境.
使用mount
查看当前挂载了哪些分区, 接下来先将我们真正的系统分区挂载道'/root' 然后再依次准备/dev等
## show mounted
mount
## mount OS partition to /root
mount /dev/mapper/luks-xxxx /root
## mount all others from shown above
mount --bind /dev /root/dev
mount --bind /... /root/...
## chroot
chroot /root
## mount /boot/EFI and /boot from disk
mount /dev/nvme2n1p2 /boot
mount /dev/nvme2n1p1 /boot/EFI
接下来准备联网
ifconfig eno2 192.168.6.50 netmask 255.255.255.0 up
ping bing.com
接下来按照下方教程重新生成EFI分区
Ref: https://access.redhat.com/solutions/3486741
yum reinstall grub2-efi-x64 shim-x64
yum reinstall grub2-common
efibootmgr -c -d /dev/<disk> -p 1 -l \\EFI\\redhat\\shimx64.efi -L "Red Hat Enterprise Linux <insert 7 or 8 or 9 here depending on system version>"
如果格式化了分区 一定记得修改/etc/fstab里面的分区UUID, 避免开机失败
ls -la /dev/disk/by-uuid
vim /etc/fstab
## Then replace UUID to right one
如果提示Crash recovery kernel arming.
他会自动进 rescue mode 然后上文没注意的地方可以看一下..
小插曲2: 内存报了ECC Corrected error
journctl -k
查询具体的问题
Feb 04 17:01:29 kernel: mce: [Hardware Error]: Machine check events logged
Feb 04 17:01:29 kernel: [Hardware Error]: Corrected error, no action required.
Feb 04 17:01:29 kernel: [Hardware Error]: CPU:3 (17:31:0) MC17_STATUS[Over|CE|MiscV|AddrV|-|-|SyndV|CECC|-|-|-]: 0xdc2040000000011b
Feb 04 17:01:29 kernel: [Hardware Error]: Error Addr: 0x0000000733418100
Feb 04 17:01:29 kernel: [Hardware Error]: IPID: 0x0000009600650f00, Syndrome: 0x636044440a800900
Feb 04 17:01:29 kernel: [Hardware Error]: Unified Memory Controller Ext. Error Code: 0
Feb 04 17:01:29 kernel: EDAC MC0: 1 CE on mc#0csrow#0channel#6 (csrow:0 channel:6 page:0xf83418 offset:0x100 grain:64 syndrome:0x4444)
Feb 04 17:01:29 kernel: [Hardware Error]: cache level: L3/GEN, tx: GEN, mem-tx: RD
显示日志如下, 这里的 Error Addr: 0x0000000733418100
是kernel访问的内存, 真实的内存地址通过page:0xf83418 offset:0x100
换算, 每个page是4kb, 那么当前page的真实地址范围为 0xf83418000 -> 0xf83419000
.
下载memtest86跑一下测试, 官网下载压缩包, 解压后将 EFI/BOOT 文件夹改名复制到EFI分区, 例如我的EFI分区如下:
然后配置grub文件, 新增 /etc/grub.d/10_memtest86 内容如下
5FCC-1122 是 EFI分区的 UUID, 可以用ls -la ls /dev/disk/by-uuid/
确定
cat << EOF
menuentry 'Memtest86' {
search --fs-uuid --no-floppy --set=root 5FCC-1122
chainloader /EFI/memtest86/BOOTX64.efi
}
EOF
然后给权限 chmod +x /etc/grub.d/10_memtest86
.
运行 grub2-mkconfig > /boot/grub2/grub.cfg
更新 (注意不同的系统这个文件位置不同, 我是 redhat 9)
起初用免费的memtest+发现测不出, 因为ECC的错误汇报给cpu, 他没有解析. 故建议关闭ECC 或用 memtest86开启ECC reporting. 测试范围填上述以page换算的真实内存地址, 例如我的是0xf83418000 -> 0xf83419000
.
将Linux虚拟机从 HyperV 迁移至 KVM
先来复习一下Linux的启动步骤:
(Motherboard)
-> (EFI partition) EFI {load driver.efi}
-> (boot partition) Grub
-> (boot partition) initramfs.img {
load luks-encrypt
load platform-drivers
iterator all drivers for full_kernel & OS requirement
load the real OS
}
-> (root partition)
直接在KVM中配置虚拟机后, 启动直接卡在dracut, 并且报找不到设备, 然后ls /dev
确实没有block设备.
尝试在kvm配置中更换磁盘为scsi, sata, virtio 均不行, 然后lsmod
发现没有virtio相关驱动载入.
问题出在 initramfs.img 上, Linux为了精简, 不会携带大部分驱动写入initramfs, 一般只会在安装或更新系统时 写入当前硬件平台 能挂载'/'的 所需要的驱动程序, 可以认为initramfs属于kernel的一部分. (注: initramfs和真正的系统 都不能从EFI阶段获取硬件驱动).
例如当前硬件平台从PCIE-NVME启动, 系统在制作initramfs.img时, 就会包含nvme.ko, 否则可能不会包含.
从 HyperV 迁移到 KVM时, 在initramfs阶段缺少了 virtio virtio_pci virtio_blk virtio_net virtio_scsi
这几个驱动, 导致找不到KVM下映射的硬盘.
于是参考 https://kyle.pericak.com/rhel-virtio-initrd.html 我们重新生成一个initramfs
先引导至rescue系统, 可以是ISO带的rescue, 也可以是 GRUB里面的rescue条目, 系统版本大差不差就可以.
如果KVM宿主机是Linux 也可以尝试使用宿主机系统.
# 如果已经成功mount和chroot, 省略此步
mount /dev/mapper/the-target-os-root /target
mount /dev/the-target-os-boot /target/boot
mount --bind /dev /target/dev
chroot /target
## -- 此时我们位于 VM-GUEST的root文件夹 --
# 检查之前的initramfs是哪个 并备份
ls /boot
cp /boot/initramfs-5.14.0-503.19.1.el9_5.x86_64.img /boot/initramfs-5.14.0-503.19.1.el9_5.x86_64.img.hyperV
# 确认系统含有当前版本的kernel-module
ls /lib/modules
# 重新生成initramfs.img
dracut -f \
/boot/initramfs-5.14.0-503.19.1.el9_5.x86_64.img \
5.14.0-503.19.1.el9_5.x86_64 \
--add-drivers "virtio virtio_pci virtio_blk virtio_net virtio_scsi"
重启后正常.
额外注意点
- 检查 /etc/fstab 是否有非UUID挂载的分区
- 如有桥接网卡, 保持mac地址一致, 可以在上游DHCP获得相同的IP地址.
一些idea: 我认为initramfs对于桌面版Linux, 应当出一个 尽可能保持大版本兼容 小版本迭代的版本 类似portable version, 或提供跨平台的 initramfs定制工具 / install ISO内提供定制工具, 这或许需要发行商作出努力. 这样便可以支持直接以默认方式把系统装进U盘, 然后再简单的定制就能用了.
在宿主机关机时暂停虚拟机
Ref: https://www.reddit.com/r/kvm/comments/1as5x04/rhel9_how_to_perform_vm_graceful_shutdown_with/
Ref: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/sect-shutting_down_rebooting_and_force_shutdown_of_a_guest_virtual_machine-manipulating_the_libvirt_guests_configuration_settings
参照上述文档, 新建 /etc/sysconfig/libvirt-guests 填入如下内容(具体可参考man libvirt-guests
)
ON_SHUTDOWN=suspend