1. 排障前的思想准备先弄清楚nova-compute到底是怎么挂的先别急着重启服务这是很多新手甚至是老手都会犯的毛病。看到nova-compute挂了第一反应就是systemctl restart nova-compute结果发现起不来再看日志一头雾水然后反复重启直到把自己搞崩溃。我自己的习惯是碰到服务异常先花两分钟搞清楚三件事这个服务当前是什么状态、它上一次正常是什么时候、在它挂掉之前系统里发生了什么变化。有了这三条基线排查效率能高一倍。先说当前状态不是简单看一眼systemctl status nova-compute显示 failed 就完了。你要确认的是它到底是启动失败、运行中不断退出、还是活着但报错。这三者的处理思路完全不同。启动失败一般是配置、依赖或者环境层面的问题运行时退出多半是后端连接不稳定比如消息队列、数据库的偶发断连活着但报错则可能是计算节点资源问题或状态不同步。其次是时间线。如果你昨天还能正常创建虚拟机今天早上来发现服务挂了那重点就要放在昨晚到今早之间系统发生了什么。是不是有人改了配置是不是升级了内核或python包是不是磁盘被日志写满了这些信息通常能在/var/log/messages或者journalctl --since yesterday里找到线索。最后是变化点。OpenStack环境最怕的就是“什么都没动”突然出问题。但事实上很多所谓的“什么都没动”其实是别人动过没告诉你或者某个监控脚本、备份任务、系统更新在后台悄悄动了手。所以排查的第一步不是看nova自己的日志而是先看系统层面的变化。1.1 快速定位服务当前状态记录下这三条命令的输出这能给后续排查提供最基础的判断依据systemctl status nova-compute systemctl list-units | grep nova journalctl -u nova-compute --since 2024-01-01 00:00:00systemctl status会告诉你服务有没有进程活着、最近的日志是什么。list-units用来看nova全家桶的情况比如nova-api、nova-scheduler、nova-conductor是否正常方便判断问题是计算节点本身还是控制节点牵连过来的。journalctl则是看从某个时间点之后服务的完整输出比tail -f /var/log/nova/nova-compute.log更全面因为systemd会把stderr也一起收进来。这里有个容易忽略的细节很多人排查nova只看/etc/nova/nova.conf但Kolla部署的环境里nova-compute的配置往往还要看容器内部。你需要先确认部署方式再决定从哪一层开始排查。源码部署的直接看宿主机的 systemd 服务Kolla 部署的则要先docker ps看到容器状态再用docker logs来看日志。容器化部署和传统部署的排查路径有本质区别不能混为一谈。1.2 判断是配置问题还是环境问题这一步可以做个简单的小实验手动在后台启动一次nova-compute进程看它的报错输出。比如su -s /bin/sh -c nova-compute --config-file /etc/nova/nova.conf nova如果手动起不来说明是配置层面的问题比如配置文件语法错误、某个依赖包缺失、数据库密码错误等。如果能起来但systemd服务起不来那就要检查systemd的启动参数、环境变量、日志路径权限等。这个小实验能帮你把问题范围缩小一大半比盯着systemd的报错瞎猜要高效得多。2. 最常见的启动异常类型逐个击破nova-compute启动异常的报错千奇百怪但归类下来绝大多数跑不出下面这六类问题。我按出现的频率排个序后面对应每一种给出处理方案。异常类型典型报错特征出现频率数据库连接/同步问题DBConnectionError、deadlock detected高消息队列连接失败AMQP server、connect to rabbit高libvirt/KVM 环境异常libvirt error、cannot open KVM高配置参数错误Config parse error、Invalid value中资源不足/权限问题Permission denied、No space left中版本不匹配/依赖冲突ImportError、ModuleNotFoundError低2.1 数据库问题不只是连不上那么简单nova-compute启动第一步就是初始化数据库连接它会去读数据库里的API表、cell映射表等。最常见的错误就是DBConnectionError这种情况先确认数据库端口通不通、账号密码对不对。但还有一个隐蔽的问题很多人没意识到数据库表结构不一致。我记得有一次排查nova-compute日志里报的是某个表找不到字段怎么查数据库账号权限都没问题后来发现是因为控制节点升级了nova代码但计算节点没有跑过数据库同步命令导致代码期望的表结构和数据库里实际存在的表结构对不上。这种问题在源码头部署里格外常见尤其是没有把数据库同步纳入到升级流程里的话。处理方案是分别执行# 控制节点上执行 nova-manage api_db sync nova-manage db sync然后在计算节点或控制节点确认版本一致nova-manage --version注意nova-manage db sync要确保只在控制节点或指定的一个节点上执行不要多个节点同时跑否则可能造成数据库锁冲突。2.2 消息队列连接失败网络和账号是两大主因RabbitMQ连接失败有两种常见表现一种是完全连不上日志里直接报 Connection refused另一种是连接被莫名关闭报 AMQP server on ... closed connection一般是因为 rabbitmq 里残留了旧的连接占用了 channel。对于第一种检查三项transport_url里的IP和端口是否可达、用户名和密码是否正确、rabbitmq里是否存在对应的vhost和用户权限。你可以用一个python命令快速验证比重启服务快得多sudo rabbitmqctl list_users sudo rabbitmqctl list_permissions # 或者直接测端口 telnet mq_ip 5672对于第二种比较常见于计算节点内存压力大、RabbitMQ的keepalive机制把空闲连接断掉了。这种情况可以考虑在nova.conf中调整心跳参数[oslo_messaging_rabbit] rabbit_retry_interval1 rabbit_retry_backoff2 rabbit_interval_max30 rabbit_max_retries0这几个参数的含义分别是重连时间间隔、退避时间、最大间隔和最大重试次数。rabbit_max_retries0是表示无限重试适合不愿手工干预的生产环境。不过调参只是缓解本质还是要查清为什么连接被断开比如网络拨动、防火墙会话超时等。2.3 libvirt/KVM异常计算节点最容易踩的坑nova-compute要管理虚拟机底层必须能跟libvirt通信。常见的报错有几种Cannot connect to hypervisor URI说明libvirtd没起来或socket权限不对KVM is not available说明CPU虚拟化没有被正确暴露或模块没加载operation failed: Cannot get interface MTU on ...通常是网络配置引起处理思路是先把libvirtd服务状态查清楚systemctl status libvirtd virsh list --all ls /dev/kvm看到/dev/kvm不存在的话就要检查内核模块lsmod | grep kvm modprobe kvm_intel # Intel CPU modprobe kvm_amd # AMD CPU一个很隐蔽的坑是有些物理机虽然BIOS里开了虚拟化但宿主机内核是用了不支持kvm的配置编译的或者操作系统是跑在虚拟机里的没有嵌套虚拟化。这种时候就算模块加载成功创建虚机也会报虚拟机CPU模式不支持等问题。检查方法grep -E vmx|svm /proc/cpuinfo如果这里没有输出说明CPU不支持或虚拟化没开启后面再怎么配nova也白搭。2.4 配置参数错误一条参数让你排查一天配置错误往往是最隐蔽的因为nova启动的时候不会把整个配置文件的错误一次性全报出来有些参数是临到用时才报错。最常见的坑是my_ip配置不对。my_ip是用来标识计算节点管理IP的nova-compute启动时会用这个IP去跟控制节点通信、注册资源。如果配成了None或者一个无法路由的地址日志里会出现网络相关的一堆诡异错误但不会直接说“你的my_ip错了”。检查命令nova-manage config list | grep my_ip另外还有一个高频参数是instances_path。这个路径如果不存在或者nova用户没有写权限nova-compute启动时创建虚机就失败。之前遇到过一个情况是instances_path指向的盘满了nova-compute进程可以起但一旦要创建虚拟机或做迁移就会卡住。建议把下面这段配置单独列出来核对一遍[DEFAULT] my_ip 10.0.0.11 instances_path /var/lib/nova/instances host compute01 use_cow_images True2.5 资源不足和权限问题容易被忽略的隐形杀手计算节点磁盘满是个经典问题。nova-compute启动时会在instances_path下写一些临时文件如果df -h显示这个分区用量达到100%服务会直接启动失败。有时候甚至不报磁盘满而是报一些奇怪的IO错误比如 Input/output error、Permission denied。还有SELinux的问题。如果你在计算节点上改了文件目录的上下文比如把instances_path迁移到了自定义路径但忘了给新路径设置正确的SELinux标签nova-compute访问这些文件就会被拒绝。检查方法ls -Z /var/lib/nova /data/nova_instances chcon -R -t nova_var_lib_t /data/nova_instancesKolla部署的场景SELinux大多设置为disabled但源码头部署经常遇到这个问题。3. 实操过程从日志入手一步步定位根因这部分我直接按一次完整的实战排查过程来写。假设现在有一台计算节点compute03上的nova-compute起不来我们从头走一遍。3.1 第一步抓取关键日志先给日志留档然后按时间顺序阅读journalctl -u nova-compute -n 200 --no-pager /tmp/nova-compute.log tail -100 /var/log/nova/nova-compute.log实际排障中nova-compute.log里面会有很多WARNING比如 “Not checking for newly hard reboots” 之类的这些不用管。重点看两个级别ERROR和TRACE。ERROR是错误原因TRACE里是Python的堆栈信息能定位到具体是哪个模块、哪一行代码出的问题。3.2 第二步从堆栈信息反推问题举一个常见例子nova.exception.Forbidden: Policy doesnt allow compute:get_all to be performed.这是权限配置出错policy.json里面compute:get_all规则被改坏了。处理方式比较简单要么修复policy文件要么恢复默认策略cp /etc/nova/policy.json /etc/nova/policy.json.bak # 对比默认模板后修复或者重装nova-conductor相关包生成默认配置如果你看到的是oslo_messaging.exceptions.MessagingTimeout: Timed out waiting for a reply to message ID那很可能是控制节点的nova-conductor处理不过来或者计算节点和控制节点之间的网络有问题。别一头扎进计算节点排查先去控制节点看看conductor的负载和日志。3.3 第三步验证后端依赖是否就绪依次检查数据库、消息队列、DNS解析、NTP时间同步。我按顺序贴出命令# 检查数据库连接 mysql -h db_ip -u nova -p -e select 1 # 检查RabbitMQ rabbitmqctl list_connections # 检查域名解析 getent hosts controller_hostname # 检查时间同步 chronyc tracking很多莫名其妙的问题其实出在时间同步上。nova-compute启动时会做token验证和消息队列消息配对如果计算节点和控制节点之间的时间偏差超过一定阈值认证会失败消息队列的消息也会因为timestamp不匹配而无法正常处理。现实中真的出现过因为NTP服务挂了一周导致计算节点上nova-compute每次都启动到一半就“AMQP timeout”被踢掉的情况。3.4 第四步尝试手动启动并捕获实时输出如果上面几步都没有发现明显异常别急着用systemd重启直接在命令行里前台启动nova-compute看它报什么su -s /bin/sh -c nova-compute --config-file /etc/nova/nova.conf /tmp/nova_compute_manual.log 21 sleep 30 cat /tmp/nova_compute_manual.log前台启动的好处是能看到完整的交互过程比如它会先去init数据库连接、加载driver、检查虚拟化环境再注册到控制节点。任何一个环节卡住或挂掉都能看到具体的报错信息。而且这种方式不受systemd超时机制的限制不会因为启动时间超过90秒就被systemd杀掉。3.5 第五步逐步启用调试日志如果手动启动也查不出来就打开debug日志重来一遍。修改nova.conf[DEFAULT] debug True重启服务或重新手动启动后看日志里加载了哪些配置、连接了哪些端点、做了哪些操作。Debug日志的信息量很大建议配合grep做过滤看关键环节grep -i connecting /tmp/nova_compute_manual.log | head -20 grep -i error\|traceback /tmp/nova_compute_manual.log | tail -504. 排查底层细节日志之外的另一条路日志是排障的第一手段但不是唯一手段。有些问题日志里只会出现一个笼统的 “Failed to start nova-compute.service: Unit not found” 或者 “Operation not permitted”但真正的原因藏在系统底层。这时候需要换个思路。4.1 systemd层面的限制先说一个坑systemd对服务的超时和资源限制会导致误判。TimeoutStartSec默认是90秒如果你的计算节点配置了很大的磁盘阵列nova-compute启动时要初始化所有卷组、加载所有driver时间很容易超过90秒。然后systemd就直接显示start failed但你去查nova的实际启动日志它还在慢慢跑。处理办法是在service文件里把超时调大[Service] TimeoutStartSec300 TimeoutStopSec300另外检查LimitNOFILE和LimitNPROC是否足够。计算节点上nova-compute要管理大量虚拟机需要打开的文件描述符数量很大。如果limit太低跑到一半就报 “Too many open files”。建议设置[Service] LimitNOFILE65536 LimitNPROC655364.2 检查apparmor和SELinux这个排障方向常被忽略尤其是Ubuntu上默认的apparmor。有时候nova-compute的日志里报的是libvirt连接失败但真正原因是apparmor把libvirtd给限制住了。检查方式aa-status sudo aa-complain /usr/sbin/libvirtd sudo aa-complain /usr/bin/qemu-system-x86_64临时解决可以直接set complain mode但生产环境建议还是把正确的profile写好或者干脆关闭对libvirtd的限制。4.3 内核模块和IO调度器有些环境的nova-compute启动异常其实和IO有关。比如系统盘IO饱和nova-compute初始化时读写数据库、检查虚拟机镜像如果IO长时间阻塞服务进程会变得不可用被systemd或其他健康检查探测到就标记为失败。这种情况看iostat -x 1能发现%util经常达到100%。处理上可以考虑调整IO调度器比如从cfq改成noneNVMe场景或mq-deadline企业级SATA场景echo none /sys/block/sda/queue/scheduler不过这只是缓解真正要解决的是磁盘IO瓶颈比如确认是否有其他应用在打满磁盘、日志文件是否太大、是否需要扩充容量。5. 常见问题速查与清洁恢复技巧5.1 问题速查表把我在实际运维和排障中遇到的高频问题整理成速查表方便你直接对着查现象可能原因快速验证解决办法启动后立即退出数据库表不同步nova-manage db version执行nova-manage db sync报AMQP连接超时消息队列网络不通或过载telnet mq_ip 5672检查网络和rabbitmq负载报KVM不可用/dev/kvm不存在ls -l /dev/kvm加载kvm模块或开启嵌套虚拟化报Permission deniedSELinux/apparmor拦截aa-status/getenforce调整安全策略或关闭强制模式报No space left磁盘满或inode耗尽df -h; df -i清理日志、迁移instances_path报ImportErrorPython依赖缺包pip freeze | grep 包名补装或重装一致版本的依赖服务起超时systemd超时上限太低systemctl show nova-compute修改TimeoutStartSec5.2 更彻底的做法清空状态后再启动如果服务在反复挣扎中遗留了一些损坏的缓存状态单纯重启可能还是失败。可以做一次比较彻底的清理。常规步骤如下# 停服务 systemctl stop nova-compute # 备份原日志方便事后回顾 mv /var/log/nova/nova-compute.log /var/log/nova/nova-compute.log.$(date %F) # 确认没有残留进程 ps aux | grep nova-compute | grep -v grep # 重新启动观察日志 systemctl start nova-compute tail -f /var/log/nova/nova-compute.log对于Kolla部署的环境需要先停止容器再启动并清理掉容器内部的旧状态缓存docker stop nova_compute docker rm nova_compute kolla-ansible -i inventory/multinode deploy --limit compute03 -t nova注意Kolla重建服务之前最好确认一下控制节点的数据库和消息队列中没有堆积的离线计算节点数据否则启动后资源同步阶段可能出问题。5.3 一个值得尝试的技巧从模板对比配置如果别的计算节点没问题只有一个节点的nova-compute起不来那直接把正常节点的配置拉过来对比是最快的。比如diff /etc/nova/nova.conf.compute01 /etc/nova/nova.conf.compute03很多时候真的就是my_ip写错了这种小问题一眼就能在diff里看出来。这个方式对配置文件混乱的环境尤其好用。6. 别让重启掩盖真问题事后要做的事服务恢复正常不等于事情结束了。恰恰相反事后复盘才是避免下次再踩坑的关键。我每次处理完nova-compute启动异常都会强制自己做三件事第一把这次异常的时间线完整记录下来。从什么时候开始出现异常到哪个时间点确认恢复中间执行了哪些操作每一步的效果如何。这份记录不仅是文档更是下次遇到相似问题时的排障地图。第二把之前加过的临时参数、急救命令整理一遍确认哪些是长期有效的哪些只是权宜之计。比如前面提到的调大rabbit_retry_interval如果实际是防火墙导致连接被重置那调整参数只是让服务更抗造本质问题还要推动网络侧去解决。第三把计算节点的监控指标检查一遍特别是CPU、内存、磁盘IO和网络连接数。nova-compute启动异常往往不是孤立事件它背后可能是硬件即将故障、磁盘健康度告警或者网络持续抖动。把监控做好很多问题可以在用户感知之前就被提前排查掉。碰到nova-compute挂在启动阶段心态别崩。这个服务虽然依赖多、报错绕但本质上它的启动链路是固定的数据库、消息队列、libvirt、虚拟化支持、配置和权限。沿着这条链路逐项确认绝大多数问题都能在半小时内定位出来。真正让人头疼的反而是那些“服务起来了但一创建虚拟机就报错”的情况那通常意味着配置虽然能过启动检查但和底层环境的实际状态不匹配。最后分享一个小技巧把nova-compute --config-file的配置校验命令加进自己的运维脚本库每次改完配置先跑一遍再重启服务能拦截掉相当一部分低级错误。nova-manage config validate --config-file /etc/nova/nova.conf这命令虽然不能覆盖所有问题但对配置文件的合法性检查很有效尤其是批量改配置的时候能省下不少试错时间。