別以爲真懂Openstack: 虛擬機創建的50個步驟和100個知識點(3)

四、Nova-compute

image

步驟17:nova-compute接收到請求後,通過Resource Tracker將創建虛擬機所需要的資源聲明佔用

步驟18:調用Neutron API配置Network,虛擬機處於Networking的狀態

需要注意的是,這一步雖然是配置Network,但是主要是數據結構的準備,真正的設備並沒有創建。

由於在創建虛擬機的時候,我們指定了將虛擬機放到哪個private network裏面,因而在創建真正的設備之前,所有的信息都需要準備好。

這裏的知識點設計Network的創建,然而這一步其實在虛擬機創建之前就應該做好。

一個最簡單的場景是通過下面的腳本創建網絡

#!/bin/bash
TENANT_NAME="openstack"
TENANT_NETWORK_NAME="openstack-net"
TENANT_SUBNET_NAME="${TENANT_NETWORK_NAME}-subnet"
TENANT_ROUTER_NAME="openstack-router"
FIXED_RANGE="192.168.0.0/24"
NETWORK_GATEWAY="192.168.0.1"

PUBLIC_GATEWAY="172.24.1.1"
PUBLIC_RANGE="172.24.1.0/24"
PUBLIC_START="172.24.1.100"
PUBLIC_END="172.24.1.200"

TENANT_ID=$(keystone tenant-list | grep " $TENANT_NAME " | awk '{print $2}')

(1) TENANT_NET_ID=$(neutron net-create --tenant_id $TENANT_ID $TENANT_NETWORK_NAME --provider:network_type gre --provider:segmentation_id 1 | grep " id " | awk '{print $4}')

(2) TENANT_SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 --name $TENANT_SUBNET_NAME $TENANT_NET_ID $FIXED_RANGE --gateway $NETWORK_GATEWAY --dns_nameservers list=true 8.8.8.8 | grep " id " | awk '{print $4}')

(3) ROUTER_ID=$(neutron router-create --tenant_id $TENANT_ID $TENANT_ROUTER_NAME | grep " id " | awk '{print $4}')

(4) neutron router-interface-add $ROUTER_ID $TENANT_SUBNET_ID

(5) neutron net-create public --router:external=True

(6) neutron subnet-create --ip_version 4 --gateway $PUBLIC_GATEWAY public $PUBLIC_RANGE --allocation-pool start=$PUBLIC_START,end=$PUBLIC_END --disable-dhcp --name public-subnet

(7) neutron router-gateway-set ${TENANT_ROUTER_NAME} public

create network

  1. 爲這個Tenant創建一個private network,不同的private network是需要通過VLAN tagging進行隔離的,互相之間broadcast不能到達,這裏我們用的是GRE模式,也需要一個類似VLAN ID的東西,稱爲Segment ID

  2. 創建一個private network的subnet,subnet纔是真正配置IP網段的地方,對於私網,我們常常用192.168.0.0/24這個網段

  3. 爲這個Tenant創建一個Router,才能夠訪問外網

  4. 將private network連接到Router上

  5. 創建一個External Network

  6. 創建一個Exernal Network的Subnet,這個外網邏輯上代表了我們數據中心的物理網絡,通過這個物理網絡,我們可以訪問外網。因而PUBLIC_GATEWAY應該設爲數據中心裏面的Gateway, PUBLIC_RANGE也應該和數據中心的物理網絡的CIDR一致,否則連不通,而之所以設置PUBLIC_START和PUBLIC_END,是因爲在數據中心中,不可能所有的IP地址都給Openstack使用,另外可能搭建了VMware Vcenter,可能有物理機器,僅僅分配一個區間給Openstack來用。

  7. 將Router連接到External Network

經過這個流程,從虛擬網絡,到物理網絡就邏輯上聯通了。

然而真正的創建底層的設備,卻是通過具體的命令來的,本人總結了一下:

neutron創建network執行的那些命令 

當然還有更復雜的場景,參考這篇文章

多個router和多個network 

步驟19:生成MAC Address

步驟20: 獲取DHCP Server的配置

步驟21:獲取Network的信息

步驟22:獲取Security Group的信息

步驟23:拿着所有的信息,創建Port對象,是一個Tap device,當然真正的設備還沒有創建

步驟24:調用Libvirt Driver創建虛擬機

五、Image

image

在創建Instance之前,當然需要Image,Image後來發現是一個大學問。

在Openstack裏面,對於KVM,應用到的Image格式主要是兩種RAW和qcow2,

