Cloud-init
cloud-init is a software package that automates the initialization of cloud instances during system boot.
cloud-init 这个软件是安装在 Guest OS 里面的。同时也是负责 Guest OS 里面组件的初始化工作。但是要运行的配置是我们从宿主机上传进去的。
cloud-init 脚本在每次 guest 重启的时候都会运行。 cloud-init 的服务端是 ad hoc 的方式实现的,各个云厂商都有自己的服务实现方式,并没有一个统一的工具来实现。
公共镜像和自定义镜像里都有 cloud-init 组件吗?
CloudInit 组件是在 guest(云主机)里面 ,主要用于 云主机启动时的初始化操作 ,负责安装和启动 Kubernetes 依赖组件。CloudInit 是注入到云主机(guest)的启动脚本,运行在用户集群的节点(即云主机)内部。
查看 cloud-init 有没有运行成功:
# Guest OS 里运行
cloud-init status --wait
- The standard for customising cloud instances
canonical/cloud-init: Official upstream for the cloud-init: cloud instance initialization
Documentation: cloud-init 25.1.2 documentation
cloud-init 的 4 个主要阶段(按执行顺序)
- init-local
- 在系统启动的早期执行(非常早,在网络启动前)。
- 主要任务:识别 cloud datasource(比如 ConfigDrive、IMDS、VolcStack 等),配置本地磁盘等。
- init
- 配置网络、主机名、SSH key、用户等基础内容。
- 会执行 /etc/cloud/cloud.cfg 里的 cloud_init_modules。
- config
- 执行 /etc/cloud/cloud.cfg 中定义的 cloud_config_modules。
- 这里常见的任务有:写文件、设置包管理、更新系统、设置用户、时区、apt 源等。
- final(也叫 modules-final) ✅
- 执行 /etc/cloud/cloud.cfg 中的 cloud_final_modules 列表。
- 通常是最后阶段,执行用户自定义脚本和指令,比如:
- /var/lib/cloud/scripts/per-boot/
- /var/lib/cloud/scripts/per-instance/
- /var/lib/cloud/scripts/per-once/
- runcmd(用户在 cloud-config 里写的命令)
- scripts-user(用户数据中的脚本)
- 这是 用户定义步骤最常出现的地方。
# 检查当前状态,如果是 Running 就是还在跑着
sudo cloud-init status --long
# 查看运行到哪一步了。
tail -f /var/log/cloud-init.log
# 重新跑一遍
sudo cloud-init clean
sudo cloud-init init
sudo cloud-init modules --mode=config
sudo cloud-init modules --mode=final
| 阶段 | 描述 | 执行脚本目录 |
|---|---|---|
| init | 初始化网络、主机名、SSH key 等 | /var/lib/cloud/instance/scripts/init/ |
| config | 安装包、写文件、配置服务 | /var/lib/cloud/instance/scripts/config/ |
| final | 用户脚本 (runcmd 等) 最终执行 |
/var/lib/cloud/instance/scripts/per-boot/ |
Bootcmd 第一次装系统时没有生效,但是在后续启动时生效了
检查一下 /etc/cloud/cloud.cfg 这个文件。看一下启动顺序,如果 bootcmd 在 write-files 前面,那么可能是因为先执行了 bootcmd,此时还没有任何从 metadata server 上拉下来的 scripts,再执行了 write-files,此时才把 bootcmd 的脚本放到了对应的位置,这也是为什么第二次 boot 的时候生效了,因为这个时候就有了。
解决方式是吧 bootcmd 的内容也加入到 runcmd 中去,因为 runcmd 在 write-files 后面。
Cloud-init module frequency
有三档:
- always:每次 boot 都会运行;
- instance:每个实例第一次创建的时候,都会运行一次;
- once:如果基于这个镜像创建来一个实例,并且运行了一次,那么后面基于这个镜像克隆出来的其他实例也不会再运行了,频率更低。
如何查看每一个 module 的 frequency:
- 可以直接看 log:
grep "Running module" /var/log/cloud-init.log。 - 这里有每一个模块的默认频率:Modules — cloud-init 21.2 documentation
-
bootcmd: always -
runcmd: once-per-instance
-
Cloud-init stages and modules
从下面能看出来,一共有四个 stage,每一个 stage 都有不同的 modules。
# cat /etc/cloud/cloud.cfg
users:
- default
disable_root: 0
ssh_pwauth: 1
growpart:
mode: auto
devices: ['/']
ignore_growroot_disabled: false
mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2']
resize_rootfs_tmp: /dev
ssh_deletekeys: 1
syslog_fix_perms: ~
disable_vmware_customization: false
manage_etc_hosts: localhost
cloud_init_modules:
- disk_setup
- migrator
- bootcmd
- write-files
- growpart
- resizefs
- set_hostname
- update_hostname
- update_etc_hosts
- rsyslog
- users-groups
- ssh
cloud_config_modules:
- mounts
- locale
- set-passwords
- rh_subscription
- yum-add-repo
- package-update-upgrade-install
- timezone
- puppet
- chef
- salt-minion
- mcollective
- disable-ec2-metadata
- runcmd
cloud_final_modules:
- rightscale_userdata
- 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_info:
distro: debian
paths:
cloud_dir: /var/lib/cloud
templates_dir: /etc/cloud/templates
ssh_svcname: sshd
scripts-per-boot And bootcmd
bootcmd 不要被这个命令迷惑了。
/var/lib/cloud/
云实例初始化相关的关键数据和状态信息。
/var/lib/cloud/instance
该目录的内容与当前实例强绑定,不同实例(即使基于同一镜像创建)的 instance 目录内容会因元数据、用户数据的不同而存在差异。这也是 cloud-init 能够为每个实例提供独立初始化配置的关键。
/var/lib/cloud/instance/vendor-data.txt
存储云厂商的自定义配置。
主流云平台(如 OpenStack、AWS、GCP 等)通过元数据服务(Metadata Service) 动态向实例传递 vendor-data:
- 云平台在实例创建时,会将预定义的 vendor-data 存储在其内部元数据服务中;
- 实例启动后,cloud-init 会通过本地网络(通常是 169.254.169.254 这类保留 IP)访问云平台的元数据服务,拉取包括 vendor-data 在内的各类数据(同时拉取的还有 user-data、meta-data 等);
- 拉取后,cloud-init 会将 vendor-data 保存到实例本地的
/var/lib/cloud/instance/vendor-data.txt中,作为执行依据。
可以看到 vendor-data.txt 中已经包含了实例规格信息,比如 path: /home/ecs.ebmhpcpni3lm.48xlarge_runcmd.sh 这种字段。本地不会更改这个字段,这个是在服务端决定的。