支持的自定义操作

如需自定义虚拟机映像(例如运行终端脚本、更新启动参数、转移二进制文件或安装 GPU 驱动程序),您可以在自定义配方 (imagebuilder.yaml) 的 spec.steps 块内定义特定的辅助操作。

概览

在 Image Builder 构建的执行阶段,编排器会在临时工作器虚拟机上按顺序运行自定义配方 (spec.steps) 中声明的步骤。

每个步骤都必须指定一个 name、一个 action 和一个针对相应操作类型量身定制的 inputs 块。Image Builder 支持以下自定义操作:

  • Shell:在工作器客户机操作系统上执行内嵌终端脚本或命令。
  • UpdateKernelCommandLine:修改启动参数和内核命令行标志。
  • FileCopy:将配置文件、脚本或资源从 Cloud Storage 或本地工作区转移到虚拟机。
  • InstallGPU:下载、编译和注册 NVIDIA GPU 驱动程序。

Shell 操作

借助 Shell 操作,您可以在临时工作器虚拟机的 guest 操作系统上执行内嵌终端脚本或单个 shell 命令,以执行自定义操作,例如更新软件包、配置用户账号或编译软件。

steps.inputs 下指定以下任一输入内容:

  • inlineScript(字符串):要执行的原始多行 shell 命令。
  • command(字符串):单个系统命令字符串或二进制文件可执行文件的相对路径。

示例配置

以下标签页显示了运行内嵌脚本与运行单个命令的示例步骤配置:

运行内嵌脚本

以下配置运行一个多行脚本,该脚本使用 apt 更新软件包:

- name: "Update guest packages and configure groups"
  action: Shell
  inputs:
    inlineScript: |
      #!/bin/bash
      apt-get update -y
      apt-get install -y fail2ban build-essential
      groupadd -r adminusers

运行单个命令

以下配置运行单个 shell 命令来验证活跃的操作系统内核版本:

- name: "Log kernel identifier"
  action: Shell
  inputs:
    command: "uname -a"

特殊行为

当您运行 Shell 操作时,自定义配置程序会管理安全性审核和自动系统重启,如下几部分中所述:

安全审核

为防止敏感令牌、密钥或专有代码泄露到执行日志中,自定义配置器不会打印脚本的原始行,除非启用了交互式调试 (debug: true)。否则,它会将脚本载荷的 SHA-256 完整性哈希记录到 build 日志中。此哈希可提供有关映像上运行的代码的不可变审核跟踪记录。

系统重新启动(退出代码 3010)

某些 shell 操作(例如内核补丁更新或存储分区调整)需要重新启动系统,然后才能运行后续步骤。

如需在自定义期间请求系统重新启动,您的 shell 脚本必须以命令 exit 3010 结束。当自定义预配工具收到退出代码 3010 时,它会按如下方式处理重启生命周期:

  1. 预配工具检测到退出代码 3010,暂停执行,并标记步骤进度索引。
  2. 预配工具会重新启动工作器虚拟机。
  3. 虚拟机重启后,配置器会装载工作区,并自动恢复队列中的流水线,从下一步开始执行。
重新启动示例:

以下示例展示了一个更新软件包并请求重新启动的步骤配置:

- name: "Install core updates and request reboot"
  action: Shell
  inputs:
    inlineScript: |
      #!/bin/bash
      echo "Applying configuration package upgrades..."
      apt-get dist-upgrade -y
      # Terminate with return code 3010 to trigger a system reboot
      exit 3010
- name: "Post-reboot verification"
  action: Shell
  inputs:
    command: "uname -r"

UpdateKernelCommandLine 操作

UpdateKernelCommandLine 操作用于查找、替换、插入或移除在系统启动时传递给内核的命令行标志,例如在配置控制台日志或调整内核参数时。

steps.inputs 映射下指定以下属性:

  • oldArguments(字符串,必需):要在引导加载程序配置中查找、移除或替换的确切命令行实参。
  • newArguments(字符串,可选):要写入以取代目标标志的替换实参。如果您省略 newArguments 属性,Image Builder 会从引导行中完全移除 oldArguments 属性中配置的参数。

