«

移动云私有镜像制作 ISO镜像转qcow2

myluzh 发布于 阅读:17 CLOUD


0x00 前言

软件商要求用 openEuler 22.03 LTS x86_64,最小化安装,只勾选 Standard,系统盘用 LVM+XFS。手上只有 ISO,就在 Mac 上用 QEMU 装了一台,再封装成移动云能导入的 QCOW2。

所谓 ISO 转 QCOW2,其实就是先创建虚拟硬盘,用 ISO 把系统装进去,配置好驱动再导出。直接 qemu-img convert install.iso 得到的还是安装光盘内容。

我这里的环境:

制作环境:ARM Mac+OrbStack / Docker+QEMU TCG
系统版本:openEuler 22.03 LTS 原始版 x86_64
安装环境:Minimal Install+Standard
启动方式:BIOS+MBR
系统盘:20GiB,/boot 1GiB,其余给 LVM 根分区,均为 XFS
语言时区:en_US.UTF-8,Asia/Shanghai

ARM Mac 模拟 x86 安装比较慢,尤其碰到编译。经常做的话,还是找台 x86 Linux 用 KVM 省事。

0x01 准备工具

QEMU 放在 Docker 里跑。新建目录,把 ISO 放进去,统一命名为 install.iso。

mkdir -p ~/Documents/ecloud-image
cd ~/Documents/ecloud-image
cp ~/Downloads/openEuler-22.03-LTS-x86_64-dvd.iso ./install.iso

Dockerfile:

FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN sed -i \
      's|http://ports.ubuntu.com/ubuntu-ports|http://mirrors.aliyun.com/ubuntu-ports|g' \
      /etc/apt/sources.list.d/ubuntu.sources \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
       qemu-system-x86 qemu-utils genisoimage python3 \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /work

构建并进入容器,后面的 QEMU 命令在容器里执行,/work 就是 Mac 上的这个目录。

docker build -t ecloud-image-builder:local .
docker run --rm -it \
  --mount "type=bind,source=$PWD,target=/work" \
  ecloud-image-builder:local bash

0x02 安装系统

创建硬盘

qemu-img create -f qcow2 /work/system.qcow2 20G

配置 Kickstart

我这里用 Kickstart 自动安装,ks.cfg 如下。ROOT_PASSWORD_HASH 换成自己生成的 SHA-512 crypt 哈希。

text
cdrom
lang en_US.UTF-8
keyboard us
timezone Asia/Shanghai --isUtc
network --bootproto=dhcp --device=link --activate --onboot=yes
rootpw --iscrypted ROOT_PASSWORD_HASH
firstboot --disable
selinux --enforcing
firewall --enabled --service=ssh
services --enabled=sshd,NetworkManager,chronyd,auditd

ignoredisk --only-use=sda
zerombr
clearpart --all --initlabel --disklabel=msdos --drives=sda
part /boot --fstype=xfs --size=1024 --ondisk=sda
part pv.01 --fstype=lvmpv --size=8192 --grow --ondisk=sda
volgroup openeuler --pesize=4096 pv.01
logvol / --fstype=xfs --name=root --vgname=openeuler --size=8192 --grow
bootloader --location=mbr --boot-drive=sda --append="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 rd.multipath=0"
poweroff

%packages --excludedocs
@core
@standard
cloud-init
qemu-guest-agent
openssh-server
NetworkManager
chrony
acpid
irqbalance
gdisk
parted
python3
lvm2
%end

@core 对应这份 ISO 的最小化安装。--grow 是安装时用满系统盘,不是云主机开机自动扩容。清盘配置只针对这台制作虚拟机的新空盘,不要挂数据盘。

生成配置光盘,提取安装器内核:

mkdir -p /work/payload
cp /work/ks.cfg /work/payload/ks.cfg
genisoimage -quiet -R -J -V ECLOUDKS \
  -o /work/kickstart.iso /work/payload

isoinfo -R -i /work/install.iso \
  -x /images/pxeboot/vmlinuz > /work/vmlinuz
isoinfo -R -i /work/install.iso \
  -x /images/pxeboot/initrd.img > /work/initrd.img

启动安装

把安装、启动共用的参数写成一个函数,4 核、6GiB 内存,磁盘和网卡都走 VirtIO:

