cloud-init学习笔记
现在无论是公有云还是私有云,虚拟机还是裸金属,在交付过程中或多或少总有很多定制化的需求,比如密码定制,磁盘挂载,agent启动等等。有些场景可以将定制化的需求放在镜像内,但对于一些业务种类,规模较多的场景来说,频繁更新镜像并不是一个好事情,cloud-init 的方式就会比较合理,通过启动时候注入的方式,完成了主机的初始化,且就目前来说,cloud-init已经成为了云主机初始化的一个行业标准,并
背景
现在无论是公有云还是私有云,虚拟机还是裸金属,在交付过程中或多或少总有很多定制化的需求,比如密码定制,磁盘挂载,agent启动等等。有些场景可以将定制化的需求放在镜像内,但对于一些业务种类,规模较多的场景来说,频繁更新镜像并不是一个好事情,cloud-init 的方式就会比较合理,通过启动时候注入的方式,完成了主机的初始化,且就目前来说,cloud-init已经成为了云主机初始化的一个行业标准,并几乎适用于所有主流的Linux发行版。
关键词
- metadata:一系列字典格式的元数据,用作模板渲染、模块运行等等。
- userdata:启动实例时用户能够指定的数据(单实例数据)。
- vendordata:云基座传入的数据(全局数据)。
- datasource: 用于获取元数据的地方。
以openstack为例,上述的metadata, userdata,可以在用户创建虚拟机的时候基于参数传入,而vendordata则由nova-api-metadata服务启动时指定。
启动顺序
和linux启动顺序类似,cloud-init启动也分为5个阶段,分别是Generator->Local->Network->Config->Final。
其服务基于systemd进行管理,所以每个阶段都可以找到对应的service的systemd的配置文件,并且通过systemd来控制启动顺序。
Generator
- 启动文件位置: /usr/lib/systemd/system-generators/cloud-init-generator
其本质上就是一个shell脚本,用于做两件事,分别是判断是否启动cloud-init,以及选择可用的数据源,截取了2段脚本内的函数:
- generator先通过读取cmdline,判断是否存在cloud-init=disabled的选项,如果存在,则不启动,此外会判断/etc/cloud/cloud-init.disabled文件是否存在,同理,如果存在,则不启动。
local search result="error" ret=""
for search in kernel_cmdline etc_file default; do
if $search; then
debug 1 "$search found $_RET"
[ "$_RET" = "$ENABLE" -o "$_RET" = "$DISABLE" ] &&
result=$_RET && break
else
ret=$?
debug 0 "search $search returned $ret"
fi
done
# enable AND ds=found == enable
# enable AND ds=notfound == disable
# disable || <any> == disabled
if [ "$result" = "$ENABLE" ]; then
debug 1 "checking for datasource"
check_for_datasource
ds=$_RET
if [ "$ds" = "$NOTFOUND" ]; then
debug 1 "cloud-init is enabled but no datasource found, disabling"
result="$DISABLE"
fi
fi
if [ "$result" = "$ENABLE" ]; then
if [ -e "$link_path" ]; then
debug 1 "already enabled: no change needed"
else
[ -d "${link_path%/*}" ] || mkdir -p "${link_path%/*}" ||
debug 0 "failed to make dir $link_path"
if ln -snf "$CLOUD_SYSTEM_TARGET" "$link_path"; then
debug 1 "enabled via $link_path -> $CLOUD_SYSTEM_TARGET"
else
ret=$?
debug 0 "[$ret] enable failed:" \
"ln $CLOUD_SYSTEM_TARGET $link_path"
fi
fi
: > "$RUN_ENABLED_FILE"
elif [ "$result" = "$DISABLE" ]; then
if [ -f "$link_path" ]; then
if rm -f "$link_path"; then
debug 1 "disabled. removed existing $link_path"
else
ret=$?
debug 0 "[$ret] disable failed, remove $link_path"
fi
else
debug 1 "already disabled: no change needed [no $link_path]"
fi
if [ -e "$RUN_ENABLED_FILE" ]; then
rm -f "$RUN_ENABLED_FILE"
fi
else
debug 0 "unexpected result '$result' 'ds=$ds'"
ret=3
fi
return $ret
}
- 基于/usr/libexec/cloud-init/ds-identify的策略, 进行源的datasource的选择, 将可用的datasource写入/run/cloud-init/cloud.cfg 内。
check_for_datasource() {
local ds_rc=""
local dsidentify="/usr/libexec/cloud-init/ds-identify"
if [ ! -x "$dsidentify" ]; then
debug 1 "no ds-identify in $dsidentify. _RET=$FOUND"
return 0
fi
$dsidentify
ds_rc=$?
debug 1 "ds-identify rc=$ds_rc"
if [ "$ds_rc" = "0" ]; then
_RET="$FOUND"
debug 1 "ds-identify _RET=$_RET"
return 0
fi
_RET="$NOTFOUND"
debug 1 "ds-identify _RET=$_RET"
return 1
}
Local
- 启动文件位置: /usr/lib/systemd/system/cloud-init-local.service
Local启动需要在文件系统挂载之后,网络服务启动之前进行:
After=systemd-remount-fs.service
Before=NetworkManager.service
Before=network-pre.target
Before=shutdown.target
RequiresMountsFor=/var/lib/cloud
在Local阶段,cloud-init主要会通过以下三种方式进行网络配置(仅做配置,不拉起网络服务):
- 通过元数据配置网络
- 通过cloud-init 配置"dhcp on eth0"
- 禁止配置网络
Network
- 启动文件位置:/usr/lib/systemd/system/cloud-init.service
cloud-init的网络服务,在网络服务启动之后启动,该阶段用于网络启动后再次更新数据源,然后渲染userdata和vendor_data,以及执行该阶段下的模块。
Wants=cloud-init-local.service
Wants=sshd-keygen.service
Wants=sshd.service
After=cloud-init-local.service
After=systemd-networkd-wait-online.service
After=network.service
Before=network-online.target
Before=sshd-keygen.service
Before=sshd.service
Before=systemd-user-sessions.service
该阶段和上述2个阶段不同,该阶段下存在很多可执行模块,默认的可执行模块可以在cloud.cfg中找到,即:cloud_init_modules:
cloud_init_modules:
- migrator
- source-address
- pip-source
- seed_random
- bootcmd
- write-files
- [ growpart, once-per-instance ]
- [ resizefs, once-per-instance ]
- disk_setup
- mounts
- set_hostname
- update_hostname
- update_etc_hosts
- ca-certs
- rsyslog
- users-groups
- ssh
可以看到,该步骤下存在多个模块,比如修改主机名,启动syslog等等
Config
- 启动文件位置:/usr/lib/systemd/system/cloud-config.service
该阶段启动在Network阶段之后,该阶段下同样存在很多可执行模块,默认的可执行模块可以在cloud.cfg中找到,即:cloud_config_modules, 主要包含一些系统配置,如ssh, yum源,时区等。
# The modules that run in the 'config' stage
cloud_config_modules:
- ssh-import-id
- locale
- set-passwords
- spacewalk
- yum-add-repo
- ntp
- timezone
- disable-ec2-metadata
- runcmd
# - ntp-conf
# - chrony-conf
Final
- 启动文件位置:/usr/lib/systemd/system/cloud-final.service
该阶段启动在Config阶段之后,该阶段的主要功能是运行cloud_final_modules中配置的模块,如一些用户脚本,个人服务等。
# The modules that run in the 'final' stage
cloud_final_modules:
- package-update-upgrade-install
- puppet
- chef
- mcollective
- salt-minion
- 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
模块
初始化服务器的任务均以模块化进行,每个模块包含名称、运行频率、配置参数这三大要素。
- 模块名称: 用于识别该模块。
- 运行频率: 表示一个模块可以在什么时候执行,主要分为两种: once-per-instance(首次启动时执行),always(每次启动都执行)。
- 配置参数: 类似一个全局变量,在配置文件头部定义,用于描述如何运行各类模块。
常用命令
调试相关
# 手动初始化local阶段
cloud-init init --local
# 手动初始化network阶段
cloud-init init
# 手动初始化config阶段
cloud-init modules --mode=config
# 手动初始化final阶段
cloud-init modules --mode=final
# 还原所有cloud-init配置并重启
cloud-init clean -r
查询相关
# 查询cloud-id
cloud-id
# 查询cloud-init执行状态
cloud-init status -l
# 查询可用的metadata
cloud-init query -l
# 查询指定的metadata信息
cloud-init query $name
更多推荐
所有评论(0)