跳至内容

5. 镜像构建者的视角

默认值和通用化

到目前为止,我们的旅程一直专注于在启动时使用 user-data 配置单个实例。在本章中,我们将视角转向 **镜像构建者**。也就是说,一个创建和维护“黄金镜像”的人,这些镜像作为其他虚拟机的模板。

我们的目标是创建一个新的、自定义的镜像,其中包含我们自己的内置策略和默认值。这涉及两个关键过程:

  1. 自定义系统范围的默认值: 修改 *镜像内部* 的 cloud-init 配置。
  2. 通用化镜像: 使用 cloud-init cleanvirt-sysprep 等工具剥离所有特定于机器的数据,为镜像的克隆做准备。

1. 定制实验室设置

首先,我们需要一个正在运行的基础云镜像实例,以便进行修改。我们将 *不* 提供任何 user-data 来启动此虚拟机,以获得一个干净的系统。

# Create a disk image for our new template
qemu-img create -f qcow2 -o size=10G golden-image-template.qcow2

# Boot the base image using virt-install
virt-install --name golden-image-builder \
--memory 2048 --vcpus 2 \
--disk path=golden-image-template.qcow2,format=qcow2 \
--cloud-init none --os-variant rockylinux10 --import

# Connect to the console and log in as the default 'rocky' user
virsh console golden-image-builder

2. 使用 cloud.cfg.d 进行系统范围的配置

在正在运行的虚拟机内部,我们现在可以自定义系统范围的 cloud-init 配置。您永远不应直接编辑主文件 /etc/cloud/cloud.cfg。正确的、安全升级的自定义位置是 /etc/cloud/cloud.cfg.d/ 目录。cloud-init 在主 cloud.cfg 之后按字母顺序读取此处的所有 .cfg 文件,允许您覆盖默认值。

实践:设置黄金镜像的默认值

让我们为黄金镜像强制执行一项策略:我们将禁用密码认证,设置一个新的默认用户,并确保始终安装一组基线软件包。

  1. 创建自定义配置文件: 从虚拟机内部,创建 /etc/cloud/cloud.cfg.d/99-custom-defaults.cfg99- 前缀确保它最后被读取。

    sudo cat <<EOF > /etc/cloud/cloud.cfg.d/99-custom-defaults.cfg
    # Golden Image Customizations
    
    # Define a new default user named 'admin'
    system_info:
      default_user:
        name: admin
        sudo: ["ALL=(ALL) NOPASSWD:ALL"]
        shell: /bin/bash
    
    # Enforce key-based SSH authentication
    ssh_pwauth: false
    
    # Ensure a baseline of packages is always installed
    packages:
      - htop
      - vim-enhanced
    EOF
    

禁用特定模块

一项强大的安全技术是完全禁用某些 cloud-init 模块。例如,要阻止任何用户使用 runcmd,您可以将以下内容添加到自定义 .cfg 文件中。这告诉 cloud-init 在最后阶段运行一个空的模块列表。

cloud_final_modules: []

3. 通用化镜像

我们的虚拟机现在包含了我们的自定义配置,但它也包含唯一的机器标识符(如 /etc/machine-id)和 SSH 主机密钥。在我们克隆它之前,我们必须在一个称为 **通用化** 的过程中删除这些数据。

方法 1:cloud-init clean (在虚拟机内部)

cloud-init 提供了一个内置命令来实现此目的。

  1. 运行 cloud-init clean 从虚拟机内部,运行以下命令来剥离实例特定的数据。

    sudo cloud-init clean --logs --seed
    

    关于 cloud-init clean --seed

    此命令删除 cloud-init 用来识别实例的唯一种子,强制它在下次启动时从头开始运行。它 *不会* 删除 /etc/cloud/cloud.cfg.d/ 中的自定义配置。此步骤对于创建真正通用的模板至关重要。

  2. 立即关机: 清理后,立即关闭虚拟机。

    sudo poweroff
    

方法 2:virt-sysprep (从主机)

一个更彻底、行业标准的工具是 virt-sysprep。您可以从主机机器上对已关机的虚拟机磁盘运行它。它执行 cloud-init clean 的所有操作,甚至更多,例如清除命令历史记录、删除临时文件和重置日志文件。

  1. 确保虚拟机已关机。

  2. 从您的主机运行 virt-sysprep

    sudo virt-sysprep -a golden-image-template.qcow2
    

通用化过程完成后,磁盘文件 (golden-image-template.qcow2) 就是您的新黄金镜像。

黄金镜像命名约定

给您的黄金镜像起一个描述性的名称,包含操作系统和版本号,例如 rocky10-base-v1.0.qcow2,这是一个好习惯。这有助于版本控制和基础设施管理。

4. 验证黄金镜像

让我们通过 *从* 新镜像启动一个新实例(没有任何 user-data)来测试我们的新镜像。

  1. 从我们的黄金镜像创建新的虚拟机磁盘

    qemu-img create -f qcow2 -F qcow2 -b golden-image-template.qcow2 test-instance.qcow2
    
  2. 启动测试实例

    virt-install --name golden-image-test --cloud-init none ...
    
  3. 验证: 连接到控制台 (virsh console golden-image-test)。登录提示应该是用户 admin,而不是 rocky。登录后,您还可以通过 (rpm -q htop) 验证 htop 的安装。这证实了您的内置默认值正在工作。

下一步

您现在已经学会了如何通过 cloud-init 的系统范围配置来烘焙默认值,并对它们进行适当的通用化以便克隆,从而创建标准化的模板。在下一章中,我们将介绍在 cloud-init 未按预期工作时进行故障排除的关键技能。

作者:Wale Soyinka

贡献者:Steven Spencer