本主题将讨论在已部署实例上测试和调试 cloud-init 的一般方法。
启动时间分析 - cloud-init 分析
有时,实例的性能不如我们希望的那样,而 cloud-init 封装了一个简单的工具来检查在启动和设置期间哪些操作花费了 cloud-init 的时间最长。
脚本/usr/bin/cloud-init有一个 analyze 子命令analyze 将任何 cloud-init.log 文件解析为格式化和排序的事件。它允许对最昂贵的 cloud-init 操作进行详细分析,以确定 cloud-init 配置和设置中的长杆。这些子命令默认读取 /var/log/cloud-init.log。
analyze show按阶段解析和组织 cloud-init.log 事件,并将每个子阶段粒度包含在时间增量报告中。
$ cloud-init analyze show -i my-cloud-init.log
-- Boot Record 01 --
The total time elapsed since completing an event is printed after the "@"
character.
The time the event takes is printed after the "+" character.
Starting stage: modules-config
|`->config-emit_upstart ran successfully @05.47600s +00.00100s
|`->config-snap_config ran successfully @05.47700s +00.00100s
|`->config-ssh-import-id ran successfully @05.47800s +00.00200s
|`->config-locale ran successfully @05.48000s +00.00100s
...
analyze dump将 cloud-init.log 解析为事件记录并返回可用于其他报告需求的字典列表。
$ cloud-init analyze dump -i my-cloud-init.log
[
{
"description": "running config modules",
"event_type": "start",
"name": "modules-config",
"origin": "cloudinit",
"timestamp": 1510807493.0
},...
analyze blame将 cloud-init.log 解析为事件记录,并根据最高时间成本对其进行排序,以便快速评估可能需要改进的 cloud-init 区域。
$ cloud-init analyze blame -i my-cloud-init.log
-- Boot Record 11 --
00.01300s (modules-final/config-scripts-per-boot)
00.00400s (modules-final/config-final-message)
00.00100s (modules-final/config-rightscale_userdata)
...
analyze boot对内核进行子进程调用以获得相关的 pre-cloud-init 时间戳,例如内核启动、内核完成启动和 cloud-init 启动。
$ cloud-init analyze boot
-- Most Recent Boot Record --
Kernel Started at: 2019-06-13 15:59:55.809385
Kernel ended boot at: 2019-06-13 16:00:00.944740
Kernel time to boot (seconds): 5.135355
Cloud-init start: 2019-06-13 16:00:05.738396
Time between Kernel boot and Cloud-init start (seconds): 4.793656
分析快速入门 - LXC
要快速获取 cloud-init 日志,请尝试在任何 ubuntu 系统上使用 lxc:万乘基因发布高通量单细胞测序仪,打破海外垄断国内市场现状
$ lxc init ubuntu-daily:focal x1
$ lxc start x1
$ # Take lxc's cloud-init.log and pipe it to the analyzer
$ lxc file pull x1/var/log/cloud-init.log - | cloud-init analyze dump -i -
$ lxc file pull x1/var/log/cloud-init.log - | \
python3 -m cloudinit.analyze dump -i -
分析快速入门 - KVM
快速分析 KVM 的 cloud-init 日志:
- 下载当前云镜像
$ wget https://cloud-images.ubuntu.com/daily/server/focal/current/focal-server-cloudimg-amd64.img
- 创建快照图像以保留原始云图像
$ qemu-img create -b focal-server-cloudimg-amd64.img -f qcow2 \
test-cloudinit.qcow2
- 使用cloud-localds创建带有元数据的种子图像
$ cat > user-data <<EOF
#cloud-config
password: passw0rd
chpasswd: { expire: False }
EOF
$ cloud-localds my-seed.img user-data
- 启动修改后的 VM
$ kvm -m 512 -net nic -net user -redir tcp:2222::22 \
-drive file=test-cloudinit.qcow2,if=virtio,format=qcow2 \
-drive file=my-seed.img,if=virtio,format=raw
- 分析引导(责备、转储、显示)
$ ssh -p 2222 ubuntu@localhost 'cat /var/log/cloud-init.log' | \
cloud-init analyze blame -i -
运行单个云配置模块
该子命令不被 init 系统调用。在实例启动后,可以手动调用它来加载配置的数据源并使用缓存的用户数据和元数据运行单个 cloud-config 模块。每个 cloud-config 模块都配置了一个模块 FREQUENCY:PER_INSTANCE、PER_BOOT、PER_ONCE 或 PER_ALWAYS。当一个模块由 cloud-init 运行时,它会存储一个信号量文件, /var/lib/cloud/instance/sem/config_<module_name>.<frequency>其中标记了该模块最后一次成功运行的时间。如果该信号量文件已经运行,则该信号量文件的存在会阻止模块再次运行。为了确保模块再次运行,可以在命令行上覆盖所需的频率:
$ sudo cloud-init single --name cc_ssh --frequency always
...
Generating public/private ed25519 key pair
...
检查 cloud-init.log 以获取结果执行了哪些操作的输出。
cloud-init 的稳定版本更新 (SRU) 测试
一旦 Ubuntu 版本稳定(即在发布之后),它的更新必须遵循称为“稳定版本更新”(或SRU)的特殊程序。
cloud-init 项目在验证 cloud-init SRU 时有一个特定的过程,记录在CloudinitUpdates wiki 页面中。
cloud-init 的 SRU 测试通常执行以下操作:
- 从-proposed APT 口袋安装 cloud-init 的预发布版本 (例如bionic-proposed)
- 升级 cloud-init 并尝试干净运行 cloud-init 以断言新版本的 cloud-init 在特定平台和 Ubuntu 系列上正常工作
- 检查回溯或行为错误
手动 SRU 验证程序
以下是从-proposed手动测试 cloud-init 预发布版本的步骤
笔记
对于每个 Ubuntu SRU,Ubuntu Server 团队在以下平台上手动验证新版本的 cloud-init:Amazon EC2、Azure、GCE、OpenStack、Oracle、Softlayer (IBM)、LXD、KVM
- 在您最喜欢的平台上启动 VM,提供此云配置用户数据并将<YOUR_LAUNCHPAD_USERNAME>替换为您的用户名:
## template: jinja
#cloud-config
ssh_import_id: [<YOUR_LAUNCHPAD_USERNAME>]
hostname: SRU-worked-{{v1.cloud_name}}
- 等待当前 cloud-init 完成,将<YOUR_VM_IP>替换为您在步骤 1 中启动的 VM 的 IP 地址:
CI_VM_IP=<YOUR_VM_IP>
# Make note of the datasource cloud-init detected in --long output.
# In step 5, you will use this to confirm the same datasource is detected after upgrade.
ssh ubuntu@$CI_VM_IP -- cloud-init status --wait --long
- 在你的虚拟机上设置-proposed pocket 并升级到-proposed cloud-init:
# Create a script that will add the -proposed pocket to APT's sources
# and install cloud-init from that pocket
cat > setup_proposed.sh <<EOF
#/bin/bash
mirror=http://archive.ubuntu.com/ubuntu
echo deb \$mirror \$(lsb_release -sc)-proposed main | tee \
/etc/apt/sources.list.d/proposed.list
apt-get update -q
apt-get install -qy cloud-init
EOF
scp setup_proposed.sh ubuntu@$CI_VM_IP:.
ssh ubuntu@$CI_VM_IP -- sudo bash setup_proposed.sh
- 更改主机名,清理 cloud-init 的状态,然后重新启动以从头开始运行 cloud-init:
ssh ubuntu@$CI_VM_IP -- sudo hostname something-else
ssh ubuntu@$CI_VM_IP -- sudo cloud-init clean --logs --reboot
- 验证-proposed cloud-init 没有错误出现
# Block until cloud-init completes and verify from --long the datasource
# from step 1. Errors would show up in --long
ssh ubuntu@$CI_VM_IP -- cloud-init status --wait --long
# Make sure hostname was set properly to SRU-worked-<cloud name>
ssh ubuntu@$CI_VM_IP -- hostname
# Check for any errors or warnings in cloud-init logs.
# (This should produce no output if successful.)
ssh ubuntu@$CI_VM_IP -- grep Trace "/var/log/cloud-init*"
- 如果您在 SRU 测试期间遇到错误:
- 创建一个新的 cloud-init 错误,报告受影响的 cloud-init 版本
- 在 Libera 的#cloud-init IRC 频道上 Ping 上游 cloud-init