如何制作Openstack Linux镜像

在上一篇文章构建Openstack镜像的环境搭建中我们介绍了如何在自己的笔记本或台式机上搭建一个可以用于制作Openstack镜像的环境,本文我们将利用这个环境,以制作CentOS7.1镜像为例,介绍手动制作Openstack Linux镜像的详细步骤。

手动制作Openstack Linux镜像


下载镜像

访问镜像下载地址,进入后选择版本为7.1.1503,在isos目录下下载x86_64的Minimal镜像,并上传到/tvm下。如果网速不给力,最好不要选择下载Netinstall镜像,因为这会在安装时联网下载大量的软件包,重新安装时需要重新下载这些软件包。

创建虚拟机

首先创建一个raw格式镜像文件,用于虚拟机的根磁盘,大小30G就够了。(镜像文件大小可根据实际情况自行调整,此处以30G为例)

1
2
cd /tvm/
qemu-img create -f raw CentOS7.1.raw 30G

修改/tvm/templates.xml,将图中红色方框处改成虚拟机镜像文件所在绝对路径,并指定相应ISO文件绝对路径。

启动虚拟机

1
2
cd /tvm/
virsh create templates.xml

启动完成后,使用vnc client连接到虚拟机控制台。

安装OS

进入虚拟机控制台可以看到CentOS的启动菜单,选择“Install CentOS 7”,继续选择语言后将进入INSTALL SUMMARY,其中大多数配置默认即可,时区选择“Asia/Shanghai”,“SOFTWARE SELECTION”选择“Minimal Install”,“INSTALLATION DESTINATION”需要选择手动配置分区,我们只需要一个根分区即可,不需要swap分区,Device Type选择Standard Partition(务必选择此选项,因为cloud-init只支持标准分区的自动扩展),文件系统选择ext4或者xfs,存储驱动选择Virtio Block Device,如图:

配置完成后就可以开始安装了,在CONFIGURATION中设置root用户密码。大约几分钟后,即可自动完成安装配置工作,最后点击右下角的reboot重启退出虚拟机。

注:此时你会发现虚拟机重启后又再次进入了CentOS的启动菜单,因此需要先终止掉此虚拟机进程,然后修改/tvm/templates.xml,将文件中指定的ISO文件路径清空,然后再次启动虚拟机,此时虚拟机就会直接从硬盘中启动系统。

1
2
3
4
5
6
7
[root@koenli tvm]# virsh list
Id Name State
----------------------------------------------------
3 koenli running

[root@koenli tvm]# virsh destroy 3
Domain 3 destroyed

配置OS

配置网卡配置文件

配置网卡配置文件ifcfg-eth0,ifcfg-eth1,删除mac地址和UUID相关配置项,IP为dhcp获取,开机自启动

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
38
39
40
41
42
43
44
45
46
47
CentOS6.x/RedHat6.x操作如下:
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=dhcp
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
DEVICE=eth1
TYPE=Ethernet
ONBOOT=no
NM_CONTROLLED=yes
BOOTPROTO=dhcp
EOF

/etc/init.d/network restart

CentOS7.x/RedHat7.x操作如下:
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
TYPE=Ethernet
BOOTPROTO=dhcp
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
NAME=eth0
DEVICE=eth0
ONBOOT=yes
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
TYPE=Ethernet
BOOTPROTO=dhcp
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
NAME=eth1
DEVICE=eth1
ONBOOT=no
EOF

systemctl stop NetworkManager
systemctl disable NetworkManager
systemctl restart network

配置sshd服务

关闭sshd服务的UseDNS和GSSAPIAuthentication选项

1
2
3
4
5
6
7
8
9
CentOS6.x/RedHat6.x操作如下:
sed -i 's/#UseDNS yes/UseDNS no/g' /etc/ssh/sshd_config
sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/g' /etc/ssh/sshd_config
/etc/init.d/sshd restart

CentOS7.x/RedHat7.x操作如下:
sed -i 's/#UseDNS yes/UseDNS no/g' /etc/ssh/sshd_config
sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/g' /etc/ssh/sshd_config
systemctl restart sshd

配置iptables和selinux

关闭iptables和selinux,并设置开机不自启(需重启生效)

1
2
3
4
5
6
7
8
9
10
11
12
13
CentOS6.x/RedHat6.x操作如下:
/etc/init.d/iptables stop
chkconfig iptables off
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
reboot

CentOS7.x/RedHat7.x操作如下:
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
reboot

系统参数和内核参数优化

