周振林 周振林
首页
  • 前端文章

    • HTML
    • CSS
    • Tailwind CSS (opens new window)
    • JavaScript
    • Vue3
    • 其他
  • 学习笔记

    • 《JavaScript教程》
    • 《ES6 教程》
    • 《TypeScript》
    • 《Vue》
    • 《Git》
    • 《小程序笔记》
    • 《JS设计模式总结笔记》
  • 规范
  • Spring
  • 安装教程
  • 其他教程
  • 归真医学
  • 常用药材
  • 学习笔记
  • 经方学习心得
  • 基础
  • 虚拟化
  • Docker
  • OpenStack
  • 心情杂货
关于
收藏
  • 分类
  • 标签
  • 归档

周振林

IT界的小学生
首页
  • 前端文章

    • HTML
    • CSS
    • Tailwind CSS (opens new window)
    • JavaScript
    • Vue3
    • 其他
  • 学习笔记

    • 《JavaScript教程》
    • 《ES6 教程》
    • 《TypeScript》
    • 《Vue》
    • 《Git》
    • 《小程序笔记》
    • 《JS设计模式总结笔记》
  • 规范
  • Spring
  • 安装教程
  • 其他教程
  • 归真医学
  • 常用药材
  • 学习笔记
  • 经方学习心得
  • 基础
  • 虚拟化
  • Docker
  • OpenStack
  • 心情杂货
关于
收藏
  • 分类
  • 标签
  • 归档
  • 基础

  • 虚拟化

  • Docker

  • OpenStack

    • OpenStack命令
    • OpenStack简介
    • OpenStack安装部署
    • Keystone服务详解
    • Placement服务详解
    • Glance服务详解
    • CentOS镜像的制作
      • CentOS镜像的制作
        • 前置条件
        • 镜像创建流程
        • 1.创建空白镜像文件
        • 2.安装虚拟机操作系统(使用界面安装即可)
        • 3.卸载光驱
        • 4.基本服务配置
        • 5.配置实例匹配元数据
        • 6. 配置console
        • 7. 虚拟机清理
        • 8. 取消libvirt域(domain)设置
    • Cinder服务详解
    • LVM详解
    • Nova服务详解
  • 心情杂货

  • 更多
  • OpenStack
周振林
2025-04-17
目录

CentOS镜像的制作

# CentOS镜像的制作

# 前置条件

下面这些步骤是在一个带图形化界面的CentOS7机器上操作的,这个机器下面我们称它为宿主机,因此我们需要先准备:

  • 一个安装了图形化桌面环境的CentOS 7
  • CentOS 7.x的镜像,我这里是7.9,放到/tmp目录下;
  • 宿主机CPU开启虚拟化支持
  • 在宿主机上执行下面的命令安装下面步骤中所需要的rpm依赖:
 yum install qemu-kvm libvirt virt-install virt-viewer virt-manager -y
1

其中virt-viewer是可视化的GUI组件。

# 镜像创建流程

# 1.创建空白镜像文件

首先执行下面命令创建一个空白的镜像文件

[root@controller2 ~]# qemu-img create -f qcow2 /tmp/centos.qcow2 10G

Formatting '/tmp/centos.qcow2', fmt=qcow2 size=10737418240 encryption=off 
cluster_size=65536 lazy_refcounts=off refcount_bits=16
1
2
3
4

如果直接用图形化界面安装虚拟机,也可以省略调这个流程,但是图形化安装的虚拟机镜像文件默认 路径是/var/lib/libvirt/images目录。

# 2.安装虚拟机操作系统(使用界面安装即可)

然后使用virt-install命令安装一个CentOS虚拟机或者直接使用virt-manager的图形化界面安装:

virt-install --virt-type kvm --name centos7.9 --ram 1024 \
--disk /tmp/centos.qcow2,format=qcow2 --network network=default \
--graphics vnc,listen=0.0.0.0 --noautoconsole --os-type=linux \
--os-variant=centos7.0 --location=/tmp/CentOS-7-x86_64-DVD-2009.iso
1
2
3
4

需要把iso文件放在/tmp目录下,避免一些额外的权限配置问题。在宿主机上安装了图形界面后,打开virt-manager,就能看到刚才命令创建的虚拟机。如下所示:

doc910bfbe89a6f41568cb2d04c34724a79.png

