3. 配置引擎
深入了解 cloud-init 模块¶
在上一章中,您成功启动了一个云镜像并执行了简单的自定义。虽然有效,但通过其模块系统,您可以真正释放 cloud-init
的强大功能、可移植性和幂等性。这些模块是 cloud-init
工具包中的专用工具,旨在以声明式和可预测的方式处理特定的配置任务。
本章将深入探讨模块系统,解释什么是模块、它们如何工作以及如何使用最核心的模块来构建一个配置良好的服务器。
1. 配置的解剖¶
什么是 cloud-init 模块¶
cloud-init
模块是一个专门的 Python 脚本,用于处理单个、离散的配置任务。将它们看作是管理用户、安装软件包或写入文件等任务的插件。
与简单脚本(如 runcmd
)相比,使用模块的关键优势在于**幂等性**。幂等操作无论执行一次还是十次,都会产生相同的结果。当您声明一个用户应该存在时,模块会确保满足该状态——如果用户不存在,它会创建用户;如果用户已存在,则不做任何操作。这使得您的配置可靠且可重复。
重新审视 #cloud-config 格式¶
当 cloud-init
看到 #cloud-config
头部时,它会将该文件解释为一系列 YAML 格式的指令。此 YAML 文件中的顶级键直接映射到 cloud-init
模块。
模块执行和顺序¶
模块在引导过程的特定阶段按 /etc/cloud/cloud.cfg
中定义的顺序运行。此流程的简化视图如下所示:
System Boot
|
+--- Stage: Generator (Very early boot)
| `--- cloud_init_modules (e.g., migrator)
|
+--- Stage: Local (Pre-network)
| `--- (Modules for local device setup)
|
+--- Stage: Network (Network is up)
| `--- cloud_config_modules (e.g., users-groups, packages, write_files)
|
`--- Stage: Final (Late boot)
`--- cloud_final_modules (e.g., runcmd, scripts-user)
顺序至关重要。例如,users-groups
模块在 runcmd
之前运行,确保脚本可以由在同一配置中刚创建的用户运行。
自定义 cloud-init
行为
虽然 /etc/cloud/cloud.cfg
定义了默认行为,但您永远不应该直接编辑它。对于持久的、系统范围的自定义,请将您自己的 .cfg
文件放在 /etc/cloud/cloud.cfg.d/
目录中。这是构建自定义镜像的标准做法,我们将在后面的章节中探讨。
2. 高效模块:日常驱动程序¶
让我们通过使用 virt-install
的直接注入方法来实际操作最常见的模块。
模块深入:users
和 groups
¶
妥善管理用户帐户是保护新服务器实例的基石。users
模块是您进行此操作的主要工具,它允许您创建新用户、修改现有用户、管理组成员身份,最重要的是,注入 SSH 密钥以在首次引导时实现安全、无密码登录。
示例 1:创建一个新的管理员用户
在此示例中,我们将配置一个名为 sysadmin
的新专用管理用户。我们将通过将该用户添加到 wheel
组并提供特定的 sudo
规则来授予该用户无密码 sudo
能力。我们还将注入一个 SSH 公钥以确保安全访问。
-
创建
user-data.yml
cat <<EOF > user-data.yml #cloud-config users: - name: sysadmin groups: [ wheel ] sudo: [ "ALL=(ALL) NOPASSWD:ALL" ] shell: /bin/bash ssh_authorized_keys: - <YOUR_SSH_PUBLIC_KEY_HERE> EOF
-
关键指令说明
name
:新帐户的用户名。groups
:将用户添加到的组列表。在 Rocky Linux 上,通常使用wheel
组成员身份来授予管理权限。sudo
:要应用的sudoers
规则列表。规则ALL=(ALL) NOPASSWD:ALL
允许用户在提示输入密码的情况下运行任何sudo
命令。ssh_authorized_keys
:添加到用户~/.ssh/authorized_keys
文件的 SSH 公钥列表。
-
引导和验证:使用此
user-data
引导 VM。您应该能够以sysadmin
身份 SSH 登录并运行sudo
命令。
示例 2:修改默认用户
更常见的任务是简单地保护云镜像(rocky
)提供的默认用户。在这里,我们将修改该用户以添加我们的 SSH 密钥。
-
创建
user-data.yml
cat <<EOF > user-data.yml #cloud-config users: - default - name: rocky ssh_authorized_keys: - <YOUR_SSH_PUBLIC_KEY_HERE> EOF
-
关键指令说明
default
:此特殊条目告诉cloud-init
首先执行其默认用户设置。name: rocky
:通过指定现有用户的名称,模块将修改该用户而不是创建新用户。在这里,它将提供的 SSH 密钥合并到rocky
用户的帐户中。
-
引导和验证:引导 VM。您现在可以以
rocky
用户身份无密码 SSH 登录。
模块深入:packages
¶
packages
模块提供了一种声明式的方法来管理实例上的软件,确保在引导时安装特定的应用程序。
在此示例中,我们将确保安装两个有用的工具 nginx
(高性能 Web 服务器)和 htop
(交互式进程查看器)。我们还将指示 cloud-init
首先更新软件包存储库元数据,以确保它可以找到最新版本。
-
创建
user-data.yml
cat <<EOF > user-data.yml #cloud-config package_update: true packages: - nginx - htop EOF
-
关键指令说明
package_update: true
:指示软件包管理器刷新其本地元数据。在 Rocky Linux 上,这等同于运行dnf check-update
。packages
:要安装的软件包名称列表。
-
引导和验证:引导后,SSH 登录并使用
rpm -q nginx
检查nginx
的安装情况。
幂等性在行动
如果您使用相同的 user-data
重新引导此 VM,packages
模块将看到 nginx
和 htop
已安装,不会采取进一步行动。它确保所需状态(软件包存在)而无需不必要的操作。这就是幂等性。
模块深入:write_files
¶
此模块功能非常强大,允许您将任何文本内容写入系统上的任何文件。它是部署应用程序配置文件、填充 Web 内容或创建辅助脚本的理想工具。
为了展示其强大功能,我们将使用 write_files
来创建 nginx
Web 服务器的自定义主页,该 Web 服务器也在同一次运行中进行安装。
-
创建
user-data.yml
cat <<EOF > user-data.yml #cloud-config packages: [nginx] write_files: - path: /usr/share/nginx/html/index.html content: '<h1>Hello from cloud-init!</h1>' owner: nginx:nginx permissions: '0644' runcmd: - [ systemctl, enable, --now, nginx ] EOF
-
关键指令说明
path
:文件将在文件系统上写入的绝对路径。content
:要写入文件的文本内容。owner
:指定文件的所有者用户和组(例如nginx:nginx
)。permissions
:文件权限(以八进制格式表示,例如0644
)。
-
引导和验证:引导后,SSH 登录并使用
curl localhost
查看新主页。
写入二进制文件
write_files
模块不仅限于文本。通过指定 encoding
,您可以部署二进制文件。例如,您可以使用 encoding: b64
来写入 base64 编码的数据。有关高级用例,请参阅官方 write_files
文档。
下一步¶
您现在已经掌握了三个最基本的 cloud-init
模块。通过组合它们,您可以执行大量的自动化服务器配置。在下一章中,我们将处理更高级的场景,包括网络配置以及在同一次运行中组合不同的 user-data
格式。
作者:Wale Soyinka
贡献者:Steven Spencer