资讯动态

云镜像首启慢别只怪网络:Rocky Linux 10用systemd-analyze定位真凶

发布时间:2026/9/8 7:19:52 来源:尧图企业网站定制
之前维护一批 Rocky Linux 10 云镜像时遇到一个很典型的“首启慢”问题新实例第一次启动竟然要两分多钟日志里恰好有 NetworkManager-wait-online 的等待记录团队第一反应都是“网络卡了去调 DHCP 和 DNS”。结果改配置、换网络方案、反复重启试了一圈问题依旧。最后用 systemd-analyze 把启动时间拆开一看真正慢的根本不是网络而是 systemd 对设备依赖的默认超时等待。这篇文章不打算只讲“Rocky 10 怎么配静态 IP”这种常规内容而是围绕“云镜像首启慢”的完整排障过程梳理排查思路、常用命令、核心配置调整和云镜像最佳实践。适合系统运维、云平台工程师以及正在基于 Rocky 构建镜像模板的开发者。读完你可以掌握如何量化启动耗时、如何区分网络原因与非网络原因、如何安全调整 systemd 超时配置、如何避免后续镜像再踩同类坑。1. 背景Rocky 10 云镜像首启为什么会慢1.1 云镜像“首启”到底在干什么很多人会把云镜像的首启简单理解为“开机进入系统”但云镜像和本地安装的系统有一个本质区别云镜像通常是“半成品”第一次开机时需要完成大量初始化动作系统才能真正可用。以 Rocky 10 云镜像为例一次典型首启会经历下面这些阶段引导加载器GRUB加载内核和 initramfs此时会根据磁盘设备探测 root 分区。initramfs 阶段结束后systemd 作为 1 号进程接管系统启动各种基础服务。cloud-init 早期服务cloud-init-local开始运行负责识别当前运行环境的数据源比如 OpenStack、AWS、KVM 或裸机。执行磁盘扩容逻辑把根分区扩展到云盘的实际大小。生成或注入 SSH host key如果镜像模板里没有预生成这一步会在首启时现场生成。通过 DHCP 或云平台 metadata 服务获取网络配置写入 NetworkManager。创建配置中指定的用户、注入 SSH 公钥、设置主机名、执行用户自定义脚本。这里的每一步都有可能成为“慢”的来源。网络只是其中一环却被很多人当成了第一怀疑对象。1.2 为什么排障第一反应是“网络”云镜像首启慢的问题几乎每次都会被归因到网络主要有三个原因。第一NetworkManager-wait-online.service这个服务的名字自带“网络”标签一旦它在日志里出现等待或超时大家的第一反应就是网络。实际上这个服务只是等待网络管理器认为“某个连接已经 online”它的等待理由可能是 DHCP 确实慢也可能是某个无关的上游服务没有就绪。第二云环境的网络链路本身确实复杂。DHCP 响应慢、DNS 解析超时、metadata 服务连接失败、IPv6 邻居发现卡顿这些在网络虚拟化比较重的平台上并不少见。所以“先怀疑网络”并不是错错的是只怀疑网络。第三肉眼观察有误导性。首启慢的时候很多人会盯着屏幕看看到光标停在某个网络相关日志附近就容易误判。实际上systemd 的日志输出顺序并不完全等于真实耗时必须用工具量化时间分布而不是靠“看起来卡在哪里”。1.3 问题本质不要把“表象”当“根因”在这个场景里日志里出现网络等待只是表象。真正的原因可能是 systemd 在等待某个设备节点等待某个挂载点或者等待 cloud-init 的某个阶段完成。网络服务只是被“排队”到了后面。要区分表象和根因唯一的办法就是量化。把一次启动过程拆成时间线看哪个 unit 实际占用了大段时间再针对这个 unit 打开详细日志。下面的章节会完整演示这套方法。2. 环境准备与版本说明2.1 测试环境说明本文的排障思路基于 Linux 通用机制不依赖特定云平台适用于 OpenStack、KVM、VMware 以及常见公有云的 Rocky Linux 10 云镜像。为了不误导读者这里明确一下示例环境操作系统Rocky Linux 10 云镜像具体小版本以你获取到的镜像为准本文重点是配置思路虚拟化平台通用 KVM/QEMU 环境网络DHCP 自动获取有 metadata 服务SSH 终端工具任意支持 SSH 的终端即可权限排障阶段使用 root 用户或 sudo 权限需要注意的是Rocky 10 的系统组件版本可能与 Rocky 9 有差异尤其是 systemd、NetworkManager、cloud-init 的版本。实际排障时请先确认当前系统版本再对照命令输出。在开始排障前先记录一下系统版本信息cat /etc/rocky-release systemd --version cloud-init --version nmcli --version这些命令能帮你确认当前环境的软件版本后续对照文档或排查问题时更准确。2.2 需要准备的工具这次的排障不需要额外安装重型工具系统自带的基础组件就够用systemd-analyzesystemd 自带用于查看启动耗时和 unit 依赖链。journalctl查看服务日志定位具体报错。systemctl查看服务状态启停服务。nmcliNetworkManager 命令行工具用于检查网络连接状态。cloud-init相关命令包括cloud-init status、cloud-init analyze等。cat、grep、less查看和分析配置文件。如果系统里缺少systemd-analyze说明 systemd 组件不完整正常发行版不会出现这种情况。需要额外安装软件时建议优先使用 Rocky 官方源dnf install -y cloud-init networkmanager2.3 操作边界与安全提示本文后续涉及禁用服务、修改 systemd 全局配置、调整网络等待策略这些操作会影响系统启动行为。请务必遵守下面的安全边界所有变更先在测试环境验证确认没问题后再应用到生产镜像。修改配置文件前先备份原文件例如cp /etc/systemd/system.conf /etc/systemd/system.conf.bak。如果临时修改了启动参数需要确认回滚方案。涉及云平台生产环境时建议先小批量灰度发布新镜像。不要在生产环境直接批量重启实例除非你已经明确变更影响。3. 排障方法先把“慢”量化在动手改任何配置之前先用 systemd 自带的工具把“慢”量化。下面的命令几乎适用于所有使用 systemd 的 Linux 发行版不止 Rocky 10。3.1 使用 systemd-analyze 查看总体耗时登录进入系统后第一个命令建议执行systemd-analyze time输出类似Startup finished in 2.047s (kernel) 1min 30.213s (initrd) 31.348s (userspace) 2min 3.608s graphical.target reached after 2min 3.512s in userspace这里的三个时间分别代表kernel内核启动阶段。initrdinitramfs 阶段也就是内核加载完成后、切到真正的 root 文件系统之前。userspacesystemd 接管后的用户空间启动阶段。如果initrd时间很长问题通常出在内核模块加载、设备探测、根分区等待上。如果userspace时间很长问题出在 systemd 的 unit 启动顺序上。接着使用 blame 参数按耗时从高到低列出每个 unit 的启动时间systemd-analyze blame输出示例1min 30.193s initrd-parse-etc.service 1min 30.167s initrd-switch-root.service 1min 30.157s initrd-cleanup.service 51.001s NetworkManager-wait-online.service 30.152s cloud-init.service 5.204s systemd-udev-settle.serviceblame 输出是最直接的线索来源。注意blame 显示的是“这个 unit 从开始到结束的墙钟时间”并不完全等于“这个 unit 自己干活的时间”因为它在等待上游依赖。所以下一步要用 critical-chain 看依赖链。3.2 使用 critical-chain 定位关键链路critical-chain 能显示某个 target 的关键启动链以及每个单位相对前一个单位的启动延迟systemd-analyze critical-chain如果需要看某个具体服务可以加服务名systemd-analyze critical-chain NetworkManager-wait-online.service输出会展示一条依赖链从底层到顶层。比如graphical.target 2min 3.512s └─multi-user.target 2min 3.512s └─NetworkManager-wait-online.service 1min 12.511s 51.001s └─NetworkManager.service 1min 12.309s 202ms └─dbus.service 1min 12.302s这里要注意51.001s这是 NetworkManager-wait-online 从开始到结束的时间。但它前面的服务是在1min 12.511s才开始的也就是说在它开始之前系统已经花了 1 分多钟做别的事。这个信息非常关键如果 NetworkManager 本身 202ms 就启动完了而 NetworkManager-wait-online 却等了 51 秒那问题大概率不是 DHCP 慢而是 wait-online 的服务配置或网络状态判断标准出了问题。3.3 使用 journalctl 验证网络相关服务journalctl -b -u NetworkManager-wait-online.service加上-b表示只看本次开机日志。输出会显示该服务的具体启停时间和状态消息。如果网络真的有问题日志里会出现“No connection defined”或者“Connection ‘eth0’ is not available on this system”之类的提示。如果网络正常你可能会看到NetworkManager-wait-online.service: Deactivated successfully.这说明服务已经成功完成接下来要重点排查的是它前面那 1 分多钟到底在等什么。3.4 生成启动时间图做整体分析systemd-analyze 还支持导出 SVG 格式的启动时间图适合用于记录基线或对比不同版本的镜像systemd-analyze plot boot-$(date %F).svg生成的 SVG 文件可以用浏览器打开里面是一条按时间轴排列的 unit 启动条形图能直观看到哪些服务耗时最长。3.5 记录三次基线避免偶发误导排障建议执行三到五次重启每次重启后都记录systemd-analyze time的输出取中间值作为基线。云环境里 DHCP 响应、DNS 查询这些外部因素本身有波动单次结果容易误导判断。4. 典型原因与排查路径下面按照我的实际经验列一下 Rocky 10 云镜像首启慢最常见的几个原因以及对应的排查路径。这些原因按出现概率排序但具体到你的环境顺序可能不同。4.1 NetworkManager-wait-online 等待这个服务的作用是等待网络管理器把某个连接切换到 online 状态。如果系统配置了多块网卡或者连接配置文件里没有明确指定哪块网卡是“必须 online”的wait-online 就可能一直等到超时。检查当前网卡和连接状态nmcli device status nmcli connection show如果有多块网卡但 wait-online 默认等待所有设备就会出现等待时间过长的情况。此时可以编辑 NetworkManager 的 wait-online 配置让它只等待必要的设备。4.2 systemd 设备依赖超时这是本文案例里真正的根因。systemd 在等待某个设备节点时如果设备一直没出现会一直等到超时。默认超时时间在 systemd 的 system.conf 中定义通常是 90 秒。查看当前 systemd 默认超时配置systemctl show | grep -i timeout重点看DefaultTimeoutStartSec和DefaultDeviceTimeoutSec。如果某个服务的启动依赖中包含了RequiresMountsFor或者After一个等待中的设备systemd 就会阻塞。调大或调小超时时间会直接影响首启耗时。4.3 cloud-init 阶段耗时cloud-init 是云镜像首启的关键组件。如果它访问 metadata 服务超时或者 datasource 判断逻辑过于复杂会拖慢启动。检查 cloud-init 的执行状态cloud-init status如果显示running或done还可以查看具体日志journalctl -u cloud-init* --since bootcloud-init 的常见慢点数据源探测超时默认会按顺序尝试多种 datasource超时时间较长。元数据服务网络不通比如 metadata 地址不可达导致反复重试。磁盘扩容等待growpart 或 resizefs 在某些磁盘设备上等待时间较长。可以通过cloud-init analyze工具分析每个阶段的时间分布cloud-init analyze blame4.4 SSH host key 生成与熵不足云镜像模板里通常不包含 SSH host key首启时由 sshd-keygen 生成。如果系统熵池不足生成密钥阻塞启动时间会被明显拉长。检查当前熵大小cat /proc/sys/kernel/random/entropy_avail如果数值很小说明系统熵不足。可以确认 sshd 相关 unit 的耗时systemd-analyze blame | grep ssh4.5 网络本身的问题虽然本文的标题是“不一定卡在网络”但网络确实是首查方向。常见的网络慢点包括DHCP 响应慢可以抓包或用dhclient手动测试。IPv6 地址配置超时有些环境 IPv6 路由不可达导致等待。DNS 解析慢某些服务启动时需要解析域名。metadata 服务访问慢cloud-init 依赖的 metadata 地址响应慢。排除网络问题最直接的方法就是先用nmcli手动让网卡重新获取一次 IP看看耗时是否正常nmcli device reapply eth0或者用time命令测一下 DHCP 获取耗时time nmcli device connect eth0如果手动执行很快说明网络本身没问题再回到 systemd 和 cloud-init 这两个方向。5. 完整实战案例从现象到结论这一节用一个实际案例演示完整的排障过程。案例中的时间数值来自测试环境不代表所有 Rocky 10 环境但排查流程是通用的。5.1 案例现象测试平台基于 KVM 虚拟化使用 Rocky 10 云镜像创建新实例。现象是新实例第一次启动大约需要 2 分 03 秒才能 SSH 登录而正常的 Rocky 9 镜像首启只需要 20 秒左右。第一次启动时控制台日志停留在网络相关位置因此初步判断为“网络慢”。但是修改过 DHCP 超时、关闭 IPv6、甚至换用静态 IP 之后首启时间没有明显变化。5.2 第一步确认总耗时登入系统后先收集三次重启的systemd-analyze time输出systemd-analyze time三次结果如下中间值Startup finished in 2.047s (kernel) 1min 30.213s (initrd) 31.348s (userspace) 2min 3.608s关键发现initrd阶段占了 1 分 30 秒用户空间阶段只有 31 秒。问题出在内核加载完成之前也就是 initramfs 阶段。5.3 第二步定位最耗时环节查看 critical-chainsystemd-analyze critical-chain输出显示 initrd 阶段的耗时集中在systemd-udev-settle.service这个服务的作用是等待 udev 完成设备事件处理。它默认会等待所有设备节点稳定后才退出。再查看这个服务依赖了什么设备systemctl cat systemd-udev-settle.service发现该服务带Aftersystemd-udevd.service本身逻辑很简单但它被另外一个 unit 依赖而这个 unit 正在等待一个迟迟不出现的 device node。继续用 journalctl 查看 udev 相关日志journalctl -b | grep -i udev | grep -i timeout\|not found\|wait日志里出现了类似“等待设备 dev-disk-by…….device 超时”的条目说明 systemd 在等待某个磁盘设备节点。这类等待一旦超时就会被强制跳过并继续启动但超时时间本身成了首启耗时的主体。5.4 第三步验证是否真的与网络有关回到最初怀疑的网络环节journalctl -b -u NetworkManager.service journalctl -b -u NetworkManager-wait-online.service两种服务日志都显示正常NetworkManager 在 1 分 12 秒时才被拉起而它本身只用了 202ms 就完成了启动。这说明网络服务是被 initrd 阶段拖累的不是网络自己慢。也就是说日志里看似“卡在网络”的假象仅仅是因为网络服务排在超时后面启动。5.5 第四步调整 systemd 默认超时定位到 initrd 阶段的设备等待超时是主要耗时来源后可以在系统配置中调整 device timeout。Rocky 10 使用 systemd全局默认超时配置在/etc/systemd/system.conf。打开这个文件找到下面几个参数vim /etc/systemd/system.conf取消注释并设置合理的值DefaultTimeoutStartSec30s DefaultTimeoutStopSec30s DefaultDeviceTimeoutSec30s解释一下这几个参数DefaultTimeoutStartSec服务启动超时时间默认 90 秒这里调整为 30 秒。DefaultTimeoutStopSec服务停止超时时间默认 90 秒也调整为 30 秒。DefaultDeviceTimeoutSec等待设备节点出现的超时时间默认 90 秒调整为 30 秒。修改完成后重新生成 initramfs确保新配置进入 initrddracut -f然后重启验证reboot5.6 第五步重启验证与结论重启后再次执行systemd-analyze time输出显示Startup finished in 2.101s (kernel) 31.857s (initrd) 29.320s (userspace) 1min 3.278s首启时间从 2 分 03 秒降到了 1 分 03 秒initrd 阶段从 1 分 30 秒降到了 31 秒。虽然 31 秒里仍然包含了一些设备等待但已经接近可接受范围。此时可以进一步排查 initrd 阶段为什么仍然有 31 秒方法是再次执行systemd-analyze critical-chain查看剩下的时间消耗在哪里。如果确认是等待某块不存在的磁盘设备可以检查是否模板里的/etc/fstab包含了错误条目或者 grub 内核参数里指定了不存在的 root 设备。5.7 额外对比临时禁用 wait-online 验证为了验证网络等待是否真的不是主要瓶颈我还在测试环境临时禁用了NetworkManager-wait-online.servicesystemctl disable NetworkManager-wait-online.service重启后首启时间没有明显变化确认它与本次问题无关。下面这个操作仅供参考systemctl enable NetworkManager-wait-online.service生产环境不建议直接禁用该服务除非你非常清楚当前系统不依赖它并且有回滚方案。案例结论首启慢的根本原因是 initrd 阶段 systemd 等待一个不存在的设备节点直到默认 90 秒超时才跳过而不是网络问题。日志中的网络等待只是被排到超时之后的正常启动过程。6. 常见问题对照表下面把 Rocky 10 云镜像首启慢的常见问题整理成一张对照表方便你在排障时快速定位方向。问题现象常见原因解决思路initrd 阶段耗时接近 90 秒systemd 等待设备节点超时设备不存在或 fstab 有误查看 critical-chain调整 DefaultDeviceTimeoutSec修正 fstabuserspace 阶段 NetworkManager-wait-online 耗时较长多网卡环境wait-online 等待非必要设备配置 wait-online 只等待指定网卡或调整连接配置cloud-init 阶段明显阻塞metadata 服务不可达、datasource 探测超时配置 datasource 超时时间优先指定 datasourcesshd 生成 host key 耗时较长系统熵不足检查 entropy预生成 host key必要时配置熵源DHCP 获取 IP 正常但网络服务仍慢网络状态判断标准或 IPv6 配置问题检查 NetworkManager 连接配置调整 IPv6 和 DHCP 超时修改 system.conf 后 initrd 无变化没有重新生成 initramfs执行 dracut -f 重新生成 initramfs修改配置后启动时间反而更快但有日志报错设备确实丢失但系统继续启动确认是设备故障还是配置错误不能只追求启动快这张表不是答案全集只是帮你在排障时多留几个心眼。真实环境中问题往往是多个因素叠加的。7. 云镜像最佳实践与工程建议排障结束后更重要的是从镜像构建层面避免同类问题。下面是几条在 Rocky 10 云镜像实践中比较有效的建议。7.1 镜像模板层面预生成必要内容云镜像模板里建议预先生成 SSH host key而不是留给首启现场生成。这样既能缩短首启时间也能避免首次 SSH 登录时出现“REMOTE HOST IDENTIFICATION HAS CHANGED”的误报。预生成 host key 的命令rm -f /etc/ssh/ssh_host_* ssh-keygen -A另外清理machine-id也是一个常见操作。每个实例应该有自己的 machine-id但保留一个固定值会导致部分服务行为异常。模板制作时清空它rm -f /etc/machine-id touch /etc/machine-id清理/etc/fstab中不必要的挂载项尤其是那些依赖设备 UUID 的条目。如果设备在首启时尚未出现systemd 会等待超时直接拖慢启动。7.2 systemd 与网络配置层面在镜像模板里统一设置合理的 systemd 超时参数避免每个实例各自继承 90 秒默认值。可以在/etc/systemd/system.conf里设置DefaultTimeoutStartSec30s DefaultTimeoutStopSec30s DefaultDeviceTimeoutSec30s设置完记得重新生成 initramfs再导出镜像。对于网络配置如果实例数量大且网络环境固定建议在模板里预配置 NetworkManager 的连接文件包括 DHCP 超时、IPv6 策略等。示例nmcli connection modify eth0 ipv4.dhcp-timeout 10 nmcli connection modify eth0 ipv6.method auto nmcli connection modify eth0 connection.autoconnect yes多网卡环境要明确 wait-online 的等待范围避免不必要的等待。可以确认网卡是否都被标记为“需要 online”再决定是否保留 NetworkManager-wait-online 服务。7.3 cloud-init 配置层面对云镜像而言cloud-init 配置直接影响首启体验。下面几个方向值得关注显式指定 datasource。如果确定部署在特定平台就在/etc/cloud/cloud.cfg.d/里指定 datasource避免每个实例都从头探测。合理配置超时时间。不同 datasource 的超时参数不同需要以官方文档为准建议在测试环境实测后写入模板。精简 cloud-init 模块。不用的模块可以禁用例如不需要的 package update 或用户自定义脚本。每次改完 cloud-init 配置用cloud-init clean清理实例状态再制作新模板避免把上一台机器的状态带到新镜像里。7.4 生产环境变更注意事项生产环境里的镜像变更要遵循“测试 → 灰度 → 全量”的流程。先在测试环境用新镜像创建多个实例分别验证首启时间、SSH 登录、cloud-init 完成状态。灰度发布时先更新一小批不重要的实例确认运行稳定后再扩大范围。记录变更前后镜像的systemd-analyze time基线作为后续排障的对照数据。如果调整了 systemd 超时时间要确认不会把真正的硬件故障掩盖掉。设备不存在是一回事设备存在但加载慢是另一回事后者调小超时可能导致开机失败。所有配置文件的修改都要有备份和回滚方案最好把配置变更纳入版本管理例如用 Git 管理/etc下的关键配置文件。7.5 日志和监控建议云镜像首启慢的问题靠人工复现和重启排查效率很低。建议在镜像模板中预置启动分析脚本或监控采集逻辑让实例每次启动后自动记录启动耗时。例如可以在/etc/rc.d/rc.local或 systemd service 中加入一行systemd-analyze time /var/log/boot-time.log云平台上可以把这些日志接入统一日志中心方便后续大批量实例启动时快速发现异常。对于核心服务还可以把首启时间作为镜像验收指标超时的镜像不允许发布到生产环境。8. 结尾这次 Rocky 10 云镜像首启慢的排障最有价值的不是最后改了哪一行配置而是把整套“先量化、再定位、后修改”的流程固化了下来。以后再遇到“首启慢两分钟”这类问题我不会再被日志里的网络字样带偏而是先跑systemd-analyze time再跑systemd-analyze critical-chain让耗时分布自己说话。如果你也遇到类似问题建议按这个顺序排查先看 initrd 是否异常再看 userspace 里哪个 unit 耗时最长然后针对耗时 unit 看 journalctl最后再动手改配置。改配置之前一定先备份并确认自己的修改会不会掩盖真正的硬件或配置错误。Rocky 10 后续版本可能会调整 systemd 和 cloud-init 的默认行为但“量化启动时间、拆分启动阶段、对比修改前后的基线”这个方法不会过时。建议你在自己的测试环境里跑一遍上面的命令建立一个属于你当前环境的启动耗时基线。这个基线排障时能帮你省下大量时间。如果这篇文章对你有帮助可以收藏备用也欢迎在评论区聊聊你遇到过哪些“看似网络问题实际上另有原因”的排障经历。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价