双击虚拟机名称,就能进入到虚拟机的console界面,此时开始安装。在虚拟机配置界面修改时区为上海,设置硬盘自动分区,设置网络为dhcp获取方式,域名使用默认的。进入安装流程,在安装流程中,设置需要的root密码和普通用户centos。

分区格式和硬盘自动扩展的关系

上面配置流程中选择的是硬盘自动分区,那么它默认使用的根分区格式是LVM格式,后面安装的cloudinit和cloud-utils-growpart包无法自动扩展LVM格式,需要自己手动写一个脚本来帮助cloud-init工具自动扩展系统盘,脚本命令依次是:

growpart /dev/vda 2  #先扩大/dev/vda2分区的大小
pvresize /dev/vda2   # 再扩大/dev/vda2这个pv的大小
num=$(vgdisplay | grep 'Free PE' | awk '{print $5}')   #这里获取新的PE总数量
vgchange -l $num /dev/centos           # 扩大根分区vg的大小,num是新的PE总数
lvresize -l +$[num-256] /dev/centos/root       # 减去256个PE的大小给Swap
xfs_growfs /    #扩大根文件系统大小
1
2
3
4
5
6

把这些命令写入到一个脚本autoExtendRootPartition.sh文件中,放在宿主机上,稍后使用。

如果不想使用上面的脚本来自动扩展硬盘分区,而是使用openstack自带的cloud-init来自动扩展分区,那么在安装这个虚拟机操作系统的时候,硬盘需要手动分区。一般只保留/boot、/、swap分区,同时swap分区必须在/ 分区之前,否则自动扩展程序会出错。要么就干脆不要swap分区。这样的话,根目录就直接对应的是/dev/vda2。

# 3.卸载光驱

虚拟机一般用不上光驱,因此一般需要把虚拟机里这个设备给卸载。等到虚拟机系统安装完毕,可以先使用下面的命令确认cdrom在系统中对应的文件名称,如下所示:

virsh dumpxml centos79
1

命令结果输出如下:

<domain type='kvm' id='9'>
 <name>centos79</name>
 <uuid>aeda72dc-5682-4cf4-a44a-97611c587aae</uuid>
 <memory unit='KiB'>1048576</memory>
 <currentMemory unit='KiB'>1048576</currentMemory>
 <vcpu placement='static'>1</vcpu>
 ...
 <disk type='file' device='cdrom'>
 <driver name='qemu' type='raw'/>
 <source file='/tmp/CentOS-7.9-x86_64-DVD-2009.iso'/>
 <backingStore/>
 <target dev='hda' bus='ide'/>
 <readonly/>
 <alias name='ide0-0-0'/>
 <address type='drive' controller='0' bus='0' target='0' unit='0'/>
 </disk>
 ... 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

使用root用户在宿主机上运行下面的命令弹出光驱,然后使用virsh重启。如果你是要GUI来弹出硬盘,可以使用停止和启动按钮来重启。(建议使用界面来弹出光驱)

# virsh detach-disk --type cdrom --mode readonly centos79 "" hda
# virsh reboot centos79
1
2

如果发现该命令对该版本的镜像没有效果,可以在virt-manager上通过图形界面进行分离。基本流程是:

  • 把虚拟机关机
  • 点击界面上的小灯泡图标,打开硬件配置,找到IDE CDROM
  • 点击邮件,选择remove hardware
  • 确认删除cdrom 然后重新启动该虚拟机,进入下面配置流程。

# 4.基本服务配置

等到虚拟机系统安装完毕后,登陆到虚拟机中。配置镜像使用的一些内网服务,例如将镜像源修改为内网的源:

 cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
 curl http://mirrors.avlyun.org/repo/centos7.repo > /etc/yum.repos.d/CentOS-Base.repo
1
2

安装常见的软件vim和net-tools,命令是:

yum install vim net-tools -y
1

然后配置ACPI服务,这个服务是宿主机用来控制虚拟机的一个中介服务,安装命令是:

yum install acpid
systemctl start acpid
systemctl enable acpid
1
2
3

如果有其他你们自己的基本服务需要安装,例如配置你们自己的管理组件,监控组件等等,也可以在这一步里都配置好。

禁用zeroconf路由

为了实例能够访问元数据服务,需要禁用zeroconf路由,命令是:

echo "NOZEROCONF=yes" > /etc/sysconfig/network
1

关闭防火墙和SELinux

不关闭防火墙,会导致启动的实例无法连接到元数据服务器,获取主机名等信息。命令是:

systemctl disable firewalld
systemctl stop firewalld
1
2