run_vm() {
  qemu-system-x86_64 \
    -machine q35 -accel tcg,thread=multi \
    -cpu max -smp 4 -m 6144 \
    -display none -serial mon:stdio -no-reboot \
    -device virtio-scsi-pci,id=scsi0 \
    -drive file=/work/system.qcow2,format=qcow2,if=none,id=os,discard=unmap \
    -device scsi-hd,drive=os,bus=scsi0.0 \
    -netdev user,id=net0 -device virtio-net-pci,netdev=net0 \
    -device virtio-rng-pci \
    -device virtio-serial-pci \
    -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
    -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 \
    "$@"
}

run_vm \
  -drive file=/work/install.iso,media=cdrom,readonly=on \
  -drive file=/work/kickstart.iso,media=cdrom,readonly=on \
  -kernel /work/vmlinuz -initrd /work/initrd.img \
  -append 'inst.stage2=hd:LABEL=openEuler-22.03-LTS-x86_64 inst.ks=hd:LABEL=ECLOUDKS:/ks.cfg inst.text console=ttyS0,115200n8 net.ifnames=0 biosdevname=0'

inst.stage2 的卷标对应这份 ISO,其他版本用 isoinfo -d -i install.iso 核对。安装完成会关机,再从系统盘启动:

run_vm -boot c

0x03 移动云适配

这一节的命令在安装好的 openEuler 里执行,也可以放进 Kickstart 的 %post。

VirtIO

Linux 用内核自带的 VirtIO 驱动,确认驱动进了 initramfs 就行。

/etc/dracut.conf.d/90-ecloud-virtio.conf:

hostonly="no"
add_drivers+=" virtio virtio_ring virtio_pci virtio_blk virtio_scsi virtio_net virtio_console "
add_dracutmodules+=" lvm "

首次从装好的系统启动后执行:

dracut --force "/boot/initramfs-$(uname -r).img" "$(uname -r)"
lsinitrd "/boot/initramfs-$(uname -r).img" | grep virtio

如果驱动编译进内核了,/boot/config-$(uname -r) 中对应配置为 =y,不一定能在模块列表里看到。

网络和 cloud-init

启动参数用了 net.ifnames=0 biosdevname=0,网卡统一为 eth0,配置 DHCP,不绑定旧 MAC。

/etc/sysconfig/network-scripts/ifcfg-eth0:

TYPE=Ethernet
NAME=eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes

/etc/cloud/cloud.cfg.d/90-ecloud.cfg:

datasource_list: [ConfigDrive, Ec2]
disable_root: false
ssh_pwauth: true
preserve_hostname: false
manage_etc_hosts: false
network:
  config: disabled
growpart:
  mode: off
resize_rootfs: false
system_info:
  default_user:
    name: root
    gecos: root
    lock_passwd: false
    shell: /bin/bash

网卡交给 NetworkManager,cloud-init 保留,用来接收平台初始化信息。原来的临时网卡配置需要清理掉,loopback 保留。

软件商要求 root 登录,/etc/ssh/sshd_config 里相应配置:

PermitRootLogin yes
PasswordAuthentication yes
PermitEmptyPasswords no

QGA 和改密

保留 ISO 自带的 qemu-guest-agent 包,再从移动云官方文档下载对应系统、架构的 QGA。核对校验值后,替换二进制。

文件先放进目标系统的 /root/ecloud-files/:

install -m 0755 /root/ecloud-files/qemu-ga /usr/bin/qemu-ga
mkdir -p /usr/local/var/run /var/log/qemu-ga
restorecon /usr/bin/qemu-ga
systemctl enable qemu-guest-agent

mkdir -p /var/lib/cloud/scripts/per-boot
install -m 0755 /root/ecloud-files/cloudRun.sh \
  /var/lib/cloud/scripts/per-boot/cloudRun.sh

cloudRun.sh 用官方的离线改密脚本。QGA 需要虚拟机提供 org.qemu.guest_agent.0 端口,上面的 QEMU 命令已经加了。

growpart 也保留。我这里单独装了 openEuler 官方签名的 cloud-utils-growpart RPM,没有升级整个系统。cloud-init 的自动扩容已关闭,也不再保留自定义的 ecloud-grow-root.service 和扩容脚本,后面自己手动扩。

0x04 踩坑

multipath 接管系统盘

