cloud-init 26.1 配置参数详解

基于 Ubuntu 22.04 实测环境逐项拆解 cloud-init 26.1 配置体系,覆盖配置目录与合并规则、cloud.cfg 顶层参数、三大模块清单 53 个模块、system_info 发行版配置、日志配置与生产配置模板,全部配置内容实测采集。

cloud-initcloud-initUbuntuUbuntu 22.04Linux配置管理2026/10/17

cloud-init 26.1 配置参数详解

目标:逐项讲清 cloud-init 26.1 的配置体系——配置目录与合并规则、cloud.cfg 全部顶层参数、三大模块清单 53 个模块的职责、system_info 发行版配置与日志配置,并给出可直接落地的生产配置模板。全部配置文件内容已在 Ubuntu 22.04、cloud-init 26.1-0ubuntu1~22.04.1 环境实测采集。

一、环境信息

  • 操作系统:Ubuntu 22.04(jammy),x86_64
  • 内核:6.8.0-138-generic
  • cloud-init:26.1-0ubuntu1~22.04.1
  • 配置目录:/etc/cloud/(主配置 cloud.cfg、扩展目录 cloud.cfg.d/、模板目录 templates/)
  • 运行数据目录:/var/lib/cloud/;运行态状态:/run/cloud-init/
  • 主日志:/var/log/cloud-init.log;命令输出日志:/var/log/cloud-init-output.log

二、前置条件

  1. 已安装 cloud-init 26.1 并能正常输出版本:
cloud-init --version

实测回显:

/usr/bin/cloud-init 26.1-0ubuntu1~22.04.1
  1. 以下命令均以 root 执行;改动 /etc/cloud/ 前建议先备份原文件。
  2. 修改配置后,对已初始化的机器需要 cloud-init clean 后重跑才会生效(详见《cloud-init 26.1 进阶实战与运维》),本章只讲参数含义与改法。

三、配置文件体系与查看方式

3.1 配置目录结构

cloud-init 的全部配置落点在 /etc/cloud/,实测目录结构如下:

ls -R /etc/cloud/ | head -14

实测回显:

/etc/cloud/:
build.info
clean.d
cloud.cfg
cloud.cfg.d
templates

/etc/cloud/clean.d:

/etc/cloud/cloud.cfg.d:
05_logging.cfg
90_dpkg.cfg
99-disable-network-config.cfg
README
wc -l /etc/cloud/cloud.cfg

实测回显:

136 /etc/cloud/cloud.cfg

各项说明:

路径作用
cloud.cfg发行版基线配置(实测 136 行),定义默认用户、三大模块清单与 system_info
cloud.cfg.d/扩展配置目录,按文件名字母序合并覆盖 cloud.cfg
05_logging.cfg日志行为配置(见第七章)
90_dpkg.cfg包维护脚本生成的数据源清单(见 4.4 小节)
99-disable-network-config.cfg演示环境自建的文件(禁用 cloud-init 网络管理,见 6.3 小节)
templates/各模块渲染配置用的 jinja 模板(hosts、chrony、apt 源等,实测共 52 个)
clean.d/cloud-init clean 时调用的清理钩子目录(包自带为空)
build.info包构建标识,实测内容为 serial: 20260924.1

3.2 配置合并规则

