为 OpenStack Nova 制作 Ubuntu 镜像

最近超级忙,被 Mesh Potato 的项目折腾的不行,发现只要什么东西沾上 “分布式、集群” 这些东西事情就变得格外复杂,一台 Asterisk 服务器做 VoIP 容易,n 台 Asterisk 服务器做集群就不容易;一台 Xen/KVM 服务器做虚拟机容易,n 台 Xen/KVM 服务器做云计算就不是那么容易。上星期我们介绍了在 Ubuntu 上安装和配置 OpenStack Nova,今天来进一步介绍如何在 OpenStack Nova 环境里制作虚拟机模板(镜像)以及创建虚拟机运行实例(以 Ubuntu 为例子)。为了和我们平时说的 “VMware/Xen/KVM/VirtualBox 虚拟机” 区分开,VPSee 在这里把在 OpenStack Nova、OpenNebula 这样的云计算平台上运行的虚拟机称为 “云虚拟机”。简单说在 OpenStack Nova 平台上运行一个 ubuntu 虚拟机的流程是:先制作一个 ubuntu 虚拟机镜像(模板),然后再以这个镜像为模板来创建 ubuntu 虚拟机(实例)。

安装 Ubuntu 镜像

首先下载要安装的 ubuntu 版本:

$ wget http://releases.ubuntu.com/lucid/ubuntu-10.04.2-server-amd64.iso

创建一个 10GB 大小的 “硬盘”(raw 格式):

$ kvm-img create -f raw ubuntu.img 10G
Formatting 'ubuntu.img', fmt=raw size=10737418240

使用刚才下载的 ubuntu “安装盘” 和刚创建的 “硬盘” 引导启动系统,为了简单起见,VPSee 在这里使用 kvm 虚拟技术,避开 xen 繁琐的配置。-vnc 参数代表打开 vnc 访问,以便可以用其他机器远程登录到这个引导界面进行安装操作:

$ sudo kvm -m 512 -cdrom ubuntu-10.04.2-server-amd64.iso \
-drive file=ubuntu.img -boot d -nographic -vnc :0

用 vncviewer 登录引导界面后按照屏幕的提示完成 ubuntu 的安装工作(和在自己电脑上安装 ubuntu 过程一样)。需要注意的是在分区阶段把 10GB 硬盘全部划分成一个 ext4 root 分区,不要创建多个分区也不要创建 swap 区:

$ vncviewer 172.16.39.111:5900

安装完后退出(必要时 kill 掉 kvm 进程),按照下面命令启动刚刚安装好的虚拟机镜像 ubuntu.img,如果出现 failed to find romfile “pxe-rtf8139.bin” 的错误提示可以通过安装 kvm-pxe 解决:

$ sudo kvm -m 512 -drive file=ubuntu.img -boot c -nographic -vnc :0
kvm: pci_add_option_rom: failed to find romfile "pxe-rtl8139.bin"

$ sudo apt-get install kvm-pxe

再次用 vnc 登录虚拟机镜像,安装一些必要工具(因为这个镜像将会是模板,所以最好保持最简最小化,不要乱装东西):

$ vncviewer 172.16.39.111:5900

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install openssh-server cloud-init

70-persistent-net.rules 会自动添加其他的网络接口,需要删除这个文件避免自动添加除了 eth0 以外的接口。删除后系统基本就准备好了,关闭虚拟机:

$ sudo rm -rf /etc/udev/rules.d/70-persistent-net.rules

$ sudo shutdown -h now

调整 Ubuntu 镜像

因为 OpenStack 只接受 ext4 文件系统格式的镜像,所以需要把上面创建的 raw 镜像(kvm-img create -f raw)转换成 ext4 镜像。下面的步骤用来找出镜像文件里面的分区起点是从哪里开始的:

$ sudo losetup -f ubuntu.img 
$ sudo losetup -a
/dev/loop0: [fb00]:24117291 (/home/vpsee/ubuntu.img)

$ sudo fdisk -cul /dev/loop0

Disk /dev/loop0: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders, total 20971520 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
Disk identifier: 0x000502e6

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1   *        2048    20969471    10483712   83  Linux

上面最后一行显示分区是从扇区(sector)2048开始的,每个扇区是512个字节,所以是从 2048 x 512 = 1048576个字节开始的。记住这个1048576,下面会用到。