设置系统文件句柄数限制和进程数限制(需重启生效)

1
2
3
4
5
6
7
8
CentOS6.x/RedHat6.x/CentOS7.x/RedHat7.x操作如下:
cat >> /etc/security/limits.conf << EOF
* soft nproc 655360
* hard nproc 655360
* soft nofile 655360
* hard nofile 655360
EOF
reboot

设置系统内核参数

1
2
3
4
5
6
7
8
9
10
11
12
CentOS6.x/RedHat6.x操作如下:
cp -a /etc/sysctl.conf /etc/sysctl.conf.bak
echo "net.ipv4.ip_forward=1" > /etc/sysctl.conf
echo "net.ipv4.conf.default.rp_filter=0" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf
sysctl -p

CentOS7.x/RedHat7.x操作如下:
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv4.conf.default.rp_filter=0" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf
sysctl -p

设置history历史命令显示格式

1
2
3
CentOS6.x/RedHat6.x/CentOS7.x/RedHat7.x操作如下:
echo 'HISTTIMEFORMAT="[%Y-%m-%d %H:%M:%S $USER] "' >> /etc/profile
source /etc/profile

上传iso文件配置本地yum源

此步可参考CentOS6.X/CentOS7.X配置本地yum源教程,此处不再赘述。

安装基础软件包

1
2
CentOS6.x/RedHat6.x/CentOS7.x/RedHat7.x操作如下:
yum install -y vim net-tools lrzsz unzip dos2unix telnet sysstat iotop pciutils lsof tcpdump wget strace ipmitool psmisc tree bc

安装epel源

https://fedoraproject.org/wiki/EPEL/zh-cn下载对应操作系统版本的epel-release包的最新版本,然后上传到虚拟机的/root目录下并安装

1
2
3
4
5
6
7
8
9
CentOS6.x/RedHat6.x操作如下:
cd /root/
rpm -ivh epel-release-latest-6.noarch.rpm
rm -rf epel-release-latest-6.noarch.rpm

CentOS7.x/RedHat7.x操作如下:
cd /root/
rpm -ivh epel-release-latest-7.noarch.rpm
rm -rf epel-release-latest-7.noarch.rpm

安装cloud-utils-growpart

安装cloud-utils-growpart工具,实现根分区自动扩展

1
2
3
4
5
6
CentOS6.x/RedHat6.x操作如下:
yum install cloud-utils-growpart dracut-modules-growroot -y
dracut -f

CentOS7.x/RedHat7.x操作如下:
yum install cloud-utils-growpart -y

安装cloud-init

https://share.weiyun.com/5gNv58k 密码:k6wnsx 下载对应操作系统版本的cloud-init安装包,并上传到虚拟机的/root/cloud-init目录下并安装(/root/cloud-init目录通过执行mkdir /root/cloud-init新建)

1
2
3
4
5
6
7
CentOS6.x/RedHat6.x操作如下:
cd /root/cloud-init/
yum localinstall *.rpm -y

CentOS7.x/RedHat7.x操作如下:
cd /root/cloud-init/
yum localinstall *.rpm -y

编辑/etc/cloud/cloud.cfg,将disable_root参数设为0(允许root用户ssh远程登录),ssh_pwauth参数设为1(允许password认证),保存退出

1
2
3
4
5
6
7
8
CentOS6.x/RedHat6.x/CentOS7.x/RedHat7.x操作如下:
vim /etc/cloud/cloud.cfg
users:
- default

disable_root: 0
ssh_pwauth: 1
...

启动cloud-init并设置开机自启,因为做镜像的环境是无法访问到openstack的元数据服务的,故此次启动cloud-init时间会比较长,可以新开一个窗口执行tail -f /var/log/messages查看启动进度。

1
2
3
4
5
6
7
CentOS6.x/RedHat6.x操作如下:
chkconfig cloud-init on
/etc/init.d/cloud-init restart

CentOS7.x/RedHat7.x操作如下:
systemctl enable cloud-init
systemctl restart cloud-init

CentOS7.x/RedHat7.x上若cloud-init启动失败,执行systemctl status cloud-init查看服务状态,若出现类似如下报错,则执行下面的指令更新six,然后再次启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 2...dule>
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: from cloudinit import netinfo
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: File "/usr/lib/python2.7/site-packages/cloudinit/netinfo.py", line 14...dule>
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: from cloudinit import util
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: File "/usr/lib/python2.7/site-packages/cloudinit/util.py", line 37, i...dule>
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: from six.moves.urllib import parse as urlparse
Dec 12 00:12:59 localhost.localdomain cloud-init[1989]: ImportError: No module named urllib
Dec 12 00:12:59 localhost.localdomain systemd[1]: cloud-init.service: main process exited, code=exited, status=1/FAILURE
Dec 12 00:12:59 localhost.localdomain systemd[1]: Failed to start Initial cloud-init job (metadata service crawler).
Dec 12 00:12:59 localhost.localdomain systemd[1]: Unit cloud-init.service entered failed state.