SELinux一般默认禁用,打开/etc/selinux/config文件,修改配置如下:

selinux=disabled
1

# 5.配置实例匹配元数据

实例在启动的过程中,必须和元数据(metadata)服务交互,来执行若干任务。例如获取ssh公钥,获取用户数据脚本等。要保证实例能够执行这些任务,有两种方式:

  • 安装一个cloud-init RPM包,这也是推荐的方式
  • 修改/etc/rc.local文件来匹配元数据服务需要的数据。

使用cloud-init来匹配公钥

cloud-init会自动从元数据服务中获取到公钥信息,并且保存到用户家目录下的authorized_keys文件中。因此需要安装这个包。cloud-initramfs-tools工具是用来在虚拟机启动时自动扩大系统分区的,因为上面创建的虚拟机镜像默认大小只有10G,这个工具在启动时会根据选择的虚拟机实例类型中的硬盘大小,自动配置根分区的大小。

cloud-utils-growpart工具是用来提供分区自动扩容的命令的。这3个组件的安装命令是:

yum install cloud-init cloud-utils cloud-initramfs-tools cloud-utils-growpart -y
1

这个时候如果发生了包冲突,例如cloud-init需要的一些包版本比较旧,而系统安装的比较新,可以使用yum的降级命令将包的版本降下来,然后就可以正常安装成功。

cloud-init将获取到的公钥保存在哪个目录取决于不同的发行版,在CentOS上默认是放在centos用户目录下,如果你要将它保存到不同的用户目录下,可以修改/etc/cloud/cloud.cfg文件,配置内容格式是:

users:
 - name: admin
1
2

上面的格式是配置了将公钥放在admin用户目录下

修改/etc/rc.local文件来匹配元数据服务需要的数据

如果不使用cloud-init来获取虚拟机元数据,则需要写一个脚本来从元数据服务中获取公钥并写入用户家目录,脚本内容如下:

if [ ! -d /root/.ssh ]; then
  mkdir -p /root/.ssh
  chmod 700 /root/.ssh
fi
# Fetch public key using HTTP
ATTEMPTS=30
FAILED=0
while [ ! -f /root/.ssh/authorized_keys ]; do
 curl -f http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key \
    > /tmp/metadata-key 2>/dev/null
 if [ \$? -eq 0 ]; then
    cat /tmp/metadata-key >> /root/.ssh/authorized_keys
    chmod 0600 /root/.ssh/authorized_keys
    restorecon /root/.ssh/authorized_keys
    rm -f /tmp/metadata-key
    echo "Successfully retrieved public key from instance metadata"
    echo "*****************"
    echo "AUTHORIZED KEYS"
    echo "*****************"
    cat /root/.ssh/authorized_keys
    echo "*****************"
  fi
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 6. 配置console

要想nova console-log命令在以这个CentOS7镜像创建的虚拟机上正常运行,你需要执行下面几个步骤:

(1)编辑/etc/default/grub文件

配置GRUB_CMDLINE_LINUX选项,删除rhgb quiet,然后添加console=tty0 console=ttyS0,115200n8到选项中

例如:

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap \
console=tty0 console=ttyS0,115200n8"
1
2

(2)运行下面的命令保存配置,生成新的引导参数:

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

引导项配置好以后在虚拟机里使用root用户执行关机命令关闭虚拟机:

poweroff
1

# 7. 虚拟机清理

在虚拟机启动的时候,操作系统会记录虚拟网卡的mac地址,例如/etc/sysconfig/network-scripts/ifcfg-eth0。然而每次镜像启动的不同实例的虚拟网卡都需要有不同的mac地址,所以类似这样的唯一性信息必须从虚拟机的配置文件里清除掉。完成这个任务的工具叫做virt-sysprep,能够执行大量的虚拟机清理任务,例如移除mac地址引用。清理一个虚拟机的命令如下:

virt-sysprep -d centos79
1

如果没有这个命令的话,还需要先安装,安装命令是:

yum install libguestfs-tools -y
1