raw格式簡單,容易轉換爲其他的格式。需要文件系統的支持才能支持sparse file,性能相對較高。

qcow2是動態的,相對於raw來說,有下列的好處:

  • 即便文件系統不支持sparse file,文件大小也很小

  • Copy on write

  • Snapshot

  • 壓縮

  • 加密

具體的格式和特點,參考下面的文章

QEMU KVM libvirt手冊(4) – images

[轉] The QCOW2 Image Format

創建一個image,有多種方法

一種方法是通過virt-install,講hard disk設爲一個image文件, 從CDROM啓動一個虛擬機,按照正常的安裝流程來,最後操作系統安裝好,image再經過qemu-img進行處理,壓縮,最終形成image。

參考文章

QEMU KVM libvirt 手冊(1) 

當然現在有了更先進的方法,就是libguestfs,它可以輕鬆基於已有版本的image創建一個你想要的image,就是virt-builder

參考文章

libguestfs手冊(3): virt命令 

當然一個可以在Openstack裏面使用的image,絕不是僅僅安裝一個操作系統那麼簡單。

OpenStack Virtual Machine Image Guide中詳細寫了一個Linux Image的各種需求

  • Disk partitions and resize root partition on boot (cloud-init)

  • No hard-coded MAC address information

  • Ensure ssh server runs

  • Disable firewall

  • Access instance by using ssh public key (cloud-init)

  • Use cloud-init to fetch the public key

  • Process user data and other metadata (cloud-init)

  • Ensure image writes boot log to console

另外加幾條:

  • 包含MBR和bootloader,可以自啓動

  • 支持virtio的disk和network driver

  • 使用DHCP分配IP

當一個Linux的Image安裝完畢後,總要測試一下:

  • 能通過key ssh上去嗎

  • 能夠文件注入嗎

  • cloud-init是否運行了

  • 文件系統被resize爲flavor大小了嗎

  • hostname設爲文件名嗎

  • timezone設的對嗎

  • /etc/fstab乾淨正確嗎

  • 虛擬機的log被正確輸出了嗎

  • /tmp路徑下乾淨嗎

  • 能打snapshot嗎

  • block storage添加後能正常看到和使用嗎

對於windows image,卻要複雜的多,windows真的不是對cloud友好的。

  • 首先必須用virt-install將windows系統安裝好。

  • windows要想使用virtio,就必須將windows版本的virtio安裝好。即便安裝好,還要在device manager裏面update driver纔好。

  • Remote Access要打開,要不怎麼遠程桌面啊。

  • 安裝一個SSH Server吧,有時候需要創建虛擬機後,自動執行腳本安裝東西,不能通過遠程桌面來。

  • 安裝windows版本的cloud-init cloudbase-init

  • 別忘了運行windows update來更新windows,否則會有很多安全漏洞。

  • 在device manager裏面添加一個serial console的device

  • windows的硬盤佔用通常很大,運行一下disk cleanup tool可以清空一些硬盤。

  • 微軟有一個SDelete工具,可以講未分配的空間設爲0,從而可以壓縮硬盤。

  • 別忘了License問題。

  • 有時候windows配置網絡的時候,會彈出對話框,這是家庭網絡,工作網絡,還是公共網絡?這會使得網絡配置死在哪裏,在註冊表裏幹掉他。

  • 運行sysprep

對於cloud-init,參考下面的文章

http://cloudinit.readthedocs.org/en/latest/index.html

http://www.scalehorizontally.com/2013/02/24/introduction-to-cloud-init/

在ubuntu中,cloud-init主要包括

配置文件在/etc/cloud下面,默認的cloud.cfg如下

root@dfasdfsdafasdf:/etc/cloud# cat cloud.cfg
# The top level settings are used as module
# and system configuration.

# A set of users which may be applied and/or used by various modules
# when a 'default' entry is found it will reference the 'default_user'
# from the distro configuration specified below
users:
   - default

# If this is set, 'root' will not be able to ssh in and they 
# will get a message to login instead as the above $user (ubuntu)
disable_root: true

# This will cause the set+update hostname module to not operate (if true)
preserve_hostname: false

# Example datasource config
# datasource: 
#    Ec2: 
#      metadata_urls: [ 'blah.com' ]
#      timeout: 5 # (defaults to 50 seconds)
#      max_wait: 10 # (defaults to 120 seconds)

# The modules that run in the 'init' stage
cloud_init_modules:
- migrator
- seed_random
- bootcmd
- write-files
- growpart
- resizefs
- set_hostname
- update_hostname
- update_etc_hosts
- ca-certs
- rsyslog
- users-groups
- ssh

