cloud-init 是云实例首次启动时进行初始化的事实标准。当你启动一个实例并传入 user-data 脚本时,正是 cloud-init 负责解释并执行它:创建用户、写入文件、安装软件包、挂载磁盘或启动 服务。
理想的搭配很清楚:golden AMI 承载不变的部分——操作系统、运行时、加固;user-data 提供 随环境或实例而变的部分:配置、注入的机密、角色。这样,一份镜像就能复用在众多场景里。
编写 user-data 的两种方式
user-data 支持多种格式,最常见的两种是 shell 脚本与 cloud-config。
- shell 脚本:以
#!/bin/bash开头。用于快速任务,直接了当。 - cloud-config:以
#cloud-config开头,使用声明式 YAML。在配置用户、软件包、文件与 命令方面更干净、更易读,也更幂等。
一个 cloud-config 示例
典型的 #cloud-config 会声明这些段落:packages:(要安装的软件包)、write_files:
(配置文件)、runcmd:(收尾命令)和 users:(账户与密钥)。由于是声明式的,它比一长串
脚本更易审阅和维护。
最佳实践
- 让 user-data 保持精简:如果它膨胀得太厉害,那部分内容多半应该烘焙进 AMI。
- 幂等性:把命令设计成重复执行也不会出问题。
- 绝不要在 user-data 里放明文机密:它可以从实例元数据读到。请在运行时从 Secrets Manager、Parameter Store 或 Vault 注入。
- 保护元数据访问:启用 IMDSv2,缓解通过 SSRF 窃取凭据的风险。
- 记录并调试:出问题时,cloud-init 的日志(
/var/log/cloud-init-output.log)是你最好的 朋友。
烘焙还是启动:什么放哪里
| 放进 AMI(烘焙) | 放进 user-data(启动) |
|---|---|
| 操作系统与补丁 | 与环境相关的配置 |
| 运行时、代理与加固 | 每个实例各自的变量与参数 |
| 稳定且体积大的软件 | 集群注册与服务发现 |
| 所有安装耗时的东西 | 运行时的机密注入 |
黄金法则:稳定又慢的东西烘焙进镜像;多变又轻的东西放在启动时。
会浪费你几小时的常见错误
- 把本该在镜像里的东西塞进 user-data,结果启动又慢又脆弱。
- 在元数据中以明文暴露机密。
- 以为 user-data 每次开机都会重跑:默认它只在首次启动时执行。
- 实例「没按预期工作」时,不去看 cloud-init 的日志。
常见问题
每次重启都会执行 user-data 吗?
默认只在首次启动时执行。你可以配置 cloud-init 让某些部分每次启动都跑,但要有意识地做,并 保证幂等。
在 user-data 里传密码安全吗?
不安全。user-data 可从实例元数据读取。请使用机密管理器并在运行时注入,同时用 IMDSv2 保护 元数据。
cloud-init 只能在 AWS 上用吗?
不是。cloud-init 是跨平台的,可在 AWS、Azure、GCP 等环境运行,非常适合以可移植的方式自动化 启动流程。
在 imaxe.cloud,我们设计的镜像本就打算与 cloud-init 搭配,让一份 AMI 在众多场景中都好用。