cloud-init 启动时按以下顺序合并出最终配置:

  1. 先读内置默认值;
  2. 读 /etc/cloud/cloud.cfg;
  3. 再按文件名字母序读 /etc/cloud/cloud.cfg.d/*.cfg,后读的键覆盖先读的键;
  4. 数据源的 meta-data / user-data / vendor-data 中的系统配置键再叠加其上。

因此「改配置」的标准姿势是:不直接改 cloud.cfg,而在 cloud.cfg.d/ 新建一个编号更靠后的 .cfg 文件覆盖(如 99-custom.cfg)。cloud.cfg 的注释原文也提示了 datasource 单行数组的书写要求(跨行数组 ds-identify 读不到)。

3.3 查看合并结果

改完配置后,用聚合视图确认最终生效值(排障利器):

python3 -c "
import json
d = json.load(open('/run/cloud-init/combined-cloud-config.json'))
for k in ['users', 'disable_root', 'preserve_hostname', 'output', 'network']:
    print(k, '=>', json.dumps(d.get(k)))
"

实测回显(演示环境已写 network: {config: disabled}):

users => ["default"]
disable_root => true
preserve_hostname => false
output => {"all": "| tee -a /var/log/cloud-init-output.log"}
network => {"config": "disabled"}

💡 说明:combined-cloud-config.json 是 cloud.cfg、cloud.cfg.d、meta-data、user-data、vendor-data 合并后的最终视图,见《cloud-init 26.1 快速入门与 NoCloud 数据源实战》8 章 Q5。检查任意参数是否生效,以它为准,不要凭 cloud.cfg 内容推断。

四、cloud.cfg 顶层参数详解

Ubuntu 22.04 打包的 cloud.cfg 顶层参数实测如下(行号为实测文件位置):

grep -nE '^[a-z_]+:' /etc/cloud/cloud.cfg | head -8

实测回显:

7:users:
12:disable_root:
15:preserve_hostname:
27:cloud_init_modules:
45:cloud_config_modules:
63:cloud_final_modules:
90:system_info:

顶层只有 4 个业务参数(其余 3 个是模块清单与 system_info),逐项详解如下。

4.1 users

users:
  - default

决定首启创建哪些用户。default 是占位符,引用 system_info.default_user 定义的发行版默认用户(Ubuntu 为 ubuntu,见 6.1 小节)。也可以写成显式清单创建任意用户,写法与 user-data 的 users 指令一致(示例见《cloud-init 26.1 快速入门与 NoCloud 数据源实战》4.2 小节)。常见取值对比:

写法效果
- default创建发行版默认用户(ubuntu)
- default + - name: ops默认用户之外再创建 ops
[]不创建任何用户

4.2 disable_root

disable_root: true

是否禁用 root 直接 SSH 登录。true 时 users_groups/ssh 模块会在 root 的 authorized_keys 中为密钥行添加限制前缀(no-port-forwarding 等选项与提示登录默认用户的 command 指令),使 root 密钥登录被引导到默认用户。实测值为 true;要放开 root 登录则改为 false。

4.3 preserve_hostname

preserve_hostname: false

false 时 set_hostname/update_hostname 模块按数据源元数据(meta-data 的 local-hostname 或 user-data 的 hostname 指令)设置主机名;true 则完全不动主机名。固定主机名的机器改 true,避免每次首启被数据源覆盖。

4.4 datasource_list(90_dpkg.cfg)

Ubuntu 打包把数据源清单放在 cloud.cfg.d/90_dpkg.cfg(由 deb 维护脚本生成):

cat /etc/cloud/cloud.cfg.d/90_dpkg.cfg

实测回显:

# to update this file, run dpkg-reconfigure cloud-init
datasource_list: [ NoCloud, ConfigDrive, OpenNebula, DigitalOcean, Azure, AltCloud, VMware, OVF, MAAS, GCE, OpenStack, CloudSigma, SmartOS, Bigstep, Scaleway, AliYun, Ec2, CloudStack, Hetzner, IBMCloud, Oracle, Exoscale, RbxCloud, UpCloud, Vultr, LXD, NWCS, Akamai, WSL, CloudCIX, None ]

清单顺序即探测优先级,实测 31 项。生产建议收窄到实际平台,缩短首启探测耗时:

printf 'datasource_list: [ NoCloud, ConfigDrive ]' > /etc/cloud/cloud.cfg.d/91-ds-limit.cfg
python3 -c "import json; print(json.load(open('/run/cloud-init/combined-cloud-config.json')).get('datasource_list'))"

收窄后重跑,合并视图实测回显:

['NoCloud', 'ConfigDrive']

💡 技术拓展:数据源类型全量对比(NoCloud/ConfigDrive/Ec2/OpenStack/各公有云/None 的来源与场景)已在《cloud-init 26.1 快速入门与 NoCloud 数据源实战》3.2 小节给出,此处不重复。修改 90_dpkg.cfg 本体不要手工编辑,按文件首行提示用 dpkg-reconfigure cloud-init;自建新编号文件覆盖是等效且更可控的做法(本文即用 91-ds-limit.cfg)。

4.5 output

output: {all: '| tee -a /var/log/cloud-init-output.log'}

定义四阶段 stdout/stderr 的去向。all 一键同时管 stdout 与 stderr,值是管道命令:所有阶段控制台输出经 tee -a 追加到 /var/log/cloud-init-output.log。该键实际写在 05_logging.cfg 中随 cloud.cfg 一起合并,可在自建 .cfg 中覆盖,例如只要 stderr 时写 output: {err: '| tee -a /var/log/cloud-init-err.log'}。支持的键:all/out/err,值可以是字符串(当作命令管道)或文件路径。

4.6 其他常用顶层键

以下键在 Ubuntu 26.1 的 cloud.cfg 中未显式写出,走内置默认值,但都是高频定制项,实测默认行为如下:

键默认值说明
ssh_pwauth0是否允许密码 SSH 登录;显式写入 cloud.cfg 即可覆盖
manage_etc_hostsfalse是否托管 /etc/hosts,多用 user-data 按实例控制
growpart.modeauto磁盘分区扩容模式(auto/growpart/off)
resize_rootfstrue根文件系统是否随分区扩容
timezone无设定时区,等价 user-data 的 timezone 指令
package_updatefalse首启是否执行 apt-get update
final_message"Cloud-init v. VERSION finished at TIME. Up UPTIME seconds"完成消息模板,支持 VERSION/TIME/UPTIME/DATASOURCE 四个内置变量

验证默认值最直接的方法是看合并视图:

python3 -c "
import json
d = json.load(open('/run/cloud-init/combined-cloud-config.json'))
print('ssh_pwauth:', d.get('ssh_pwauth', '(unset -> default 0)'))
print('final_message:', d.get('final_message', '(unset -> built-in)'))
print('vendor_data:', d.get('vendor_data'))
"

实测回显:

ssh_pwauth: (unset -> default 0)
final_message: (unset -> built-in)
vendor_data: {'enabled': True, 'prefix': []}

五、三大模块清单

模块(module)是 cloud-init 的最小执行单元,三大清单决定每个阶段跑哪些模块,顺序即执行顺序。26.1 实测共 15+15+23=53 个模块。

5.1 cloud_init_modules(init 阶段,15 个)

sed -n '/^cloud_init_modules:/,/^cloud_config_modules:/p' /etc/cloud/cloud.cfg | grep ' - ' | tr -d ' -' | paste -sd,

实测回显:

seed_random,bootcmd,write_files,growpart,resizefs,disk_setup,mounts,set_hostname,update_hostname,update_etc_hosts,ca_certs,rsyslog,users_groups,ssh,set_passwords

逐个模块职责:

模块职责对应 user-data 指令
seed_random向内核熵池注入随机数据seed_random
bootcmd极早期执行的命令(每此阶段必跑)bootcmd
write_files写入文件write_files
growpart根分区扩容到磁盘大小growpart
resizefs根文件系统随分区扩容resizefs
disk_setup磁盘分区表与文件系统创建disk_setup / fs_setup
mounts挂载点与 swap 配置mounts / swap
set_hostname设置主机名hostname / fqdn
update_hostname每次引导更新主机名同上
update_etc_hosts更新 /etc/hostsmanage_etc_hosts
ca_certs管理 CA 证书ca_certs
rsyslog配置 rsyslog 转发rsyslog
users_groups创建用户与用户组users / groups
ssh生成/写入 SSH 主机密钥与 authorized_keysssh_* 键、ssh_authorized_keys
set_passwords设置用户密码与 ssh_pwauthchpasswd / ssh_pwauth / password

5.2 cloud_config_modules(config 阶段,15 个)

sed -n '/^cloud_config_modules:/,/^cloud_final_modules:/p' /etc/cloud/cloud.cfg | grep ' - ' | tr -d ' -' | paste -sd,

实测回显:

wireguard,snap,ubuntu_autoinstall,ssh_import_id,keyboard,locale,grub_dpkg,apt_pipelining,apt_configure,ubuntu_pro,ntp,timezone,disable_ec2_metadata,runcmd,byobu

逐个模块职责:

模块职责对应 user-data 指令
wireguard配置 WireGuard 隧道wireguard
snap安装 snap 包snap
ubuntu_autoinstallUbuntu 自动安装相关autoinstall
ssh_import_id从 GitHub/LaunchPad 导入公钥ssh_import_id
keyboard设置键盘布局keyboard
locale设置系统 localelocale
grub_dpkg处理 grub 升级交互(grub-pc 安装确认)grub_dpkg
apt_pipeliningapt 下载管线配置apt_pipelining
apt_configure配置 apt 源/代理/首选项apt / apt_primary 等
ubuntu_pro附加 Ubuntu Pro 订阅ubuntu_pro
ntp配置 NTP 服务与服务器列表ntp
timezone设置时区timezone
disable_ec2_metadata关闭 EC2 元数据路由disable_ec2_metadata
runcmd注册 final 阶段执行的命令runcmd
byobu配置 byobu 终端复用byobu

5.3 cloud_final_modules(final 阶段,23 个)

sed -n '/^cloud_final_modules:/,/^system_info:/p' /etc/cloud/cloud.cfg | grep ' - ' | tr -d ' -' | paste -sd,

实测回显:

package_update_upgrade_install,fan,landscape,lxd,ubuntu_drivers,write_files_deferred,puppet,chef,ansible,mcollective,salt_minion,reset_rmc,scripts_vendor,scripts_per_once,scripts_per_boot,scripts_per_instance,scripts_user,ssh_authkey_fingerprints,keys_to_console,install_hotplug,phone_home,final_message,power_state_change

逐个模块职责:

模块职责对应 user-data 指令
package_update_upgrade_install安装/升级/卸载软件包packages / package_update / package_upgrade
fan配置 fan 网络覆盖(跨主机 overlay 地址段)fan
landscape配置 Canonical Landscape 管理端landscape
lxd初始化 LXDlxd
ubuntu_drivers自动安装硬件驱动drivers
write_files_deferred延迟写文件(final 才写)write_files 中 defer: true
puppet / chef / ansible / mcollective / salt_minion各配置管理工具接入puppet / chef / ansible 等
reset_rmc重置 RMC(IBM Cloud 场景)无
scripts_vendor执行 vendor 脚本目录/var/lib/cloud/scripts/vendor
scripts_per_once / per_boot / per_instance按频率执行脚本目录scripts_per_once 等
scripts_user执行 user-data 脚本形态#! 脚本
ssh_authkey_fingerprints输出 authorized_keys 指纹无
keys_to_console把密钥指纹打到控制台ssh
install_hotplug安装热插拔钩子无
phone_home上报完成状态到 URLphone_home
final_message输出完成消息final_message
power_state_change按计划关机/重启power_state

5.4 模块启停定制

不需要的模块直接从清单删行(或注释)即可;单个模块的参数写在顶层键(与模块同名)或 user-data 指令中。注意 21.x 的连字符旧名(write-files/users-groups/set-passwords 等)在 26.1 已全部改为下划线风格,跨版本迁移配置时模块清单要改名(CentOS 8 的 21.1 仍用连字符旧名,对照见《cloud-init 21.1 CentOS 8 安装指南》8.1 小节)。

六、system_info 详解

system_info(cloud.cfg 第 90 行起)是发行版相关的底层定义,一般不改动,但读懂它才能解释默认用户、网络渲染器等行为。

6.1 default_user

实测内容:

default_user:
  name: ubuntu
  lock_passwd: True
  gecos: Ubuntu
  groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video]
  sudo: ["ALL=(ALL) NOPASSWD:ALL"]
  shell: /bin/bash

逐项说明:name: ubuntu 即 users 清单里 default 引用的对象;lock_passwd: True 密码锁定只能密钥登录;sudo 免密 ALL 权限;groups 决定该用户的附加组。首次引导后验证:

id ubuntu

实测回显:

uid=1001(ubuntu) gid=1003(ubuntu) groups=1003(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),1001(lxd),1002(netdev)

6.2 distro 与 ssh_svcname

实测 distro: ubuntu 决定加载 Ubuntu 发行版类(软件包命令用 apt、用户管理用 useradd 等);ssh_svcname: ssh 对应 Ubuntu 的 SSH 服务名。CentOS/RHEL 打包为 distro: rhel、ssh_svcname: sshd,这是跨发行版迁移配置时的关键差异。

6.3 network

实测内容:

network:
  dhcp_client_priority: [dhclient, dhcpcd, udhcpc]
  renderers: ['netplan', 'eni', 'sysconfig']
  activators: ['netplan', 'eni', 'network-manager', 'networkd']

💡 技术拓展:网络渲染器(renderer)决定网络配置写到哪个体系——

渲染器配置落点适用
netplan/etc/netplan/*.yamlUbuntu 18.04+ 默认
eni/etc/network/interfacesDebian 传统 ifupdown
sysconfig/etc/sysconfig/network-scripts/RHEL/CentOS 系

Ubuntu 打包按优先级先试 netplan;activators 是渲染后激活网络的实现。禁用 cloud-init 网络管理用 network: {config: disabled}(实测见《cloud-init 26.1 快速入门与 NoCloud 数据源实战》8 章 Q1)。

6.4 paths 与 package_mirrors

实测 paths.cloud_dir: /var/lib/cloud/、paths.templates_dir: /etc/cloud/templates/,另有 paths.docs_dir: /usr/share/doc/cloud-init/(合并视图实测)。package_mirrors 按架构定义 apt 镜像搜索规则:i386/amd64 失败兜底 http://archive.ubuntu.com/ubuntu 与 http://security.ubuntu.com/ubuntu,并在 EC2 等平台按 region 变量搜索区域镜像;arm64/armel/armhf 走 http://ports.ubuntu.com/ubuntu-ports。私有源场景在 user-data 的 apt 指令里覆盖更常见。

七、05_logging.cfg 日志配置详解

该文件实测位于 /etc/cloud/cloud.cfg.d/05_logging.cfg,用 YAML 锚点定义三套日志后端、按 log_cfgs 选用。核心结构实测如下:

grep -nE '^\s*(- )?&|^log_cfgs|^output' /etc/cloud/cloud.cfg.d/05_logging.cfg

实测回显:

11: - &log_base |
42: - &log_file |
48: - &log_syslog |
55:log_cfgs:
71:output: {all: '| tee -a /var/log/cloud-init-output.log'}

逐项说明:

  • &log_base:loggers/handlers/formatters 骨架,root 与 cloudinit 两个 logger 都是 DEBUG 级,控制台 handler 只输出 WARNING 以上;
  • &log_file:FileHandler 写 /var/log/cloud-init.log(追加模式);
  • &log_syslog:SysLogHandler 写 /dev/log(集中日志场景);
  • log_cfgs 是候选清单,逐项尝试、第一个可用者生效——当前选中 [ *log_base, *log_file ](文件日志),注释行里预置了 syslog 组合,把 log_cfgs 改为 - [ *log_base, *log_syslog ] 即切换;
  • output 见 4.5 小节。

验证日志确实按此配置落盘:

ls -l /var/log/cloud-init.log /var/log/cloud-init-output.log

实测回显:

-rw-r----- 1 root adm  6583 Oct 17 00:09 /var/log/cloud-init-output.log
-rw-r----- 1 root adm 74752 Oct 17 00:09 /var/log/cloud-init.log

八、生产配置模板

一份可直接落地的生产基线(写入 /etc/cloud/cloud.cfg.d/99-production.cfg,按 3.2 小节规则覆盖默认值):

# /etc/cloud/cloud.cfg.d/99-production.cfg
# 场景:私有虚拟化平台(NoCloud/ConfigDrive 数据源)、16GB 内存、NVMe SSD、无状态交付
datasource_list: [ NoCloud, ConfigDrive ]
ssh_pwauth: 0
preserve_hostname: false
package_update: true
package_upgrade: false
manage_etc_hosts: localhost
final_message: "cloud-init completed at __TIME__ after __UPTIME__ seconds on __DATASOURCE__"

逐项说明:收窄数据源清单到实际平台(加快探测、减少误命中);禁密码 SSH(配合 user-data 注入密钥);保留数据源主机名管理;首启更新源索引但不升级全量包(升级交给镜像构建流程);hosts 改 localhost 模式(仅本机回环行,不整文件托管);final_message 模板带上数据源标识便于控制台确认。

落地后核验(需重跑初始化后生效):

cloud-init schema --config-file /etc/cloud/cloud.cfg.d/99-production.cfg

实测回显:

Valid schema /etc/cloud/cloud.cfg.d/99-production.cfg

九、常见问题(FAQ)

Q1:改了 cloud.cfg 不生效? 三种可能:其一,实例已完成初始化,cloud-init 不会自动重跑,需 cloud-init clean 后重跑;其二,被 cloud.cfg.d/ 中编号更靠后的文件覆盖,用合并视图(3.3 小节)确认实际生效值;其三,改的是发行版默认文件而升级包时会被包管理器接管,标准做法是自建 99-*.cfg。

Q2:datasource_list 顺序影响什么? 顺序即探测优先级,第一个命中的数据源生效。把不存在的平台排前面会白等探测超时(Ec2 默认最长等 120 秒),生产机按实际平台收窄能显著缩短首启时间(实测见 4.4 小节)。

Q3:模块清单里删掉 ssh 模块会怎样? 首启不再生成 SSH 主机密钥与 authorized_keys,已有密钥的机器不受影响,新机器会因无主机密钥导致 sshd 启动失败——不要删。想自定义主机密钥类型用顶层键 ssh_genkeytypes(如 ['ed25519'],CentOS 8 打包默认即此值)。

Q4:两个文件都写了同一参数,到底谁生效? 按文件名字母序后读覆盖先读:05_logging.cfg、90_dpkg.cfg、91-ds-limit.cfg、99-production.cfg 依次读取,后者覆盖前者同名键。cloud.cfg 本身先于全部 cloud.cfg.d 文件。有歧义时直接查合并视图,不要猜。

Q5:怎么确认某模块实际跑了没有? 两个手段:看主日志 grep 'config-runcmd' /var/log/cloud-init.log(模块名逐个落日志);或用 analyze 工具看耗时报告(cloud-init analyze blame,实测回显见《cloud-init 26.1 进阶实战与运维》)。

十、参考链接