卸载 loop 后重新从1048576字节开始挂载:

$ sudo losetup -d /dev/loop0

$ sudo losetup -f -o 1048576 ubuntu.img 
$ sudo losetup -a
/dev/loop0: [fb00]:24117291 (/home/vpsee/ubuntu.img), offset 1048576

把这整个分区拷贝到一个新文件就是一个我们要的 ext4 文件系统镜像:

$ sudo dd if=/dev/loop0 of=ubuntutemplate.img
20969472+0 records in
20969472+0 records out
10736369664 bytes (11 GB) copied, 107.455 s, 99.9 MB/s

用完 loop 后记得卸载:

$ sudo losetup -d /dev/loop0

挂载(mount)刚创建的 ext4 文件系统镜像,并修改分区加载表(/etc/fstab),注释或删除以前的,加上 UUID=uec-rootfs 一行:

$ sudo mount -o loop ubuntutemplate.img /mnt

$ sudo vi /mnt/etc/fstab
#UUID=1dc3a59e-faab-41ee-b232-3300163676bf / ext4 errors=remount-ro 0 1
UUID=uec-rootfs                           / ext4 defaults          0 0

把内核(vmlinuz)和内存盘(initrd)文件拷贝出来以便后面和虚拟机镜像一起发布到OpenStack 云里。使用完虚拟机镜像后记得卸载(unmount):

$ sudo cp /mnt/boot/vmlinuz-2.6.32-28-server /home/vpsee/
$ sudo cp /mnt/boot/initrd.img-2.6.32-28-server /home/vpsee/

$ sudo umount /mnt

把刚才的虚拟机镜像 ubuntutemplate.img 的文件系统标志改成 ‘uec-rootfs’:

$ sudo tune2fs -L uec-rootfs ubuntutemplate.img 
tune2fs 1.41.14 (22-Dec-2010)

发布 Ubuntu 镜像

好了,ubuntu 镜像已经做好了,现在可以发布到云里了,需要3个东西,虚拟机的内核文件、虚拟机的内存盘文件和虚拟机镜像文件:

$ uec-publish-image -t image --kernel-file vmlinuz-2.6.32-28-server \
--ramdisk-file initrd.img-2.6.32-28-server amd64 ubuntutemplate.img mybucket
ami-00000006	mybucket/ubuntutemplate.img.manifest.xml

等待一段时间后出现 ami-00000006 mybucket/ubuntutemplate.img.manifest.xml 表示我们刚制作的 ubuntu 镜像已经正式发布到云里,以后就可以以这个镜像为模板来快速生成虚拟机实例(instance)。可以通过 euca-describe-images 来查看:

$ euca-describe-images

IMAGE	aki-00000001	mybucket/vmlinuz-2.6.32-28-server.manifest.xml		availablpublic		x86_64	kernel	 	 
IMAGE	ari-00000002 	mybucket/initrd.img-2.6.32-28-server.manifest.xml		available	public		x86_64	ramdisk	 	 
IMAGE	ami-00000003	mybucket/ubuntutemplate.img.manifest.xml		untarring	public		x86_64	machine	aki-00000001	ari-00000002

第一个 Ubuntu 虚拟机实例

有了 ubuntu 镜像(模板)以后我们就可以以这个 “镜像” 为模板来为云计算用户创建 n 个 ubuntu 虚拟机(操作系统)实例,不过在运行实例之前需要 key:

$ euca-add-keypair mykey > mykey.priv
$ chmod 600 mykey.priv 

$ euca-describe-keypairs
KEYPAIR	mykey	76:7d:93:88:a0:e5:3e:5d:4b:62:cd:85:c5:23:7a:05

$ euca-run-instances -k mykey -t m1.tiny ami-00000003
RESERVATION	r-n0lpdme5	vpseecloud	default
INSTANCE	i-00000001	ami-00000003			scheduling	mykey (vpseecloud, None)	0		m1.tin2011-05-20T14:00:34Z	unknown zone

上面使用 euca-run-instances 创建一个实例后可以用 nova-manage 命令看到:

$ sudo nova-manage vm list
instance   node            type       state      launched            image        kernel       ramdisk       project    user       zone       index
i-00000001 node01           launching  None                3            1            2             vpseecloud    vpsee       None       0