# The modules that run in the 'config' stage
cloud_config_modules:
# Emit the cloud config ready event
# this can be used by upstart jobs for 'start on cloud-config'.
- emit_upstart
- disk_setup
- mounts
- ssh-import-id
- locale
- set-passwords
- grub-dpkg
- apt-pipelining
- apt-configure
- package-update-upgrade-install
- landscape
- timezone
- puppet
- chef
- salt-minion
- mcollective
- disable-ec2-metadata
- runcmd
- byobu

# The modules that run in the 'final' stage
cloud_final_modules:
- rightscale_userdata
- scripts-vendor
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- ssh-authkey-fingerprints
- keys-to-console
- phone-home
- final-message
- power-state-change

# System and/or distro specific settings
# (not accessible to handlers/transforms)
system_info:
   # This will affect which distro class gets used
   distro: ubuntu
   # Default user name + that default users groups (if added/used)
   default_user:
     name: ubuntu
     lock_passwd: True
     gecos: Ubuntu
     groups: [adm, audio, cdrom, dialout, dip, floppy, netdev, plugdev, sudo, video]
     sudo: ["ALL=(ALL) NOPASSWD:ALL"]
     shell: /bin/bash
   # Other config here will be given to the distro class and/or path classes
   paths:
      cloud_dir: /var/lib/cloud/
      templates_dir: /etc/cloud/templates/
      upstart_dir: /etc/init/
   package_mirrors:
     - arches: [i386, amd64]
       failsafe:
         primary: http://archive.ubuntu.com/ubuntu
         security: http://security.ubuntu.com/ubuntu
       search:
         primary:
           - http://%(ec2_region)s.ec2.archive.ubuntu.com/ubuntu/
           - http://%(availability_zone)s.clouds.archive.ubuntu.com/ubuntu/
         security: []
     - arches: [armhf, armel, default]
       failsafe:
         primary: http://ports.ubuntu.com/ubuntu-ports
         security: http://ports.ubuntu.com/ubuntu-ports
   ssh_svcname: ssh

工作文件夾在/var/lib/cloud

root@dfasdfsdafasdf:/var/lib/cloud/instance# ls
boot-finished     datasource  obj.pkl  sem            user-data.txt.i  vendor-data.txt.i
cloud-config.txt  handlers    scripts  user-data.txt  vendor-data.txt

另外就是cloud-init的命令

/usr/bin/cloud-init

如果我們打開它,發現他是python文件,如果運行/usr/bin/cloud-init init,則會運行cloud_init_modules:下面的模塊,我們以resizefs爲例子

/usr/bin/cloud-init 中會調用main_init,裏面會調用run_module_section

這就調用到python代碼裏面去了,所以cloud-init另一個部分就是python代碼部分

/usr/lib/python2.7/dist-packages/cloudinit

我們發現裏面有這個文件/usr/lib/python2.7/dist-packages/cloudinit/config/cc_resizefs.py

裏面是

def _resize_btrfs(mount_point, devpth):  # pylint: disable=W0613
    return ('btrfs', 'filesystem', 'resize', 'max', mount_point)

def _resize_ext(mount_point, devpth):  # pylint: disable=W0613
    return ('resize2fs', devpth)

def _resize_xfs(mount_point, devpth):  # pylint: disable=W0613
    return ('xfs_growfs', devpth)

def _resize_ufs(mount_point, devpth):  # pylint: disable=W0613
    return ('growfs', devpth)

哈哈,終於找到resize的根源了。

說完了創建image,還需要了解修改image,我們的文件注入,就是對image的修改。

有三種方式:通過mount一個loop device,通過qemu的network block device,或者最先進的,通過libguestfs

總結成了一篇文章

如何修改image文件 

對於qemu-nbd,有文章

QEMU KVM Libvirt手冊(6) – Network Block Device 

對於libguestfs,我也寫了一些筆記

 

libguestfs手冊(1): 架構

libguestfs手冊(2):guestfish command

libguestfs手冊(3): virt命令

對於文件注入,有文章

nova file injection 

對於如何打snapshot,分多種,有文章

QEMU KVM Libvirt手冊(5) – snapshots 

Snapshot Types

External Snapshot management

[轉] External(and Live) snapshots with libvirt

[轉] Snapshotting with libvirt for qcow2 images

步驟26:從Glance下載Image,作爲base

步驟27:基於base image,創建qcow2的image

步驟28:resize image的大小,和filesystem的大小無關

步驟29:配置configuration drive

步驟30:配置文件注入


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章