다음을 통해 공유

对使用 cloud-init 的 VM 预配进行故障排除

谨慎

本文引用 CentOS,这是支持终止(EOS)状态的 Linux 分发版。 请相应地考虑使用和规划。 有关详细信息,请参阅 CentOS 生命周期结束指南

适用对象:✔️ Linux VM ✔️ 灵活规模集

如果创建通用自定义映像并使用 cloud-init 进行预配,则 VM 可能无法正确生成。 在这种情况下,请对映像进行故障排除以查找问题。

预配问题的一些示例:

  • 计算资源提供程序 API 返回错误,cloud-init 报告生成的失败。
  • VM 停滞在“正在创建”状态达 40 分钟,并且 VM 创建操作被标记为失败。
  • 不会处理自定义数据用户数据
  • 临时磁盘无法装载(对应于 SCSI 资源磁盘随附的 VM SKU)。
  • 用户未创建,或者存在用户访问问题。
  • 未正确设置网络。
  • 交换文件或分区故障。

本文逐步讲解如何对 cloud-init 进行故障排除。 如需更深入的详细信息,请参阅深入探讨 cloud-init

排查 cloud-init 报告的故障并将其记录为错误

Cloud-init 在资源预配期间向 Azure 报告失败时会生成结构化错误信息。 这些错误消息包括原因和支持数据(例如时间戳、VM 标识符、文档 URL 等),以帮助调查失败。

原因 DESCRIPTION 行动
找不到 DHCP 接口 找不到网络接口。 删除并重新创建 VM。 如果问题仍然存在,请确保已安装网络驱动程序或 Azure 专用内核,并检查启动诊断以确认 eth0 是否被正确枚举。
未能获取 DHCP 租约 DHCP 服务因暂时性平台问题而无法响应。 删除并重新创建 VM。
找不到主 DHCP 接口 找不到主 DHCP 接口。 检查启动诊断,确保主网络接口已命名 eth0 ,且未重命名。
查询 IMDS 时连接超时 与 IMDS 的连接可能会因暂时性平台问题、NSG 或操作系统防火墙配置而超时。 删除并重新创建 VM。 如果问题仍然存在,请验证 NSG 或 OS 防火墙是否未阻止访问 IMDS。
查询 IMDS 时读取超时 与 IMDS 的连接可能会因暂时性平台问题或操作系统防火墙配置而超时。 删除并重新创建 VM。 如果问题仍然存在,请验证 OS 防火墙不会阻止访问 IMDS。
分析 ovf-env.xml 时出现意外的元数据 ovf-env.xml 中的 VM 元数据格式不正确。 使用提供的链接将问题提交到 cloud-init 跟踪器。
等待主机关闭时出错 主机关闭处理期间出现故障。 使用提供的链接将问题提交到 cloud-init 跟踪器。
找不到 Azure-proxy-agent 缺少 azure-proxy-agent 二进制文件。 确保映像中安装了 Azure 代理程序。 有关更多故障排除,请查看 MSP 故障排除指南
Azure-proxy-agent 状态失败 代理程序报告了状态错误。 根据需要查看代理日志并更新。 有关更多故障排除,请查看 MSP 故障排除指南
未经处理的异常 cloud-init 内部发生意外错误。 使用提供的链接将问题提交到 cloud-init 跟踪器。

有关启用和检查启动诊断的帮助,请参阅 启动诊断

如果在预配时后续尝试中仍然存在这些问题,则这是因为映像中配置错误。 如果有理由相信存在 cloud-init 问题,请将其报告给 cloud-init GitHub 问题跟踪器

排查 cloud-init 未报告的其他故障

根据失败情况,请考虑以下步骤。

步骤 1:在不使用 customData 的情况下测试部署

创建 VM 时,Cloud-init 可以接受 customData 传递给它的云。 首先,应确保此配置不会导致部署出现问题。 尽量在不传入任何配置的情况下预配 VM。 如果 VM 无法预配,请按照建议的故障排除步骤作。 如果未应用配置,请参阅 步骤 4

步骤 2:查看映像要求

VM 预配失败的主要原因是 OS 映像不满足在 Azure 上运行的先决条件。 尝试在 Azure 中预配映像之前,请确保已正确准备好映像。

以下文章演示了准备 Azure 中支持的各种 Linux 发行版的步骤:

对于受支持的 Azure cloud-init 映像,Linux 发行版已准备好所有必需的包和配置,方便用户在 Azure 中正确预配映像。 如果发现无法基于你自己的特选映像创建 VM,请尝试使用一个受支持的、已使用你的可选 customData 为其配置了 cloud-init 的 Azure 市场映像。 如果 Azure customData 市场映像正常工作,则特选映像可能存在问题。

步骤 3:收集和查看 VM 日志

当 VM 预配失败时,Azure 会显示“创建”状态,20 分钟,然后重新启动 VM,再等待 20 分钟,然后最后将 VM 部署标记为失败,最后将其标记为 OSProvisioningTimedOut 错误。

在 VM 运行时,需要 VM 中的日志来了解预配失败的原因。 若要了解 VM 预配失败的原因,请不要停止 VM。 让 VM 保持运行状态。 需要使失败的 VM 保持运行状态才能收集日志。 若要收集日志,请使用以下方法之一:

  • 在创建 VM 之前启用启动诊断,然后在启动过程中查看它们。

  • 运行 AZ VM 修复 以附加和装载 OS 磁盘(lvm无 lvm),这样就可以收集和检查这些日志:

    /rescue/var/log/waagent*
    /rescue/var/log/syslog*
    /rescue/var/log/rsyslog*
    /rescue/var/log/messages*
    /rescue/var/log/kern*
    /rescue/var/log/dmesg*
    /rescue/var/log/boot*
    /rescue/ /var/log/cloud-init.log
    /rescue//var/log/cloud-init-output.log
    

