简单说明一下,openstack创建虚拟机内幕!
实例的实际创建过程是通过调用libvirt函数来完成,在virt/Libvirt/driver.py中spawn方法来完成真正的虚拟机创建过程。 1 def spawn(self, context, instance, image_meta, injected_files, 2 admin_password, network_info=None, block_device_info=None): 3 disk_info = blockinfo.get_disk_info(CONF.libvirt_type, 4 instance, 5 block_device_info, 6 image_meta) 7 xml = self.to_xml(instance, network_info, 8 disk_info, image_meta, 9 block_device_info=block_device_info) 10 11 self._create_image(context, instance, xml, 12 disk_info['mapping'], 13 network_info=network_info, 14 block_device_info=block_device_info, 15 files=injected_files, 16 admin_pass=admin_password) 17 18 self._create_domain_and_network(xml, instance, network_info, 19 block_device_info) 20 LOG.debug(_("Instance is running"), instance=instance) 21 22 def _wait_for_boot(): 23 """Called at an interval until the VM is running.""" 24 state = self.get_info(instance)['state'] 25 26 if state == power_state.RUNNING: 27 LOG.info(_("Instance spawned successfully."), 28 instance=instance) 29 raise utils.LoopingCallDone() 30 31 timer = utils.FixedIntervalLoopingCall(_wait_for_boot) 32 timer.start(interval=0.5).wait() to_xml就是利用传过来的各种参数,来构造libvirt用来创建虚拟机的xml文件,其中_create_image函数比较的复杂呢,里边处理了和镜像相关的相关逻辑,如从glance中下载各种类型的所需的文件,并进行备份,将备份的文件考入实例对应的目录下作为实例实际的disk。 其中有几个非常重要的目录,系统的CONF.instances_path,也就是和实例相关的目录,实例所用到的文件都在此目录下,常见的目录是/var/lib/nova/instances,
查看目录文件:
. ├── _base │ ├── 0f7c4295-d5e8-41a3-bc1a-79c99aa0f8f5 │ ├── 5f44ef07-3990-4207-a909-40d66157a21f │ ├── 6841da6ee6638fb19178e74819c0edc08209259c │ └── 6841da6ee6638fb19178e74819c0edc08209259c_20 ├── instance-00000042 │ ├── console.log │ ├── disk │ ├── kernel │ ├── libvirt.xml │ └── ramdisk └── snapshots
其中_base目录下存放着备份或者说缓存的镜像文件,snapshots放的是快照文件instance-xxxxx里边放的就是对应实例的相关文件console.log代表实例输出的日志,libvirt.xml就是libvirt用来生成实例的文件,disk就是对应实例的文件。关于_base目录要说的一点是。manager中有一个定时方法_run_image_cache_manager_pass定期清除同glance不相关的和超过配置文件中定义的时间的缓存。 对于镜像的处理策略是,镜像从glance服务器上下载到_base目录,镜像的名字变为他的image_id的sha1 hash形式,如果镜像支持CoW,那么就会将镜像变为实例配置的大小,如果不支持CoW,就直接将镜像拷贝到实例对应的目录中,我想这就可以解释为什么会出现配置的硬盘大小同实际实例中的大小不一致的一个原因,另一个原因就是配置的镜像小于glance中的实际镜像,程序会直接忽略配置信息。最终libvirt就是根据xml文件给定参数信息,创建虚拟机。其中xml文件内容如下:
<domain type="qemu">
<uuid>9b2ca68e-0628-487b-9e01-0dfd53e006ac</uuid>
<name>instance-00000042</name>
<memory>2097152</memory>
<vcpu>1</vcpu>
<blkiotune>
<device>
<path>/dev/vda</path>
<weight>100</weight>
</device>
</blkiotune>
<os>
<type>hvm</type>
<kernel>/opt/stack/data/nova/instances/instance-00000042/kernel</kernel>
<initrd>/opt/stack/data/nova/instances/instance-00000042/ramdisk</initrd>
<cmdline>root=/dev/vda console=ttyS0</cmdline>
</os>
<features>
<acpi/>
</features>
<clock offset="utc"/>
<devices>
<disk type="file" device="disk">
<driver name="qemu" type="qcow2" cache="none"/> #镜像格式
<source file="/opt/stack/data/nova/instances/instance-00000042/disk"/>
<target bus="virtio" dev="vda"/>
</disk>
<interface type="bridge">
<mac address="fa:16:3e:66:7f:24"/>
<source bridge="br100"/>
<filterref filter="nova-instance-instance-00000042-fa163e667f24">
<parameter name="IP" value="10.0.0.2"/>
<parameter name="DHCPSERVER" value="10.0.0.1"/>
<parameter name="PROJNET" value="10.0.0.0"/>
<parameter name="PROJMASK" value="255.255.255.0"/>
</filterref>
</interface>
<serial type="file">
<source path="/opt/stack/data/nova/instances/instance-00000042/console.log"/>
</serial>
<serial type="pty"/>
<input type="tablet" bus="usb"/>
<graphics type="vnc" autoport="yes" keymap="en-us" listen="127.0.0.1"/>
</devices>
</domain>
打算后期总结一下多种格式镜像的差异,性能。。。。。