对使用 cloud-init 的 VM 预配进行故障排除
注意
本文引用了 CentOS,这是一个处于生命周期结束 (EOL) 状态的 Linux 发行版。 请相应地考虑你的使用和规划。 有关详细信息,请参阅 CentOS 生命周期结束指南。
适用于:✔️ Linux VM ✔️ 灵活规模集
如果你已在创建通用化自定义映像(使用 cloud-init 进行预配),但发现 VM 未正确创建,则需对自定义映像进行故障排除。
预配问题的一些示例:
- VM 停滞在“正在创建”状态达 40 分钟,并且 VM 创建操作被标记为失败。
CustomData
未得到处理。- 临时磁盘装载失败。
- 未创建用户,或存在用户访问问题。
- 未正确设置网络。
- 交换文件或分区故障。
本文逐步讲解如何对 cloud-init 进行故障排除。 如需更深入的详细信息,请参阅深入探讨 cloud-init。
步骤 1:在不使用 customData
的情况下测试部署
在创建 VM 时,Cloud-init 可以接受传递给它的 customData
。 首先,你应确保这不会导致任何部署问题。 尽量在不传入任何配置的情况下预配 VM。 如果你发现 VM 无法预配,请继续执行下面的步骤;如果发现未应用你传递的配置,请转到步骤 4。
步骤 2:查看映像要求
VM 预配失败的主要原因是 OS 映像不满足在 Azure 上运行的先决条件。 尝试在 Azure 中预配映像之前,请确保已正确准备好映像。
以下文章演示了准备 Azure 中支持的各种 Linux 发行版的步骤:
- 基于 CentOS 的分发版
- Debian Linux
- Flatcar Container Linux
- Oracle Linux
- Red Hat Enterprise Linux
- SLES 和 openSUSE
- Ubuntu
- 其他:非认可的分发版
对于受支持的 Azure cloud-init 映像,Linux 发行版已准备好所有必需的包和配置,方便用户在 Azure 中正确预配映像。 如果发现无法基于你自己的特选映像创建 VM,请尝试使用一个受支持的、已使用你的可选 customData
为其配置了 cloud-init 的 Azure 市场映像。 如果 customData
可以在 Azure 市场映像中正常使用,则可能是特选映像出现问题。
步骤 3:收集和查看 VM 日志
当 VM 无法预配时,Azure 会显示“正在创建”状态 20 分钟,然后重启 VM,再等待 20 分钟,最后才会将 VM 部署标记为失败,并使用 OSProvisioningTimedOut
错误来标记它。
你需要在 VM 处于运行状态的情况下使用其中的日志来了解预配为何失败。 若要了解 VM 预配为何失败,请不要停止 VM。 让 VM 保持运行状态。 为了收集日志,你需要使发生故障的 VM 保持运行状态。 若要收集日志,请使用以下方法之一:
运行 AZ VM Repair 以使用 chroot 附加和装载 OS 磁盘,这将允许你收集以下日志:
sudo cat /rescue/var/log/cloud-init*
sudo cat /rescue/var/log/waagent*
sudo cat /rescue/var/log/syslog*
sudo cat /rescue/var/log/rsyslog*
sudo cat /rescue/var/log/messages*
sudo cat /rescue/var/log/kern*
sudo cat /rescue/var/log/dmesg*
sudo cat /rescue/var/log/boot*
注意
或者,可以使用 Azure 门户手动创建救援 VM。 有关详细信息,请参阅通过使用 Azure 门户将 OS 磁盘附加到恢复 VM 来对 Linux VM 进行故障排除。
若要开始进行初始故障排除,请从 cloud-init 日志着手,了解发生故障的位置,然后使用其他日志深入了解情况并获取更多见解。
- /var/log/cloud-init.log
- /var/log/cloud-init-output.log
- Serial/boot logs
在所有日志中,开始搜索“Failed”、“WARNING”、“WARN”、“err”、“error”、“ERROR”。 建议将配置设置为忽略区分大小写的搜索。
提示
如果对自定义映像进行故障排除,应考虑在映像操作过程中添加用户。 如果预配无法设置管理员用户,你仍然可以登录到 OS。
分析日志
下面更详细地介绍了要在每个 cloud-init 日志中查找什么内容。
/var/log/cloud-init.log
默认情况下,所有优先级为“调试”或更高级别的 cloud-init 事件都会写入到 /var/log/cloud-init.log
中。 这样就可以提供在 cloud-init 初始化期间发生的每个事件的详细日志。
例如:
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
可以在 cloud-init 的各个阶段获取 stdout
和 stderr
中的信息。 这通常涉及 cloud-init 的每个阶段的路由表信息、网络信息、ssh 主机密钥验证信息、stdout
和 stderr
,以及每个阶段的时间戳。 如果需要,可以通过 /etc/cloud/cloud.cfg.d/05_logging.cfg
重新配置 stderr
和 stdout
日志记录。
Serial/boot logs
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 个阶段中执行)后运行。 若要排查为何未应用配置,请手动查看步骤 3 中的日志和 cloud-init 模块。 例如:
runcmd
- 脚本在运行时是否未出错? 请从终端手动运行配置,以确保它们按预期运行。- 安装包 - VM 是否有权访问包存储库?
- 还应检查提供给 VM 的
customData
数据配置,该配置位于/var/lib/cloud/instances/<unique-instance-identifier>/user-data.txt
中。
后续步骤
如果仍然无法厘清 cloud-init 未运行配置的原因,则需更细致地了解每个 cloud-init 阶段发生的情况,以及运行模块的时间。 有关详细信息,请参阅更深入地了解 cloud-init 配置。