> [!NOTE]
> Alternatively, you can create a rescue VM manually by using the Azure portal. For more information, see [Troubleshoot a Linux VM by attaching the OS disk to a recovery VM using the Azure portal](https://learn.microsoft.com/troubleshoot/azure/virtual-machines/troubleshoot-recovery-disks-portal-linux).
To start initial troubleshooting, begin with the serial logs and cloud-init logs to understand where the failure occurred. Then use the other logs for a  deeper dive to help provide additional insights.

* /var/log/cloud-init.log
* /var/log/cloud-init-output.log
* [Serial/boot logs](/virtual-machines/boot-diagnostics#boot-diagnostics-view)

In all logs, start searching for "Failed," "WARNING," "WARN," "err," "error," and "ERROR." Setting configuration to ignore case-sensitive searches is recommended.

Alternatively, use command `cloud‑init collect‑logs` to collect all necessary logs.
Azure’s latest cloud-init versions (≥ 18.2) include the collect‑logs command, which:

Gathers essential logs: /var/log/cloud-init*.log, instance metadata, system info.

Packages everything into a timestamped .tar.gz archive.

Saves the archive locally (for example, `/tmp/cloud-init-logs-timestamp.tar.gz`).

> [!TIP]
> If you're troubleshooting a custom image, you should consider adding a user during the image. If the provisioning fails to set the admin user, you can still log in to the OS.

#### Analyzing the logs

Here are more details about what to look for in each cloud-init log.

#### /var/log/cloud-init.log

By default, all cloud-init events with a priority of debug or higher, are written to `/var/log/cloud-init.log`. This log provides verbose logs of every event that occurred during cloud-init initialization.

For example:

```console
2019-10-10 04:51:25,321 - util.py[DEBUG]: Failed mount of '/dev/sr0' as 'auto': Unexpected error while running command.
Command: ['mount', '-o', 'ro,sync', '-t', 'auto', u'/dev/sr0', '/run/cloud-init/tmp/tmpLIrklc']
Exit code: 32
Reason: -
Stdout:
Stderr: mount: unknown filesystem type 'udf'
2020-01-31 00:21:53,352 - DataSourceAzure.py[WARNING]: /dev/sr0 was not mountable

找到错误或警告时,在 cloud-init 日志中向后读取,以了解在遇到错误或警告之前尝试的 cloud-init。 在许多情况下,cloud-init 在发生错误之前运行 OS 命令或执行预配步骤。 这些作有助于解释错误为何出现在日志中。 以下示例显示 cloud-init 在遇到问题之前尝试直接装载设备。

2019-10-10 04:51:24,010 - util.py[DEBUG]: Running command ['mount', '-o', 'ro,sync', '-t', 'auto', u'/dev/sr0', '/run/cloud-init/tmp/tmpXXXXX'] with allowed return codes [0] (shell=False, capture=True)

还可以在 /etc/cloud/cloud.cfg.d/05_logging.cfg 中重新配置 /var/log/cloud-init.log 的日志记录。 有关 cloud-init 日志记录的详细信息,请参阅 cloud-init 文档

/var/log/cloud-init-output.log

可以在 stdout获取 stderr 中的信息。 此数据通常涉及路由表信息、网络信息、ssh 主机密钥验证信息以及 stdout,stderr cloud-init 的每个阶段以及时间戳。 如果需要,可以通过 stderr 重新配置 stdout/etc/cloud/cloud.cfg.d/05_logging.cfg 日志记录。

串行/启动日志

Cloud-init 具有多个依赖项。 这些依赖项记录在 Azure 上的映像所需的先决条件中,例如网络、存储、装载 ISO 以及装载和格式化临时磁盘。 这些依赖项中的任何一个都可能会引发错误并导致 cloud-init 失败。 例如,如果 VM 无法获取 DHCP 租约,cloud-init 将失败。

如果仍然无法隔离 cloud-init 未能预配的原因,则需要了解什么是 cloud-init 阶段,以及何时运行模块。 有关详细信息,请参阅 深入了解 cloud-init

步骤 4:调查未应用配置的原因

并非 cloud-init 中的每次失败都会导致严重的预配故障。 例如,如果在 cloud-init 配置中使用 runcmd 模块,则命令中的非零退出代码会导致 VM 预配失败。 发生此行为的原因是模块在 cloud-init 的前三个阶段的核心预配步骤之后运行。 若要排查配置未应用的原因,请手动查看步骤 3 中的日志和 cloud-init 模块。 例如:

  • runcmd - 脚本在运行时是否未出错? 为了确保它们按预期运行,请从终端手动运行配置。
  • 安装包 - VM 是否有权访问包存储库?
  • customData检查提供给 VM 的配置。 此文件位于 /var/lib/cloud/instances/<unique-instance-identifier>/user-data.txt.

后续步骤

如果 cloud-init 跳过配置,请检查每个 cloud-init 阶段以及模块执行的时间以确定原因。 有关详细信息,请参阅 更深入地了解 cloud-init 配置