4. 高级配置
网络和多部分载荷¶
在上一个章节中,您已掌握了用于管理用户、软件包和文件的核心 cloud-init
模块。现在,您可以声明式地构建一个配置完善的服务器。现在,是时候探索更高级的技术,让您能够更精确地控制实例的配置了。
本章涵盖两个强大、高级的主题:
- 声明式网络配置:如何超越 DHCP,为您的实例定义静态网络配置。
- 多部分 MIME 载荷:如何将不同类型的用户数据(例如 Shell 脚本和
#cloud-config
文件)合并成一个强大的单一载荷。
1. 声明式网络配置¶
默认情况下,大多数云镜像的配置是通过 DHCP 获取 IP 地址。虽然方便,但许多生产环境需要服务器拥有可预测的静态 IP 地址。cloud-init
网络配置系统提供了一种独立于平台的声明式方法来管理此问题。
网络配置的规范与您的主 #cloud-config
分开,是一个单独的 YAML 文档。cloud-init
从同一文件中处理两者,使用标准的 YAML 文档分隔符 (---
) 来区分它们。
cloud-init
如何应用网络状态
在 Rocky Linux 上,cloud-init
不直接配置网络接口。相反,它充当一个翻译器,将其网络配置转换为 **NetworkManager**(默认网络服务)可以理解的文件。然后,它将控制权交给 NetworkManager 来应用配置。您可以在 /etc/NetworkManager/system-connections/
中检查生成的连接配置文件。
示例 1:配置单个静态 IP¶
在本练习中,我们将为虚拟机配置一个静态 IP 地址、默认网关和自定义 DNS 服务器。
-
创建
user-data.yml
此文件包含两个不同的 YAML 文档,由
---
分隔。第一个是我们标准的#cloud-config
。第二个定义了网络状态。cat <<EOF > user-data.yml #cloud-config # We can still include standard modules. # Let's install a network troubleshooting tool. packages: - traceroute --- # This second document defines the network configuration. network: version: 2 ethernets: eth0: dhcp4: no addresses: - 192.168.122.100/24 gateway4: 192.168.122.1 nameservers: addresses: [8.8.8.8, 8.8.4.4] EOF
-
关键指令说明
network:
:网络配置的顶级键。version: 2
:指定我们正在使用现代的、类似 Netplan 的语法。ethernets:
:要配置的物理网络接口的字典,以接口名称(例如eth0
)为键。dhcp4: no
:在此接口上禁用 IPv4 的 DHCP。addresses
:要分配的静态 IP 地址列表,以 CIDR 格式指定。gateway4
:IPv4 流量的默认网关。nameservers
:包含 DNS 解析 IP 地址列表的字典。
-
启动和验证
这次的验证方式不同,因为虚拟机不会获得动态 IP 地址。您必须直接连接到虚拟机的控制台。
# Use a new disk image for this exercise qemu-img create -f qcow2 -F qcow2 -b Rocky-10-GenericCloud.qcow2 static-ip-vm.qcow2 virt-install --name rocky10-static-ip \ --memory 2048 --vcpus 2 \ --disk path=static-ip-vm.qcow2,format=qcow2 \ --cloud-init user-data=user-data.yml,hostname=network-server \ --os-variant rockylinux10 \ --import --noautoconsole # Connect to the virtual console virsh console rocky10-static-ip # Once logged in, check the IP address [rocky@network-server ~]$ ip a show eth0
输出应显示
eth0
具有静态 IP 地址192.168.122.100/24
。
示例 2:多接口配置¶
一个常见的实际场景是具有多个网络接口的服务器。在这里,我们将创建一个具有两个接口的虚拟机:eth0
将使用 DHCP,eth1
将具有静态 IP。
-
为两个接口创建
user-data.yml
cat <<EOF > user-data.yml #cloud-config packages: [iperf3] --- network: version: 2 ethernets: eth0: dhcp4: yes eth1: dhcp4: no addresses: [192.168.200.10/24] EOF
-
启动具有两个 NIC 的虚拟机: 我们在
virt-install
命令中添加了第二个--network
标志。virt-install --name rocky10-multi-nic \ --memory 2048 --vcpus 2 \ --disk path=... \ --network network=default,model=virtio \ --network network=default,model=virtio \ --cloud-init user-data=user-data.yml,hostname=multi-nic-server \ --os-variant rockylinux10 --import --noautoconsole
-
验证: 通过 SSH 连接到
eth0
上的 DHCP 分配地址,然后使用ip a show eth1
检查eth1
上的静态 IP。
2. 使用多部分 MIME 统一载荷¶
有时,您需要在主要的 #cloud-config
模块执行之前运行一个设置脚本。MIME 多部分文件是解决方案,它允许您将不同类型的内容打包到一个有序的载荷中。
您可以将 MIME 文件的结构可视化如下:
+-----------------------------------------+
| Main Header (multipart/mixed; boundary) |
+-----------------------------------------+
|
| --boundary |
| +-------------------------------------+
| | Part 1 Header (e.g., text/x-shellscript) |
| +-------------------------------------+
| | Part 1 Content (#/bin/sh...) |
| +-------------------------------------+
|
| --boundary |
| +-------------------------------------+
| | Part 2 Header (e.g., text/cloud-config) |
| +-------------------------------------+
| | Part 2 Content (#cloud-config...) |
| +-------------------------------------+
|
| --boundary-- (closing) |
+-----------------------------------------+
实践:预检脚本¶
我们将创建一个多部分文件,该文件首先运行一个 Shell 脚本,然后继续执行主 #cloud-config
。
-
创建多部分
user-data.mime
文件这是一个特殊格式的文本文件,它使用“边界”字符串来分隔各个部分。
cat <<EOF > user-data.mime Content-Type: multipart/mixed; boundary="//" MIME-Version: 1.0 --// Content-Type: text/x-shellscript; charset="us-ascii" #!/bin/sh echo "Running pre-flight checks..." # In a real script, you might check disk space or memory. # If checks failed, you could 'exit 1' to halt cloud-init. echo "Pre-flight checks passed." > /tmp/pre-flight-status.txt --// Content-Type: text/cloud-config; charset="us-ascii" #cloud-config packages: - htop runcmd: - [ sh, -c, "echo 'Main cloud-config ran successfully' > /tmp/main-config-status.txt" ] --//-- EOF
关于 MIME 边界
边界字符串(此例中为
//
)是一个任意字符串,它不得出现在任何部分的內容中。它用于分隔文件的不同部分。 -
启动和验证
您以与标准
user-data.yml
文件相同的方式将此文件传递给virt-install
。# Use a new disk image qemu-img create -f qcow2 -F qcow2 -b Rocky-10-GenericCloud.qcow2 mime-vm.qcow2 virt-install --name rocky10-mime-test \ --memory 2048 --vcpus 2 \ --disk path=mime-vm.qcow2,format=qcow2 \ --cloud-init user-data=user-data.mime,hostname=mime-server \ --os-variant rockylinux10 \ --import --noautoconsole
启动后,SSH 进入虚拟机,并通过查找它们创建的文件来检查两个部分是否都已运行。
cat /tmp/pre-flight-status.txt cat /tmp/main-config-status.txt
其他多部分内容类型
cloud-init
支持其他内容类型以应对高级用例,例如用于早期启动脚本的 text/cloud-boothook
或用于运行自定义 Python 代码的 text/part-handler
。有关更多详细信息,请参阅官方文档。
下一步¶
您现在已经学习了两个强大的、高级的 cloud-init
技术。现在,您可以定义静态网络,并通过多部分用户数据来协调复杂的配置工作流程。
在下一章中,我们将视角从按实例“使用” cloud-init
转移到“定制其默认行为”,以创建您自己的预配置“黄金镜像”。
作者:Wale Soyinka
贡献者:Steven Spencer