cloud-init开机启动,运行流程主要分获取配置参数、init-local、init、modules:config、modules:final
Cloudinit通过云平台的metadata服务或ConfigDrive等数据源拿到该userdata后,首先会对其进行切分,并分别供各模块处理。Cloud中所有模块都放在/usr/lib/python2.6/site-packages/cloudinit/config。有配置文件可知主要分为如下三大类:cloud_init_modules、cloud_config_modules、cloud_final_modules、system_info。
这里需要特别提到的一个模块是scripts-user,该模块负责执行userdata中的user scripts内容以及其他模块(如runcmd)生成的脚本,因此cloudinit的配置文件将其放在了cloud_final_modules阶段的近乎最后。
Cloud配置文件主要分为两部分:
1、参数、变量定义部分。
2、模块列表部分。
cloudinit会在虚拟机启动的过程中分四个阶段运行,按照时间顺序分为:cloud-init-local, cloud-init, cloud-config, cloud-final。
cloud-init-local阶段主要是运行本地的一些初始化脚本。cloud-init, cloud-config, cloud-final阶段分别执行配置文件中名为cloud_init_modules、cloud_config_modules、cloud_final_modules下的所有模块,如果模块列表为空,则什么都不运行。
各模块在运行时,会根据之前定义的变量/参数的值,配置虚拟机的状态。
我们现阶段采用ConfigDrive 数据源。
cloudinit.sources.DataSourceConfigDrive.DataSourceConfigDriveNet
通过数据源拿到的数据进行mount操作/dev/vdb 、 读取数据、unmount /tmp/tmpzxGmvS/openstack/
['mount', '-o', 'ro,sync', '/dev/vdb', '/tmp/tmp64NfAs']
['umount', '-l', '/tmp/tmpzxGmvS']
deleting /tmp/tmpzxGmvS
运行modules 下的所有模块。
iso9660 数据信息如下:
[root@cloud6-1 mnt]# tree /mnt/
/mnt/
├── ec2
│ ├── 2009-04-04
│ │ ├── meta-data.json
│ │ └── user-data
│ └── latest
│ ├── meta-data.json
│ └── user-data
└── openstack
├── 2012-08-10
│ ├── meta_data.json
│ └── user_data
├── 2013-04-04
│ ├── meta_data.json
│ └── user_data
├── 2013-10-17
│ ├── meta_data.json
│ ├── user_data
│ └── vendor_data.json
├── 2015-10-15
│ ├── meta_data.json
│ ├── network_data.json
│ ├── user_data
│ └── vendor_data.json
├── content
│ └── 0000
└── latest
├── meta_data.json
├── network_data.json
├── user_data
└── vendor_data.json
openstack/content/0000 :
# Injected by Nova on instance boot
#
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
hwaddress ether fa:16:3e:d9:8a:f7
address 172.30.125.132
netmask 255.255.255.0
broadcast 172.30.125.255
gateway 172.30.125.254
dns-nameservers 114.114.114.114
openstack/latest/network_data.json :
{"services": [{"type": "dns", "address": "114.114.114.114"}], "networks": [{"network_id": "5fd1389b-404f-4b9b-b269-8f6d787b9e29", "type": "ipv4", "netmask": "255.255.255.0", "link": "tape35d38eb-ec", "routes": [{"netmask": "0.0.0.0", "network": "0.0.0.0", "gateway": "192.168.125.254"}], "ip_address": "192.168.125.132", "id": "network0"}], "links": [{"ethernet_mac_address": "fa:16:3e:d9:8a:f7", "mtu": null, "type": "ovs", "id": "tape35d38eb-ec", "vif_id": "e35d38eb-ec4b-4723-80f1-c4fc8efa531c"}]}
对代码的分析主要分为 获取数据、打包数据、处理数据 三部分分析;其中获取数据和打包数据由nova代码完成,cloudinit 代码处理数据。
/usr/lib/python2.7/site-packages/nova/api/metadata/base.py
FOLSOM = '2012-08-10'
GRIZZLY = '2013-04-04'
HAVANA = '2013-10-17'
LIBERTY = '2015-10-15'
OPENSTACK_VERSIONS = [
FOLSOM,
GRIZZLY,
HAVANA,
LIBERTY,
]
VERSION = "version"
CONTENT = "content"
CONTENT_DIR = "content"
MD_JSON_NAME = "meta_data.json"
VD_JSON_NAME = "vendor_data.json"
NW_JSON_NAME = "network_data.json"
UD_NAME = "user_data"
PASS_NAME = "password"
MIME_TYPE_TEXT_PLAIN = "text/plain"
MIME_TYPE_APPLICATION_JSON = "application/json" 【打包文件目录名和文件名】
class InstanceMetadata(object):
"""Instance metadata."""
/usr/lib/python2.7/site-packages/nova/virt/configdrive.py
class ConfigDriveBuilder(object):
"""Build config drives, optionally as a context manager."""
#mkisofs_cmd = genisoimage
genisoimage -o ./yyyy.iso -ldots -allow-lowercase -allow-multidot -l -publisher ywt -quiet -J -r -V config-2 ./ywt
/usr/lib/python2.6/site-packages/cloudinit/distros/rhel.py
class Distro(distros.Distro):
# See: http://tiny.cc/6r99fw
clock_conf_fn = "/etc/sysconfig/clock"
locale_conf_fn = '/etc/sysconfig/i18n'
systemd_locale_conf_fn = '/etc/locale.conf'
network_conf_fn = "/etc/sysconfig/network"
hostname_conf_fn = "/etc/sysconfig/network"
systemd_hostname_conf_fn = "/etc/hostname"
network_script_tpl = '/etc/sysconfig/network-scripts/ifcfg-%s'
resolve_conf_fn = "/etc/resolv.conf"
tz_local_fn = "/etc/localtime"
调试方法:
正常运行后会生成相应的信号文件,文件内容是运行结束的时间戳。所以想要调试一个modules 首先要删除其相应的信号文件。
将cloudinit代码导入eclipse,并将cloud-init命令导入,为方便观察可以修改文件,自定义log输出路径。
代码目录: /usr/lib/python2.7/site-packages/cloudinit/
cloud-init命令: /usr/bin/cloud-init
log日志输出路径配置文件: /etc/cloud/cloud.cfg.d/05_logging.cfg
各个模块对应的命令:
init-local cloud-init init --local
cloud_init_modules: cloud-init init
cloud_config_modules: cloud-init modules --mode=config
cloud_final_modules: cloud-init modules --mode=final
运行单个模块: cloud-init single --name set_hostname
根据调试需求修改命令参数:
在主函数 main() 打断点开始调试。
/usr/lib/python2.7/site-packages/cloudinit/distros/rhel_util.py 【工具文件】
/usr/lib/python2.7/site-packages/cloudinit/distros/parsers/resolv_conf.py 【解析文件】
/usr/lib/python2.7/site-packages/cloudinit/util.py 【写文件】