示例配置

以下标签页显示了用于替换或移除内核启动实参的示例步骤配置:

替换启动实参

以下配置会找到内核日志级别键 loglevel=4,并将其替换为更详细的参数 loglevel=6 console=ttyS0

- name: "Configure detailed boot logging"
  action: UpdateKernelCommandLine
  inputs:
    oldArguments: "loglevel=4"
    newArguments: "loglevel=6 console=ttyS0"

移除启动实参

以下配置会搜索参数 quiet 并将其从启动实参中移除,以便在启动检查阶段启用详细日志记录:

- name: "Enable verbose startup diagnostics"
  action: UpdateKernelCommandLine
  inputs:
    oldArguments: "quiet"

特定于操作系统的执行详细信息

以下标签页介绍了自定义配置器如何根据源 guest 操作系统处理映像修改:

Container-Optimized OS (COS)

由于 COS 采用只读分区布局,因此省略了标准配置工具。自定义预配工具会执行以下操作:

  1. 确定有效启动设备路径。
  2. 装载启动设备的第 12 个分区(即 EFI 分区)。
  3. 直接更新 /efi/boot/grub.cfg 内的引导加载程序参数。
  4. 安全地卸载分区 12。

Ubuntu

在 Ubuntu 映像上,自定义预配程序执行以下操作:

  1. 打开 /etc/default/grub/etc/default/grub.d/*.cfg 下的文件。
  2. GRUB_CMDLINE_LINUX 块下插入、修改或删除目标实参。
  3. 运行软件包命令 update-grub 以重新生成引导加载程序配置。

FileCopy 操作

FileCopy 操作会将配置文件、二进制文件或证书从远程存储桶或本地代码库复制到自定义映像。自定义预配工具会下载或读取源文件,将其写入工作器虚拟机上指定的 guest 路径,并配置权限。

steps.inputs 下指定以下输入:

  • destination(字符串,必需):客户机操作系统中创建文件的绝对路径。
  • permissions(字符串,必需):目标配置权限的八进制表示形式,例如 "0755""0644"
  • 指定以下任一来源属性:
    • gcsSourcePath(字符串):源文件的 Cloud Storage URI,必须采用 gs://BUCKET_NAME/OBJECT_NAME 格式。
    • localSourcePath(字符串):本地工作区代码库文件夹中文件的相对路径。出于安全考虑,系统已屏蔽使用 ../ 的路径遍历。

示例配置

以下标签页显示了从 Cloud Storage 复制文件与从本地工作区复制文件的示例步骤配置:

Cloud Storage

以下配置将配置模板从 Cloud Storage 存储桶复制到 guest 虚拟机映像:

- name: "Import licensing configuration"
  action: FileCopy
  inputs:
    gcsSourcePath: "gs://enterprise-configs-bucket/licensing/license.key"
    destination: "/etc/app/license.key"
    permissions: "0600"

本地工作区

以下配置会复制在之前的 Cloud Build 步骤中编译的应用脚本:

- name: "Deploy setup automation daemon"
  action: FileCopy
  inputs:
    localSourcePath: "bin/setup-daemon"
    destination: "/usr/local/bin/setup-daemon"
    permissions: "0755"

特定于操作系统的准则

以下标签页介绍了文件位置指南,具体取决于目标 guest 操作系统:

Container-Optimized OS (COS)

出于安全考虑,COS 映像包含只读分区布局。某些标准系统目标(例如 /usr//bin/)处于写保护状态。

在 COS 上配置文件目标位置时:

Ubuntu

Ubuntu 映像采用标准的 Linux 读写根分区布局 (/)。您可以指定任何标准系统路径(例如 /etc/usr/local/bin/var/home)中的文件目的地,前提是用户个人资料或目标文件夹在工作器虚拟机上具有适当的配置权限。

InstallGPU 操作

使用 InstallGPU 操作可构建针对机器学习、数据科学或科学工作负载进行了优化的虚拟机映像。Image Builder 会在自定义映像上下载、编译和注册 NVIDIA GPU 驱动程序。您可以根据基本映像类型和目标硬件,选择安装预编译的驱动程序或编译自定义驱动程序 .run 文件。

steps.inputs 下指定以下输入之一:

  • version(字符串):目标 NVIDIA 驱动程序版本号,例如 "595.129.03"。如果您仅指定 version,编排器会从官方 NVIDIA 库 (https://us.download.nvidia.com/tesla/<version>) 下载驱动程序。
  • gcsRunfile(字符串):自定义 NVIDIA 驱动程序安装程序文件的 Cloud Storage 路径,必须采用 gs://BUCKET_NAME/OBJECT_NAME.run 格式。
  • sourceRunfile(字符串):本地工作区代码库文件夹内安装程序 .run 文件的相对路径。

示例配置

以下标签页显示了安装特定预打包驱动程序版本与安装自定义运行文件的示例步骤配置:

标准版下载

以下配置会从官方代码库下载并安装指定的 NVIDIA 驱动程序版本:

- name: "Configure default NVIDIA drivers"
  action: InstallGPU
  inputs:
    version: "<var>DRIVER_VERSION</var>"

Cloud Storage runfile

以下配置直接从 Cloud Storage 存储桶部署自定义 NVIDIA 驱动程序 .run 安装程序:

- name: "Deploy custom GPU driver from Cloud Storage"
  action: InstallGPU
  inputs:
    gcsRunfile: "gs://<var>BUCKET_NAME</var>/drivers/NVIDIA-Linux-aarch64-<var>DRIVER_VERSION</var>.run"

本地工作区运行文件

以下配置会从本地代码库工作区部署自定义 NVIDIA 驱动程序 .run 安装程序:

- name: "Deploy custom GPU driver from workspace"
  action: InstallGPU
  inputs:
    sourceRunfile: "drivers/NVIDIA-Linux-x86_64-<var>DRIVER_VERSION</var>.run"

配置方法

以下标签页介绍了在自定义映像上配置 NVIDIA GPU 驱动程序的受支持方法:

预编译的驱动程序

我们建议使用预打包的驱动程序版本,以避免从头开始编译驱动程序的计算开销和构建时间。

  • Container-Optimized OS (COS):如果您指定 Google 预先打包的驱动程序版本,自定义预配工具会运行 guest 工具 cos-extensions install gpu 来激活该驱动程序。

    如需查看您的 COS 版本支持的预编译驱动程序版本列表,请在运行的 COS 实例上运行 sudo cos-extensions list,或参阅确定 GPU 驱动程序版本

  • Ubuntu:为了节省 Ubuntu 上的 build 时间,我们建议从公共 ubuntu-os-accelerator-images 项目中选择预配置的基础映像,其中预安装了 NVIDIA 驱动程序。

    如需列出可用的加速器映像,请在 gcloud CLI 中运行以下命令:

    gcloud compute images list \
        --project=ubuntu-os-accelerator-images \
        --no-standard-images
    

自定义 runfiles

如果您必须安装 Google 或 Canonical 未预编译的自定义驱动程序版本,可以指定直接安装程序运行文件以进行编译,如下所示:

  • Ubuntu:在 guest 中执行编译。自定义预配工具会自动安装匹配的内核头文件 (linux-headers-$(uname -r)),在工作器虚拟机上编译 NVIDIA 驱动程序 .run 文件,并将其注册到动态内核模块支持 (DKMS)。向 DKMS 注册可确保驱动程序在次要内核更新期间保持有效。
  • Container-Optimized OS (COS):编译行为因源基础虚拟机映像的 CPU 架构而异:
    • ARM64 映像:由于 ARM64 COS 虚拟机不支持在 guest 中编译标头,因此 Image Builder 会在 build 容器内自动交叉编译自定义驱动程序 .run 实用程序,并将生成的软件包安装到工作器虚拟机的 /var/lib/nvidia 中。
    • x86-64 映像:直接在工作器虚拟机上执行客户机内编译。

后续步骤