解决方法:
yum install python-pip -y
pip install --upgrade six
systemctl enable cloud-init
systemctl restart cloud-init

CentOS7.x/RedHat7.x需再次编辑网卡配置文件,将网卡配置文件(/etc/sysconfig/network-scripts/ifcfg-eth0)中的HWADDR一行删除并保存退出。

安装qemu-guest-agent

1
2
3
4
5
6
CentOS6.x/RedHat6.x操作如下:
yum install qemu-guest-agent -y
chkconfig qemu-ga on

CentOS7.x/RedHat7.x操作如下:
yum install qemu-guest-agent -y

禁用zeroconf

编辑/etc/sysconfig/network-scripts/ifup-eth注释掉以下部分,禁用zeroconf,否则zeroconf router在虚拟机开机时会自动生成路由169.254.0.0/16 0 0 0 0导致虚拟机无法与元数据通信

1
2
3
4
5
6
7
8
9
10
11
原内容
# Add Zeroconf route.
if [ -z "${NOZEROCONF}" -a "${ISALIAS}" = "no" -a "${REALDEVICE}" != "lo" ]; then
ip route add 169.254.0.0/16 dev ${REALDEVICE} metric $((1000 + $(cat /sys/class/net/${REALDEVICE}/ifindex))) scope link
fi

注释后:
# Add Zeroconf route.
#if [ -z "${NOZEROCONF}" -a "${ISALIAS}" = "no" -a "${REALDEVICE}" != "lo" ]; then
# ip route add 169.254.0.0/16 dev ${REALDEVICE} metric $((1000 + $(cat /sys/class/net/${REALDEVICE}/ifindex))) scope link
#fi

设置NTP(可选)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CentOS6.x/RedHat6.x操作如下:
yum install ntp ntpdate -y
sed -i "s%^server%#server%g" /etc/ntp.conf
echo "server <ntpserver_ip>" >> /etc/ntp.conf #<ntpserver_ip>替换为ntpserver的IP地址
/etc/init.d/ntpd restart
chkconfig ntpd on

CentOS7.x/RedHat7.x操作如下:
yum install ntp ntpdate -y
sed -i "s%^server%#server%g" /etc/ntp.conf
echo "server <ntpserver_ip>" >> /etc/ntp.conf #<ntpserver_ip>替换为ntpserver的IP地址
systemctl restart ntpd
systemctl enable ntpd
systemctl stop chronyd
systemctl disable chronyd

清理文件

1
2
3
4
5
CentOS6.x/RedHat6.x/CentOS7.x/RedHat7.x操作如下:
rm -rf /root/cloud-init/
rpm -e `rpm -qa |grep epel`
yum clean all
rm -rf /etc/udev/rules.d/70-persistent-net.rules

清理命令历史记录并关机

1
2
3
4
5
6
CentOS6.x/RedHat6.x/CentOS7.x/RedHat7.x操作如下:
echo > /var/log/wtmp
echo > /var/log/btmp
echo > ~/.bash_history
history -c
shutdown -h now

以上为几个比较常用的配置,更多自定义配置可以参考此文

转换镜像格式

将raw格式镜像文件转换成qcow2格式镜像文件,压缩空间便于传输。

1
qemu-img convert -f raw CentOS7.1.raw -O qcow2 CentOS7.1.qcow2

上传镜像


Openstack Linux镜像制作完成后,将最终生成的qcow2镜像文件上传到Openstack控制节点,先转成raw镜像文件,然后通过glance命令上传镜像,最后设置镜像的hw_qemu_guest_agent属性为yes即可。相关命令如下:

1
2
3
qemu-img convert -f qcow2 CentOS7.1.qcow2 -O raw CentOS7.1.raw
glance image-create --name "CentOS7.1" --file /tvm/CentOS7.1.raw --disk-format raw --container-format bare --is-public True --progress
glance image-update --property hw_qemu_guest_agent=yes <image_id>
  • EOF

本文作者:Koen

参考链接:https://xiexianbin.cn/openstack/2016/12/14/centos-root-partition-auto-grow