通用 initramfs 把普通磁盘映射成了 /dev/mapper/0QEMU_...。我这里是单路径云硬盘,直接关掉 multipath:

systemctl disable multipathd.service multipathd.socket
systemctl mask multipathd.service multipathd.socket
grubby --update-kernel=ALL --args='rd.multipath=0'

同时在 /etc/default/grub 的 GRUB_CMDLINE_LINUX 里保留 rd.multipath=0,再生成配置:

grub2-mkconfig -o /boot/grub2/grub.cfg

cloud-init 报 hosts 模板缺失

No hosts template could be found for distro redhat

这份原始版包缺少对应模板,我这里不需要它改 /etc/hosts,设置 manage_etc_hosts: false 后正常。

audit 刷屏

第一版已经在移动云启动了,控制台一直刷:

audit: audit_backlog=65 > audit_backlog_limit=64
audit: backlog limit exceeded

审计队列满了,audit_lost 也在增加。查了 ISO,auditd 默认就是启用的,原镜像本地启动也正常,不是后来额外装的服务。云端具体什么事件把队列打满,还没查到。

保留审计,先把队列调大:

systemctl enable --now auditd
auditctl -b 8192
auditctl -s

持久化:把 /etc/audit/rules.d/ 中已有的 -b 改成 -b 8192,没有就补一行,再加载:

augenrules --load
grubby --update-kernel=ALL --args='audit_backlog_limit=8192 loglevel=3'

audit_backlog_limit=8192 loglevel=3 也加入 /etc/default/grub 的 GRUB_CMDLINE_LINUX,保留其他参数,然后执行 grub2-mkconfig。

/etc/sysctl.d/90-ecloud-console.conf:

kernel.printk = 3 4 1 7
sysctl -p /etc/sysctl.d/90-ecloud-console.conf

这样控制台只输出 critical 及更严重的内核消息,普通错误也会被隐藏,排错时用 dmesg 或 journalctl -k 看。只抑制输出不会解决积压,还要看 lost 有没有继续增加。

0x05 清理和导出

在准备封装的虚拟机里清理机器标识、主机密钥和安装记录,删掉自己放进去的安装包、调试脚本,完成后直接关机。

cloud-init clean --logs --seed
rm -f /etc/ssh/ssh_host_* /var/lib/systemd/random-seed
rm -f /var/lib/dbus/machine-id
ln -s /etc/machine-id /var/lib/dbus/machine-id
: > /etc/machine-id
rm -f /root/anaconda-ks.cfg /root/original-ks.cfg /root/.bash_history

fstrim /
fstrim /boot
sync
systemctl poweroff

等 QEMU 退出,在工具容器里压缩导出:

qemu-img convert -p -f qcow2 -O qcow2 -c \
  /work/system.qcow2 /work/openEuler-ecloud-20G.qcow2

qemu-img check /work/openEuler-ecloud-20G.qcow2
qemu-img info --output=json /work/openEuler-ecloud-20G.qcow2

检查通过应该提示 No errors were found on the image.,容量是 20GiB,没有 backing-filename 依赖。Mac 上再生成校验文件:

shasum -a 256 openEuler-ecloud-20G.qcow2 > openEuler-ecloud-20G.sha256
shasum -a 256 -c openEuler-ecloud-20G.sha256

我这里用临时副本做启动测试,检查 BIOS 引导、DHCP、cloud-init、QGA 实际改密和审计写入。又把副本磁盘改成 40GiB 试了一次,根分区仍然约 19GiB,没有自动扩容;审计队列为 8192,lost 0。

最后文件约 946MiB,虚拟盘 20GiB。ISO 的 3.4GiB 包含离线安装包,和最终系统盘文件大小没有直接关系。

上传目标地域的 EOS 桶,在 IMS 导入系统盘镜像,选择 QCOW2、x86_64、BIOS,系统盘至少 20GiB,具体按资源池下限选。新版 20GiB 通过了本地验证,云端还要再试启动、联网和控制台改密。

参考

macos cloud-init 移动云 openEuler qcow2 QEMU


正文到此结束
版权声明:若无特殊注明,本文皆为 Myluzh Blog 原创,转载请保留文章出处。
文章内容:https://itho.cn/cloud/620.html
文章标题:《移动云私有镜像制作 ISO镜像转qcow2》