虚拟机模板信息注入解决方案

需求:需要向Windows虚拟机模板镜像中写入特定的信息

写这篇帖子的前提是,当前已经实现了密码和主机名称的注入,密码和主机名称的注入使用的是CloudBaseInit,该方法使用的是远端服务器上设置的数据进行初始化操作对于初始化单一机器的密码很好用,但是对于一个云平台来说会有很多个虚拟主机,所以就要求每个实例有自己特有的密码,不能再使用通用镜像模板进行处理,需要在初始化密码之前给模板镜像提供具体的实例信息,比如uuid用来区分实例的归属。有了实例的归属信息,我们去服务器请求密码和其他信息就简单的多了,下面就是围绕这个需求进行的;有什么写的不对的地方欢迎吐嘈

 

 

网上查找了些资料有多种方法,下面简单列一下在文章最后就我自己的做法进行详细说明,希望对大家能有帮助,这部分的内容查找资料耗费的很多时间

1、直接挂载虚拟机镜像,写入文件

     raw文件可以使用 kpartx 就行挂载

     qcow2文件可以使用qemu-nbd工具

2、libguestfs   

  libguestfs 是一组 Linux 下的 C 语言的 API ,用来访问虚拟机的 磁盘映像文件。支持的文件系统包括 : all known types of Linux filesystem (ext2/3/4, XFS, btrfs, etc.), any Windows filesystem (VFAT and NTFS), any Mac OS X and BSD filesystems, LVM2    volumes, MBR and GPT disk partitions, raw disks, qcow2, CD and DVD ISO images, SD cards, and dozens more. libguestfs 不需要 root权限。

     Centos源里边有这个工具 yum install  libguestfs  libguestfs-tools (但是我发现centos6 没有guestfsd的源)

     Ubuntu安装sudo apt-get install libguestfs-tools

     libguestfs主要有三个大的部分:guestfsd,guestfs-lib,guestfish。 
     其中,guestfsd是一个 daemon,libguestfs是一个 lib,guestfish是一个命令行的工具。 

    guestfsd是一个daemon,但是它不是运行在 host上的 daemon,它运行在 guest上,而在宿主机上建立一个本地的unix socket和虚拟机通信,所使用的技术就是我下边要介绍的技术,channel技术(下边详细介绍)

    guestfs还有其他的一些命令行工具如:

    virt-cat 查看虚拟机镜像里的文件

    virt-copy-in 向虚拟机镜像里 拷贝文件

    virt-df 查看虚拟机镜像硬盘使用率

   详细的信息可以去 http://libguestfs.org/ 去查看

   这种方法的优点是几乎兼容所有的虚拟机镜像文件格式,而且通过guestfsd 可以完成在线的文件注入等功能(不过目前测试还有些问题,比如不支持 centos,ubuntu上倒是可以,需要进一步研究测试)。

 

3、qemu的channel

      它的大概原理是,在虚拟机中产生一个字符设备,然后宿主机上产生一个本地unix socket 这样 你就可以和socket建立通信,来完成对虚拟机的一些操作。

      虚拟机的xml文件要进行如下配置:

  

<channel type='unix'>
     <source mode='bind' path='/var/lib/libvirt/qemu/centos6.4-1.agent'/>
     <target type='virtio' name='org.qemu.guest_agent.0'/>
     <address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>

 

     这样就会在宿主机的/var/lib /libvirt/qemu/目录下生成一个centos6.4-1.agent socket文件,而在虚拟机的/dev/virtio-serial/下会生成一个名为org.qemu.guest_agent.0字符设 备,qemu有个工具,

     qemu-ga它可以跑在虚拟机里边,能够实现简单的文件读写等功能,数据的传输格式为json,而且数据是base64加密的。这种方式的优势是不需要网络,就能实现在线的文件注入。

      缺点是要在虚拟机的内部运行agent,而且要对qemu-ga进行二次开发(青云就是使用这种方式)

 