-d参数后面是虚拟机的名称。virt-sysprep命令的执行过程如下:

 [   0.0] Examining the guest ... 
 [  29.9] Performing "abrt-data" ... 
 [  29.9] Performing "backup-files" ... 
 [  31.3] Performing "bash-history" ... 
 [  31.4] Performing "blkid-tab" ... 
 [  31.4] Performing "crash-data" ... 
 [  31.4] Performing "cron-spool" ... 
 [  31.4] Performing "dhcp-client-state" ... 
 [  31.4] Performing "dhcp-server-state" ... 
 [  31.4] Performing "dovecot-data" ... 
 [  31.5] Performing "logfiles" ... 
 [  31.6] Performing "machine-id" ... 
 [  31.6] Performing "mail-spool" ... 
 [  31.6] Performing "net-hostname" ... 
 [  31.6] Performing "net-hwaddr" ... 
 [  31.6] Performing "pacct-log" ... 
 [  31.6] Performing "package-manager-cache" ... 
 [  31.7] Performing "pam-data" ... 
 [  31.7] Performing "passwd-backups" ... 
 [  31.8] Performing "puppet-data-log" ... 
 [  31.8] Performing "rh-subscription-manager" ... 
 [  31.8] Performing "rhn-systemid" ... 
 [  31.8] Performing "rpm-db" ... 
 [  31.8] Performing "samba-db-log" ... 
 [  31.8] Performing "script" ... 
 [  31.8] Performing "smolt-uuid" ... 
 [  31.9] Performing "ssh-hostkeys" ... 
 [  31.9] Performing "ssh-userdir" ... 
 [  31.9] Performing "sssd-db-log" ... 
 [  31.9] Performing "tmp-files" ... 
 [  31.9] Performing "udev-persistent-net" ... 
 [  31.9] Performing "utmp" ... 
 [  31.9] Performing "yum-uuid" ... 
 [  31.9] Performing "customize" ...
 [  32.0] Setting a random seed
 [  32.0] Setting the machine ID in /etc/machine-id
 [  32.1] Performing "lvm-uuids" ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

这条命令会清理掉机器里面所有账号的.ssh目录,如果你想保留对应的key文件,例如你们公司自己的管理公钥。则需要通过不同的命令行选项来注入对应的文件,在宿主机上执行命令如下所示:

virt-sysprep -d centos7.8.2003 --ssh-inject root:file:yourkey.pub \
--ssh-inject centos:file:yourkey.pub \
--firstboot-command "chattr +i /root/.ssh/authorized_keys" \
--firstboot autoExtendRootPartition.sh
1
2
3
4

配置项说明:--ssh-inject 将公钥内容保存在antiykey.pub文件中,然后通过上面的语法,注入到镜像内。--firstboot-command选项是要首次启动时要执行的命令,我这里是将root用户的authorized_keys文件加上-i 特殊标志位,添加这个标志位会导致在启动实例的时候注入公钥失败,因此如果你不需要的话,就不要添加这个选项。--firtboot命令是在首次启动时运行上面的自动扩展分区的脚本,将root分区大小扩展到和实例类型中匹配的硬盘大小。

# 8. 取消libvirt域(domain)设置

现在你可以把虚拟机镜像文件上传到Glance镜像服务了,不再需要通过libvirt管理的这个虚拟机镜像。使用virsh undefine vm-image命令来通知libvirt,取消我们上面创建的虚拟机centos79注册,在宿主机上执行:

virsh undefine centos79
1

这个时候在libvirt里就看不到这个虚拟机的记录,只剩下它的硬盘镜像文件。在将镜像导入openstack集群之前,还可以把镜像文件再压缩一下,在宿主机上执行下面的命令是:

virt-sparsify /path/to/source.qcow2 --compress /path/to/output.qcow2
1

这个命令会将镜像中没有使用的硬盘空间全部使用0填充,能极大的压缩原来镜像的大小。压缩完成后,就可以基于这个虚拟机镜像文件,使用qemu-img create命令在OpenStack集群里创建需要使用的镜像文件,示例命令格式是:

openstack image create --file centos-7.9-x86_64.qcow2 --disk-format qcow \
  --container-format bare  --public centos-7.9-x86_64
1
2

如果想将镜像格式转换成raw格式,那么可以使用下面的命令,在宿主机上执行:

qemu-img convert -f qcow -O raw centos-7.9-x86_64.qcow2 centos-7.9-x86_64.raw
1

就可以把qcow2格式的镜像文件转换为raw格式,转换之后,镜像会变大。

Last Updated: 2025/06/18, 08:59:15
Glance服务详解
Cinder服务详解

← Glance服务详解 Cinder服务详解→

最近更新
01
Docker安装
06-10
02
Docker运行JAR
06-10
03
Docker部署MySQL
06-10
更多文章>
Copyright © 2019-2025 鲁ICP备19032096号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式