还记得上篇:在 Ubuntu 上安装和配置 OpenStack Nova 的创建网络部分吗?可以看看现在的云里面 IP 分配情况:

$ sudo nova-manage network list
network           	netmask        	start address  	DNS            
192.168.3.0/25    	255.255.255.128	192.168.3.3    	None           

刚才用 euca-run-instances 启动的一个 ubuntu 虚拟机实例的 IP 就是从 192.168.3.3 开始的,所以 ssh 登录这个 IP 就登上了我们的第一个云虚拟机:)

$ ssh 192.168.3.3
vpsee@i-00000001:~$ 

想制作 CentOS 虚拟机镜像的话可以看:为 OpenStack Nova 制作 CentOS 镜像;想制作 Windows 虚拟机镜像的话可以看:为 OpenStack Nova 制作 Windows 镜像

评论 (32 Comments)

  1. 麻烦做一个opennebula2.2.x+debian-6.0+sunstone的教程吗?

  2. 能否请教一下,如何让VM通过host的eth0从dhcp server获取IP?

  3. 在虚拟机里面看不到添加的逻辑卷:

    您好,我使用ubuntu 10.04做的模板,
    反馈这样一个情况:
    制作出来的模板,需要modprobe acpiphp 后,才能正常使用volume服务。

    下面操作,在制作模板的时候,或在启动的虚拟机里面操作都可以:
    $ echo ‘acpiphp’ >> /etc/modules
    这样每次启动就能加载acpiphp了。

    回楼上:
    你可以在/etc/nova/nova.conf 里面写这么一行:

    –flat_interface=eth0

    这样的一句就可以了。不过设置这么一句会有风险,更详细的说明请参考 nova网站上的管理手册,怎么设置dhcp的方式,是6.2.2 章节。

  4. @zz2
    嗯,如果用了 EBS volume 的话需要在装载 acpiphp 模块。

  5. Dear vpsee
    請問,我每次在做好image的時候
    root@van-compute:~# uec-publish-image -t image –kernel-file vmlinuz-2.6.38-8-server –ramdisk-file initrd.img-2.6.38-8-server amd64 ubuntu_final.img bucket
    failed to check for existing manifest
    failed to register vmlinuz-2.6.38-8-server
    都會是這個結果,請問我哪裡出了錯?

  6. @van
    设置novarc环境
    . novarc

  7. 你好,按照你的配置,我启动实例后,实例立刻就shutdown掉了,报错是failed to spawn None 这是什么原因?

  8. 你好,按照你的配置,我制作一个模板,启动系统也是ok的,但是 这个模板太大了10G。 我安装的系统实际使用大小才1G,请问怎么才能制作的模板小点呢? (在官网下载的模板文件都很小)

  9. @梦飞
    你可以制作较小的镜像,比如上面的 $ kvm-img create -f raw ubuntu.img 10G 改成 2G 就可以了。

  10. @andy
    我的情况和你一样,启动后就立即shutdown了

  11. @vpsee
    制作好的镜像在上传的时候出现提示:
    tar: vmlinuz-2.6.38-8-server:无法 open: 权限不够
    tar: 由于前次错误,将以上次的错误状态退出
    failed to bundle kernel vmlinuz-2.6.38-8-server
    failed to register vmlinuz-2.6.38-8-server
    请问怎么解决呢?谢谢!

  12. @vpsee
    在vncviewer localhost:5900时,密码不知道多少,请问默认是多少的呢?ubuntu-11.10-desktop-i386镜像。

  13. @vpsee
    额。不好意思,是我设置错了,是不许要密码的

  14. dear vpsee:
    我遇到5楼一样的问题,看到你在6楼的回复后还是不太懂,我已经做了source /home/amm/creds/novarc 的操作了,结果还是一样的问题

  15. root@van-compute:~# uec-publish-image -t image –kernel-file vmlinuz-2.6.38-8-server –ramdisk-file initrd.img-2.6.38-8-server amd64 ubuntu_final.img bucket
    failed to check for existing manifest
    failed to register vmlinuz-3.0.0.12-server

    你好,我安装openstack时发布镜像时出现如上错误
    novarc那里我完全按照官方的安装文档来的
    能详细说说吗
    谢谢

  16. @yzhou
    先不考虑你自己做的 image,你能发布官方的 ubuntu image 吗?有没有报错?

    $ wget http://c0179148.cdn1.cloudfiles.rackspacecloud.com/ubuntu1010-UEC-localuser-image.tar.gz
    $ uec-publish-tarball ubuntu1010-UEC-localuser-image.tar.gz ubuntu1010-bucket x86_64

  17. vpsee大神,我碰上yzhou类似镜像没有发布成功的问题,上面说的errno 111的connection refused问题,包括我自己的镜像还有官方的镜像。我发现我的s3的端口是开启监听的,而且s3是本机的IP地址,这个也没有错。后来我到网上说把s3_host改成0.0.0.0 后面的话就成功了..这个非常诡异。因为我之前做过FLAT模式的,也做过一次镜像,没有碰上这样的问题。但这次再重新做一次就出现这样的问题.竟然把s3_host修改成那样就可以了.
    不知道你有没有了解过

  18. 我遇到了和@梦飞一样的问题就是制作出来的镜像太大了。原因是因为无论是dd 还是cp命令都要在提取Ext4的文件系统时,把原来的文件空洞给填充上,所以非常大。请问有什么办法能在提取时不填充文件空洞呢?最好是提取出来的ext4文件系统等于安装时候 实际使用的大小!我同样看到了uec官方的镜像都很小。

  19. 请教:

    localadmin@client-Dell:~/creds$ euca-get-console-output i-00000002
    UnknownError: An unknown error has occurred. Please try your request again.

    环境,单网卡:
    Server1, nova,glance,swift,ntp,mysql…;
    Server2, nova-compute
    Client,

    详情:
    http://blog.csdn.net/panblack/article/details/7180878

    问题可能在哪呢?

  20. @panblack
    根据你日志提供的信息 Stderr: ‘ERROR: trying to add VLAN #100 to IF -:br100:- error: No such device\n’,貌似网络配置(网桥、VLAN、网卡等)配置不对,i-00000002 根本没有正常启动,所以无法 euca-get-console-output 得到终端输出。

  21. 按照你的配置,同样出现
    failed to check for existing manifest
    failed to register vmlinuz-3.0.0.12-server
    然后下了其他镜像,提示没有cert.pem。。。请问何解

  22. 请问一下,做出来的镜像Xen能运行吗?如果不能,应该怎样修改呢?

  23. @vpsee
    kvm kernel version too old: KVM_GET_API_VERSION ioctl not supported
    Could not initialize KVM, will disable KVM support
    请问怎么解决阿?

  24. @Anonymous
    CPU 是否支持 VT?然后可能 kernel 和 kvm module 不合或冲突,升级 kernel 然后单独删除 /lib/modules/3.x/kernel/drivers/kvm

  25. @K.T.Cheang
    这个是 kvm 的,不能直接运行。换个 xen 内核,然后需要改几个地方,比较麻烦。

  26. @vpsee
    好的,谢谢,我自己再研究一下

  27. 你好,我在发布官方的 ubuntu image的时候出现以下问题:
    nova-api.log输出
    2012-05-07 18:14:23 INFO nova.rpc.common [req-44d575b3-ba08-46da-b055-d5035629b8bd ubuntu1 novaproject] Connected to AMQP server on 192.168.100.11:5672
    2012-05-07 18:14:31 ERROR nova.rpc.common [req-9adeae61-dc47-48de-94d6-474ee7c27e97 ubuntu1 novaproject] Timed out waiting for RPC response: timed out
    2012-05-07 18:14:31 TRACE nova.rpc.common Traceback (most recent call last):
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/nova/rpc/impl_kombu.py”, line 490, in ensure
    2012-05-07 18:14:31 TRACE nova.rpc.common return method(*args, **kwargs)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/nova/rpc/impl_kombu.py”, line 567, in _consume
    2012-05-07 18:14:31 TRACE nova.rpc.common return self.connection.drain_events(timeout=timeout)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/kombu/connection.py”, line 175, in drain_events
    2012-05-07 18:14:31 TRACE nova.rpc.common return self.transport.drain_events(self.connection, **kwargs)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/kombu/transport/pyamqplib.py”, line 238, in drain_events
    2012-05-07 18:14:31 TRACE nova.rpc.common return connection.drain_events(**kwargs)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/kombu/transport/pyamqplib.py”, line 57, in drain_events
    2012-05-07 18:14:31 TRACE nova.rpc.common return self.wait_multi(self.channels.values(), timeout=timeout)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/kombu/transport/pyamqplib.py”, line 63, in wait_multi
    2012-05-07 18:14:31 TRACE nova.rpc.common chanmap.keys(), allowed_methods, timeout=timeout)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/kombu/transport/pyamqplib.py”, line 120, in _wait_multiple
    2012-05-07 18:14:31 TRACE nova.rpc.common channel, method_sig, args, content = read_timeout(timeout)
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/kombu/transport/pyamqplib.py”, line 94, in read_timeout
    2012-05-07 18:14:31 TRACE nova.rpc.common return self.method_reader.read_method()
    2012-05-07 18:14:31 TRACE nova.rpc.common File “/usr/lib/python2.7/dist-packages/amqplib/client_0_8/method_framing.py”, line 221, in read_method
    2012-05-07 18:14:31 TRACE nova.rpc.common raise m
    2012-05-07 18:14:31 TRACE nova.rpc.common timeout: timed out
    2012-05-07 18:14:31 TRACE nova.rpc.common
    2012-05-07 18:14:31 ERROR nova.image.s3 [req-9adeae61-dc47-48de-94d6-474ee7c27e97 ubuntu1 novaproject] Failed to decrypt ubuntu1010-bucket/maverick-server-uec-amd64-vmlinuz-virtual.manifest.xml to /tmp/tmpaqaeJK
    2012-05-07 18:14:31 TRACE nova.image.s3 Traceback (most recent call last):
    2012-05-07 18:14:31 TRACE nova.image.s3 File “/usr/lib/python2.7/dist-packages/nova/image/s3.py”, line 329, in delayed_create
    2012-05-07 18:14:31 TRACE nova.image.s3 encrypted_iv, dec_filename)
    2012-05-07 18:14:31 TRACE nova.image.s3 File “/usr/lib/python2.7/dist-packages/nova/image/s3.py”, line 383, in _decrypt_image
    2012-05-07 18:14:31 TRACE nova.image.s3 ‘%(elevated)s’
    2012-05-07 18:14:31 TRACE nova.image.s3 Error: Failed to decrypt private key: Timeout while waiting on RPC response.
    2012-05-07 18:14:31 TRACE nova.image.s3

    euca-describe-images输出
    IMAGE aki-0000000c ubuntu1010-bucket/maverick-server-uec-amd64-vmlinuz-virtual.manifest.xml failed_decrypt private x86_64 kernel instance-store
    IMAGE ami-0000000d ubuntu1010-bucket/maverick-server-uec-amd64.img.manifest.xml failed_decrypt private x86_64 machine aki-0000000c instance-store

    请教大侠是出了什么问题,非常感谢。

  28. root@ubuntu:~# kvm -m 512 -cdrom ubuntu-11.04-server-i386.iso
    open /dev/kvm: No such file or directory
    Could not initialize KVM, will disable KVM support
    这个是KVM启动不了吧,我应该装一个KVM,还是其它?望指点,非常感谢。

  29. 这个是不是由于我的CPU不支持VT?我的CPU确实不支持,是不是不能装了,该怎么办?

  30. @sujing
    CPU 不支持 VT 的话不能用 kvm 但是可以用 lxc http://www.vpsee.com/2012/01/howto-change-openstack-hypervisor/

  31. @vpsee
    我按照你的教程没有创建成功,问题还是
    failed to check for existing manifest
    failed to register …
    不知道你是否有遇到过。
    我的版本是OpenStack是Folsom,制作的镜像是ubuntu-12.04.1-server-amd64.iso。

    另外有几个问题想请教下:
    1. 为什么一定需要跳过Start的2048扇区?
    2. UUID=uec-rootfs 是必须的操作么,为什么需要替换分区表的UUID?
    3. kernel-file、ramdisk-file好像是可选上传的,那是否上传的区别是什么?

    谢谢。

  32. 麻烦问下楼主,我制作的Ubuntu桌面版和win7的镜像,都是分了10G的空间,创建实例也很正常,只是在dasboard里重启实例速度很慢,好久了还在Rebooting Hard……请问肿么回事呢??

发表评论