4、cloud-init

     cloudinit 是专为云环境中虚拟机的初始化而开发的工具,它从各种数据源读取相关数据并据此对虚拟机进行配置。常见的数据源包括:云平台的metadata服务、

     ConfigDrive等,常见的配置包括:设定虚拟机的hostname、hosts文件、设定用户名密码、更新  apt -get的本地缓存等。

     它的大概原理 就是开机后去数据源服务器(或configDrive)上去拿用户数据,然后进行配置,这里介绍一下这两种元数据获取的方式:

     1)元数据服务器

     在openstack中可以看到,获取metadata的api接口类似是:

   http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key

    可是,这个IP地址,在我们 openstack 是不存在的。为什么可以获取到metadata呢?

    这是由于Amazon的原因,最早metadata是亚马逊提出来的,参见:

  http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html

    后 来很多人给亚马逊定制了一些操作系统的镜像,比如 ubuntu, fedora, centos 等等,而且将里面获取 metadta 的api地址也写死了。所以opentack为了兼容,保留了这个地址 169.254.169.254。然后通过iptables nat映射到真实的api上:

 

     iptables -A nova-network-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.4:8775

 

      使用metadata会带来便利,但是经常碰到的一个问题是,metadata获取不成功,导致instance启动很慢,并且获取失败会导致ssh key等功能设置失效,刚才获取ssh的代码片段中,就是尝试10次。

 

 

###############华丽的分割线###################

下面就读我自己使用的接解决方案进行说明,我这边主要使用了libguestfs   和CloudBaseInit for Windows

(1) virt-ls  用来显示镜像中文件和目录列表这个类似于linux命令 ls

     lists filenames, file sizes, checksums, extended attributes and more from a virtual machine or disk image.

     Multiple directory names can be given, in which case the output from each is concatenated.

    查看下镜像文件,选定一个目录用来存放要注入的文件,这里我选择Cloudbase-Init/conf的配置文件目录,使用命令后会

   列出指定目录下面的所有文件和文件夹

//查看文件列表
sudo virt-ls -a win2003_test.img /"Program Files/Cloudbase Solutions/Cloudbase-Init/conf" -l

 

(2) virt-cat 查看镜像里面文件的内容  类似于linux命令 cat

   virt-cat is a command line tool to display the contents of file where file exists in the named virtual machine (or disk image).

//查看cloudbase-init.conf的内容
sudo virt-cat -a win2003_test.img /"Program Files/Cloudbase Solutions/Cloudbase-Init/conf/cloudbase-init.conf"

 

(3) virt-copy-in  把本地文件拷贝到镜像文件的指定目录

   virt-copy-in copies files and directories from the local disk into a virtual machine disk image or named libvirt domain.

 

//把当前目录下的test.xml拷贝到镜像win2003.img 中的Program Files/Cloudbase Solutions/Cloudbase-Init/conf目录下
 sudo virt-copy-in -a win2003_test.img test.xml  /"Program Files/Cloudbase Solutions/Cloudbase-Init/conf" 


当我们拷贝完成后,启动虚拟机在目录conf下就可以看到文件test.xml。比如我们把实例的唯一标识注入到镜像文件中,镜像文件中启动的时候

可以通过实例的唯一标识从远端服务器获得主机名称和密码使用cloudBaseInit就可以初始化密码

 

CloudBaseInit的使用参考 kvm小计

 

后记:

通过查询资料发现对于镜像文件的控制处理libguestfs是很好用的方法,这部分有空可以多关注下,文档写的也很直观

 

参考:

http://5lexin.com/blog/view/499/%E5%85%B3%E4%BA%8Ekvm%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%BF%A1%E6%81%AF%E6%B3%A8%E5%85%A5%E7%9A%84%E6%96%B9%E6%B3%95%E7%A0%94%E7%A9%B6

http://libguestfs.org/

posted @ 2015-06-19 15:17  davygeek  阅读(1695)  评论(0编辑  收藏  举报