本文以Ubuntu的私有镜像制作方法为例,介绍类Ubuntu(如Debian等)的私有镜像制作方法。本文适用于x86_64标准裸金属和弹性裸金属的私有镜像(弹性裸金属镜像需添加OFED驱动以支持DPU)。
1. 获取系统安装镜像
可通过Ubuntu官网获取Ubuntu的系统安装光盘镜像,下面我们假设您已经获取了Ubuntu 22.04.5的系统安装光盘镜像ubuntu-22.04.5-desktop-amd64.iso
2. 使用virt-manager安装操作系统
2.1 确保有使用virt-manager的权限
注意,使用virt-manager需要必要的权限。如果使用非root用户操作virt-manager,可以把用户加入libvirt组。参考Libvirt,重启后当前用户加入libvirt组生效。
# 把当前用户加入到libvirt组
sudo gpasswd -a $USER libvirt2.2 激活默认的虚拟网络
打开virt-manager,选中QEMU/KVM后,点上方菜单“编辑”-> “连接详情”。出现“连接详情”窗口后选择“虚拟网络”标签页,点下方的三角按钮,激活默认的虚拟网络。
2.3 创建新虚拟机
点击工具栏中的“创建新虚拟机”以创建新虚拟机。选择“本地安装介质(ISO映像或者光驱)”后,点“Forward”。
2.4 选择ISO光盘镜像和要安装的操作系统
选择ISO光盘镜像:点击“浏览”,选“本地浏览”后选择下载好的Ubuntu 22.04.5的ISO镜像。也可直接手动输入ISO镜像的路径。
选择要安装的操作系统:默认未检测出要安装的操作系统,取消“自动从安装介质/源检测”。在上方搜索框,输入Ubuntu后会弹出匹配,选择Ubuntu 22.04 LTS。
完成上面的配置后,点击“Forward”。
libvirt可能需要一些权限,这里点击“是”即可。
2.5 选择内存大小及CPU数
选择内存大小和CPU核数。分配给虚拟机的内存大小和CPU数不能超过宿主机拥有的内存大小和CPU数。这里根据实际情况分配足够大的内存及CPU数即可。本示例中只安装一个最小化的系统,不需要很多内存和CPU,这里选择默认配置,直接点击“Forward”。
2.6 创建磁盘镜像
根据实际情况,选择虚拟硬盘的大小。根据实际情况选择即可。需注意虚拟机硬盘不能太小,否则可能后续无法安装所需的软件包等。最终系统盘实际占用空间不能超过物理机的系统盘大小。本示例中只安装一个最小化的系统,不需要太多的硬盘空间,默认为8GiB,本文选择25GiB,点击“Forward”。
2.7 设置虚拟机名称、网络、启动方式
在“名称”文本框中输入虚拟机的名字,这个名字也会作为磁盘镜像的名字。磁盘镜像默认在/var/lib/libvirt/images/虚拟机名字.qcow2,后面转换镜像格式需要用到这个镜像,需要记下这个路径。这里名称我们使用“Ubuntu-22.04.5”。
“选择网络”处使用默认的虚拟网络即可。
x86_64架构的服务器一般支持BIOS和UEFI两种启动方式。其中UEFI是较新的启动方式,BIOS是为了兼容而保留的旧启动方式。您制作的镜像的启动方式应和物理机的启动方式保持一致。
vrit-manager默认创建的虚拟机是BIOS启动方式。如果您使用BIOS方式启动系统,点击“完成”创建虚拟机即可。
设置UEFI启动方式:
如果您打算使用UEFI方式启动系统,还需要进行一些额外的配置。勾选“在安装前自定义配置”,然后点击“完成”。
这时会有界面进行更细致的配置。在左侧选择“概况”,修改“固件”,从BIOS改为UEFI。点击右下角的“Apply”,保存配置。此时虚拟机支持的启动固件就从BIOS变为UEFI。
接下来修改启动顺序。在左侧选择“引导选项”,引导设备顺序从“VirtIO 磁盘1”改为“SATA CDROM 1”、“VirtIO 磁盘1”(勾选“SATA CDROM 1”,然后用右侧的上下箭头调整启动顺序)。点击右下角的“Apply”,保存配置。
此时虚拟机优先从光驱启动,若光驱中没有可启动的光盘镜像,则会从虚拟磁盘启动。我们的虚拟磁盘上还没有安装操作系统,此时无法从虚拟磁盘启动,需要从光驱启动。虚拟光驱中有我们前面选择的系统安装光盘镜像。
当系统安装完成后,virt-manager会自动弹出虚拟光驱中的系统安装光盘镜像,然后重启。此时虚拟光驱中无可启动的光盘镜像,会从虚拟磁盘启动。
点击左上角的“开始安装”,此时启动虚拟机,并开始安装系统。后续安装过程和BIOS方式启动安装系统几乎一样,只是分区时需要确保有EFI分区,在分区一节中我们会再强调。
2.8 启动虚拟机
启动虚拟机后会出现一个新窗口,可以看到已经从ISO光盘镜像开始启动。选择“Try or Install Ubuntu Server”开始在虚拟机中安装操作系统。
2.9 选择语言
等待一会儿后会启动安装程序。首先是选择语言,根据实际需要选择即可。这里选择英语,回车键确认。
升级系统选项,选择“Continue without updating”,回车键确认。
确认键盘样式和语言,默认“English”,回车键确认。
2.10 安装类型
可选择标准安装‘Ubuntu Server‘或最小化安装‘Ubuntu Server (minimized)’,可根据需求选择其他选项,建议选择‘最小化安装‘Ubuntu Server (minimized)’,选择‘Done’后回车键确认。
‘Search for third-party drivers’不需要选择,可在系统安装完成后安装第三方驱动和软件。
2.11 网络配置确认
默认使用dhcp获取ip,回车键确认。
无需设置代理,回车键确认。
镜像源地址设置,默认配置即可,回车键确认。
2.12 分区
分区时建议使用标准分区,即不使用LVM。后续我们会把虚拟机硬盘转换为squashfs格式的镜像,squashfs格式的镜像中只包含文件,不包含分区表、LVM等信息。分区是通过配置文件控制的,在创建物理机时会根据分区配置文件对物理机重新分区。这里使用简单的标准分区即可。
按照下图配置,使用普通分区,且自动分区,回车键确认。
点击“Install Now”,查看分区详情,确认无误后点击“Continue”。
确认进行分区,选择‘Continue’,回车键确认。
上面的截图时使用BIOS方式启动安装系统并自动分区得到的结果。如果选择UEFI方式启动,这里的自动分区结果稍有不同,如以下示例所示,会多一个/boot/efi分区。
/boot/efi分区是UEFI方式启动所必须的分区,一些UEFI启动相关的程序会放到这个分区中。该分区不必太大,一般几百MiB即可,但必须使用FAT32文件系统,即下图中显示的“EFI System Partition”。如果您选择UEFI方式启动系统,并且手动分区,则注意一定要加上这个分区。
BIOS分区示例:
#执行 fdisk -l
Disk /dev/vda: 25 GiB, 26843545600 bytes, 52428800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: B0FBB7D5-8E2F-41E5-B8A6-C36D30FAF5E6
Device Start End Sectors Size Type
/dev/vda1 2048 4095 2048 1M BIOS boot
/dev/vda2 4096 52426751 52422656 25G Linux filesystemUEFI分区示例:
#执行 fdisk -l
Disk /dev/vda: 25 GiB, 26843545600 bytes, 52428800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 9CFD9971-0076-4343-80E2-E29241DEBE68
Device Start End Sectors Size Type
/dev/vda1 2048 2203647 2201600 1G EFI System
/dev/vda2 2203648 52426751 50223104 23.9G Linux filesystem2.13 设置root用户密码
创建用户时只创建root用户即可,不建议新建其他用户,可能有安全隐患。物理机装机系统只在装机时为root用户设置密码,不考虑其他用户。这里输入的root密码只在虚拟机中可用。物理机装机时会设置root密码,进入物理机需要使用物理机装机时设置的root密码。
部分系统可跳过创建新用户,本文示例Ubuntu 22.04系统会自动创建root用户,且无法跳过创建新用户,在镜像制作完成后的清理阶段可删除该新用户。
无法创建root用户,系统会自动创建,无法手动设置root密码,系统安装完成后可设置root密码。
2.14 系统服务设置
选择‘Install OpenSSH server’,回车键确认。
可以根据需求安装所需的服务,本示例无需其他服务,回车键确认。
2.15 开始安装操作系统
完成上面的配置后,开始安装操作系统。
有些Linux发行版在这个系统安装界面上会有启用KDump的选项,此特性在内核崩溃时会转储内核,方便后续分析问题。Ubuntu未自动开启KDump,系统安装完成配置KDump。
等待一会儿后,安装完成。点击右下角的“Reboot System”按钮重启系统。
重启后会进入已经安装好的操作系统,可正常登录系统。
3. 安装软件、配置系统
这一步安装镜像中需要的软件,配置系统等。用户可根据自身需要进行定制,下面仅描述部分常见的软件安装与系统配置。
3.1 升级系统
升级系统,确保软件包更新到最新,减少安全风险。下面的命令升级除内核相关之外的包,其中包含bug修复相关的包。
apt-get -y update
DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
apt-get -y autoremove3.2 安装常用软件包
裸金属镜像需要支持lvm分区,常用系统包含lvm,缺少lvm的系统可通过以下方式安装。
DEBIAN_FRONTEND=noninteractive apt-get install -y iptables-persistent ifenslave dkms sysfsutils multipath-tools multipath-tools-boot lvm2 xfsprogs linux-crashdump unzip linux-tools-$(uname -r)3.3 配置ssh服务器
下面是对ssh服务器的一些配置。
sed -e "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/g" \
-e "s/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g" \
-e "s/^#\?PermitRootLogin.*/PermitRootLogin yes/g" \
-e "s/^#\?UseDNS.*/UseDNS no/g" \
-e "s/^#\?GSSAPIAuthentication.*/GSSAPIAuthentication no/g" \
-i.bak /etc/ssh/sshd_config说明:
PubkeyAuthentication yes:允许公钥认证访问。使用公钥认证访问通常更为安全。
PasswordAuthentication yes:允许使用密码认证访问。密码认证访问不如公钥认证访问安全。但默认镜像中没有公钥(在镜像中捆绑固定的公钥可能有安全隐患),需要使用密码认证访问。您可以在装机登录后配置好ssh公钥,然后禁用密码认证访问。
PermitRootLogin yes:允许root用户登录。允许root用户登录可能不够安全。但默认镜像中不创建其他普通用户。在镜像中创建普通用户并为其捆绑固定的密码可能有安全隐患。物理机装机时只会为root用户设置密码。您可以在装机登录后创建其他用户,然后禁用root用户登录。
UseDNS no:禁用反向DNS解析。未连通公网的机器上DNS不可用,会导致ssh连接缓慢或失败。
GSSAPIAuthentication no:禁用GSSAPI认证访问。GSSAPI认证需要自行配置才能使用。开启可能会导致ssh连接缓慢或失败。
注意
请不要在镜像中留ssh公钥或新建非root用户,可能有安全隐患。若相应的ssh私钥或用户密码泄露,继续使用该镜像会扩大受影响范围。
3.4 配置防火墙
弹性物理机有安全组,而标准物理机只能依赖系统中的防火墙。若不配置防火墙,会有安全隐患。下面给出一个样例iptables配置。
# 启用iptables、ip6tables防火墙。分别针对IPv4和IPv6网络。
systemctl enable iptables
systemctl enable ip6tables
# 配置iptables。
# 只允许ICMP协议、本地loopback接口和访问ssh服务。禁止其他所有访问。
# 禁止转发流量(通常只有路由器才需要转发流量)。
cat > /etc/iptables/rules.v4 <<EOF
#Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
EOF
# 配置ip6tables。和iptables类似,IPv6版本的防火墙。
# 多开放了DHCPv6客户端使用的udp 546端口,用来获取IPv6地址。
# (IPv4的地址是在装机时由天翼云物理机静态配置的)
cat > /etc/iptables/rules.v6 <<EOF
#Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmpv6 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 546 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
COMMIT
EOF3.5 配置DNS
下面的样例使用systemd-resolved来配置DNS。
#Ubuntu 22.04默认启用systemd-resolved
systemctl enable systemd-resolved.service
# 配置DNS服务器为114.114.114.114和2001:dc7:1000::1
sed -i.bak 's/^#\?DNS=.*/DNS=114.114.114.114 2001:dc7:1000::1/' /etc/systemd/resolved.conf
# 创建/etc/resolv.conf软链接,使其使用systmed-resolved生成的resolv.conf
ln -svf /run/systemd/resolve/resolv.conf /etc/resolv.conf3.6 设置硬件时钟使用UTC时间
设置硬件时钟使用UTC时间。
cat << EOF > /etc/adjtime
0.0 0 0.0
0
UTC
EOF3.7 配置KDump
sed -i 's/LOAD_KEXEC=.*/LOAD_KEXEC=true/' /etc/default/kexec
sed -i 's/USE_KDUMP=.*/USE_KDUMP=1/' /etc/default/kdump-tools
sed -i.bak 's/GRUB_CMDLINE_LINUX_DEFAULT=.*/#&/g' /etc/default/grub.d/kdump-tools.cfg
echo 'GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT crashkernel=256M-:512M"' >> /etc/default/grub.d/kdump-tools.cfg3.8 其他软件包
根据需要安装你需要的其他软件包,比如iproute、tcpdump、strace等。
4 安装驱动,确保启动时可加载必要驱动(重要)
4.1 安装驱动
由于是在虚拟机中制作镜像,虚拟机中虚拟出来的硬件环境和物理机上不同。需要根据实际物理机的硬件情况安装驱动。比如下面情况下,需要自行安装驱动。
Linux发行版未自带所需的驱动
Linux发行版自带的驱动版本不够高,不支持物理机硬件
安装驱动的方法有
使用官方软件源中的驱动。官方软件源中有更新的驱动,可用包管理器更新这些驱动。
从服务器厂商或硬件厂商的官方软件中获取驱动,然后安装。
需要注意的是,驱动一般是为当前运行的内核安装的。如果您需要升级内核,请在安装驱动前进行。
下面以安装megaraid_sas和MLNX_OFED为例,说明如何安装驱动。您所需的驱动和安装方式可能不同。
4.1.1 安装MegaRAID SAS驱动
注意,Ubuntu中的MegaRAID SAS驱动可能和硬件匹配,不需要自行安装。这里只是一个样例,展示如何安装驱动。
首先,可从从 https://www.broadcom.com/support/download-search 页面根据硬件信息搜索需要的驱动。
搜索后可选择驱动进行下载
这里我们选Latest Linux Driver。下载后的压缩包中有适用于多种发行版的驱动安装包。
选择ubuntu目录下的MegaRAID SAS驱动安装包,本文示例驱动包为megaraid_sas-07.733.00.00-1dkms.noarch.deb。
使用下面命令即可安装MegaRAID SAS驱动。
apt install <path to>/megaraid_sas-07.733.00.00-1dkms.noarch.deb4.1.2 安装OFED驱动(弹性裸金属必须)
OFED(OpenFabrics Enterprise Distribution)是一个用于高性能计算(HPC)和数据中心的网络驱动程序和软件包集合。它主要用于支持InfiniBand和以太网网络接口卡(NIC),特别是Mellanox的ConnectX系列适配器。下面介绍如何通过此方法安装OFED驱动。
首先,可从从 https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ 页面根据硬件信息搜索需要的驱动。
可下载iso或tgz包,下面介绍iso的安装方式:
#创建临时目录,并挂载iso
mkdir /tmp/mlnx
mount MLNX_OFED_LINUX-24.10-2.1.8.0-ubuntu22.04-x86_64.iso /tmp/mlnx
#安装ofed驱动
pushd /tmp/mlnx
./mlnxofedinstall --without-fw-update --all -q
popd
#卸载iso并删除临时安装目录
umount /tmp/mlnx && rmdir /tmp/mlnx注意:安装OFED驱动时,安装过程可能会提示缺少依赖包,按照提示按照所需依赖包即可。
4.2 更新initramfs
为了确保Linux操作系统在物理机上也能正常启动,需要把必要的驱动加入到initramfs中,以便Linux操作系统在启动时能找到必要的驱动。常见的情况如下
对使用本地盘的物理机,通常使用RAID,需要包含RAID驱动,以访问硬盘。
对使用DPU虚拟盘的物理机,需要有访问DPU虚拟盘相关的驱动。
4.2.1生成initramfs
使用下面的命令生成initramfs。
# generate initramfs
cat >> /etc/initramfs-tools/modules << EOF
ahci
aacraid
megaraid_sas
mpt3sas
smartpqi
qla2xxx
lpfc
dm_mod
dm_mirror
dm_log
dm_region_hash
EOF
# 禁用 resume. resume use uuid of swap partition
if [ -f /etc/initramfs-tools/conf.d/resume ]; then
mv -vf /etc/initramfs-tools/conf.d/resume /etc/initramfs-tools/conf.d/resume.bak
fi
cat > /etc/initramfs-tools/conf.d/resume <<EOF
RESUME=none
EOF
update-initramfs -u
# 回复resume
rm -vf /etc/initramfs-tools/conf.d/resume
if [ -f /etc/initramfs-tools/conf.d/resume.bak ]; then
mv -vf /etc/initramfs-tools/conf.d/resume.bak /etc/initramfs-tools/conf.d/resume
fi4.3 检查initramfs
可以使用lsinitrd或者lsinitramfs命令看initramfs中的内容。可以检查需要的内核模块等是否已经包含在其中。
lsinitramfs /boot/initrd.img-<kernel version> | less5配置串口终端、禁用selinux(重要)
5.1 配置串口终端、默认网卡名、GRUB
天翼云物理机默认使用串口终端访问系统,需要启用串口终端等。参考GRUB文档Simple configuration handling。
sed -e 's/GRUB_TERMINAL=.*/GRUB_TERMINAL="console serial"/g' \
-e 's/GRUB_SERIAL_COMMAND=.*/GRUB_SERIAL_COMMAND="serial --speed=115200"/g' \
-e 's/GRUB_CMDLINE_LINUX="\(.*\)/GRUB_CMDLINE_LINUX="\1 console=tty0 console=ttyS0,115200n8 biosdevname=0 net.ifnames=0"/g'\
-i.bak /etc/default/grubGRUB_TERMINAL:配置为"console serial",允许在串口终端上使用GRUB
GRUB_SERIAL_COMMAND:配置串口
GRUB_CMDLINE_LINUX:配置Linux内核参数。
console=tty0 console=ttyS0,115200n8:支持在虚拟终端和串口终端上
biosdevname=0 net.ifnames=0:使用传统网卡命名,比如使用eth0,而不是ens33等
/etc/default/grub不是最终grub使用的配置文件,还需生成、更新grub.cfg。
# 使用BIOS方式启动时使用下面命令
grub2-mkconfig -o /boot/grub2/grub.cfg
# 使用UEFI方式启动时,grub.cfg配置文件的位置不同,使用下面的命令
grub2-mkconfig -o /boot/efi/EFI/ctyunos/grub.cfg5.2 禁用SELinux
开启SELinux会导致天翼云物理机装机异常,需要关闭SELinux。
查看selinux是否disabled
apt install -y selinux-utils
# 查看selinux状态,返回Disabled则表示SElinux已关闭
getenforce可使用下面命令禁用SELinux。
sed -i.bak 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config重启后,可用‘sestatus -v’或‘getenforce’或查看‘/etc/selinux/config’文件检查SELinux是否已禁用。
6 清理系统
6.1 删除网络配置(重要)
物理机装机时会根据实际情况生成网络配置,保留镜像中的网络配置可能会造成干扰。需要删除不必要的网络配置。具体网络配置和系统使用的网络管理方式有关,下面列举一些常见的情况。
Redhat系发行版:删除/etc/sysconfig/network-scripts/目录下除了ifcfg-lo外的ifcfg-*文件
Debian:删除/etc/network/interfaces.d/下的网络配置文件
Ubuntu:删除/etc/netplan/目录下的网络配置文件
6.2 删除machine ID(重要)
machine ID标识了唯一的一台机器,在首次启动系统时一般会自动生成。需要删除镜像中的machine ID。
rm -vf /var/lib/dbus/machine-id
truncate -s 0 /etc/machine-id下面的清理项可有可无。但为了生成的镜像更小,请删除这些无用的文件。
6.3 清空软件包缓存
dnf clean all # 使用dnf的发行版
yum clean all # 使用yum的发行版
# 使用apt的发行版
apt-get -y autoclean
apt-get -y clean
rm -rf /var/lib/apt/lists/*
rm -rf /var/cache/apt/archives/*.deb6.4 清理临时文件
find /tmp -type f -exec rm -f {} \;6.5 清理日志
find /var/log -type f -exec rm -f {} \;7 镜像制作完成
完成上述配置后,关闭虚拟机,qcow2格式的镜像文件默认位于/var/lib/libvirt/images/目录下,镜像制作完成。