虚拟化容器,大数据,DBA,中间件,监控。

OpenStack 2025.2 (Flamingo) 运维手册

19 10月
作者:admin|分类:容器虚拟化

OpenStack 2025.2 (Flamingo) 运维手册

主机 open88 | openEuler 25.09 | Python 3.11.13 | 全部软件与数据落盘 /data

本手册基于本仓库的实际部署成果整理:组件简介 → 运维命令 → 故障解决 → 速查附录。 与 OpenStack-2025.2-Flamingo-部署文档.md 的分工是: 部署文档讲「怎么装」,本手册讲「装好之后怎么用、怎么看、怎么修」。


文档导航

章节内容适用场景
1. OpenStack 简介定位、核心抽象、组件架构、请求链路建立整体认知
2. 运行环境与运维约定安装路径、凭据、服务清单、统一操作方式每次登录机器前扫一眼
3. 各组件运维命令keystone/glance/placement/nova/neutron/horizon/cinder日常巡检与操作
4. 故障解决方法分层诊断法 + 各服务真实故障案例(含深度剖析)出问题时按图索骥
5. 附录端口、路径、单元、自检清单、危险操作随手查

1. OpenStack 简介

1.1 它是什么

OpenStack 是一套开源的云计算基础设施管理平台(IaaS)。它不产生算力,而是把一堆物理资源 (CPU、内存、磁盘、网络)抽象成可编程的 API,再以「项目(Project)→ 资源配额 → 实例/卷/网络」 的模型交付给用户。可以把它理解为数据中心的操作系统:

  • 对上:提供 REST API + Web 控制台 + CLI,一切操作都可脚本化;

  • 对下:驱动 libvirt/KVM、LVM/iSCSI、OVS/Linux bridge、MariaDB、RabbitMQ 等既有系统组件;

  • 对内:各服务互相通过 keystone 认证、通过消息队列解耦,可独立部署与横向扩展。

本仓库使用的是 2025.2 (Flamingo) 发行版,以源码 tarball + venv 方式部署在单节点上, 共 7 个服务,属于「最小可用集群」,适合学习、验证与轻量自用。

1.2 五个必须先理解的概念

概念含义本环境取值
Region地理/逻辑分区,一套端点集合RegionOne
Service / Endpoint服务类型与访问地址,注册在 keystone 的服务目录中见 5.1 端口表
Domain用户与项目的命名空间,多租户隔离的顶层Default
Project(Tenant)资源归属与配额单位;实例、卷、网络都属于某个项目admin、service 及自建项目
User / Role身份与权限;角色决定 API 能否通过 policy 校验admin、service、member、reader

一条最常见的误解:OpenStack 里的资源不"属于节点",而"属于项目"。所以排障时先问 「这个实例属于哪个项目、用哪个 token 操作的」,比问「它跑在哪台机器」更有效。

1.3 组件架构与职责

                    ┌──────────────────────────────────────────┐
  用户/CLI/浏览器 →│ horizon (:80/dashboard)  Web 控制台        │
                   └──────────────────┬───────────────────────┘
                                      │ REST (token)
  ┌───────────────────────────────────▼───────────────────────────────────┐
  │                     keystone (:5000/v3)  认证 + 服务目录               │
  └───────┬───────────────┬───────────────┬───────────────┬───────────────┘
          │               │               │               │
    ┌─────▼─────┐   ┌─────▼─────┐   ┌─────▼──────┐  ┌─────▼──────┐
    │ glance    │   │ placement │   │ nova       │  │ cinder     │
    │ :9292     │   │ :8778     │   │ :8774/8775 │  │ :8776      │
    │ 镜像       │   │ 资源账本   │   │ 计算       │  │ 块存储     │
    └───────────┘   └───────────┘   └─────┬──────┘  └─────┬──────┘
                                          │               │
                                    ┌─────▼──────┐  ┌─────▼──────┐
                                    │ libvirtd   │  │ LVM + iSCSI│
                                    │ KVM/QEMU   │  │ loop 卷组   │
                                    └─────┬──────┘  └────────────┘
                                          │
    ┌─────────────────────────────────────▼─────────────────────────────┐
    │ neutron (:9696)  OVS agent / DHCP agent / L3 agent / metadata agent │
    └───────────────────────────────┬───────────────────────────────────┘
                               Open vSwitch(br-int ↔ br-provider)
                                          │
                                    br0 + veth 对 → 物理 LAN

各组件一句话定位 + 本机进程形态(决定了你怎么启停它):

组件职责进程形态单元 / 入口关键配置
keystone认证、授权、服务目录、令牌签发httpd + mod_wsgihttpd / :5000/etc/keystone/keystone.conf
glance镜像的存储与元数据systemd 独立进程glance-api / :9292/etc/glance/glance-api.conf
placement计算资源库存与分配账本httpd + mod_wsgihttpd / :8778/etc/placement/placement.conf
nova实例生命周期、调度、控制台API 走 httpd;调度/计算走 systemdhttpd / :8774、:8775、nova-{scheduler,conductor,compute,novncproxy}/etc/nova/nova.conf
neutron二层/三层网络、DHCP、元数据通道systemd 多进程neutron-{rpc-server,openvswitch-agent,dhcp-agent,l3-agent,metadata-agent} / :9696/etc/neutron/*
horizonWeb 控制台httpd + mod_wsgihttpd / :80/dashboardlocal_settings.py
cinder卷的创建/挂载/快照systemd 独立进程cinder-{scheduler,volume,volumes-loop} / :8776/etc/cinder/cinder.conf

⚠️ 排障第一原则:先分清服务是「httpd 里的 WSGI 应用」还是「独立 systemd 进程」。 keystone / placement / nova-api / horizon 的问题常出在 httpd 权限与 Python 路径, 而不是 systemctl status 里那个 OpenStack 服务名——它们根本没有同名单元。

1.4 一次操作背后的完整链路

以「创建一台实例」为例,理解这条链路就理解了 90% 的故障定位点:

1. 认证    openstack CLI → keystone:5000 换取 X-Subject-Token(含 roles/scope)
2. 取目录  token 中的 service catalog → 得到 nova 端点 http://controller:8774/v2.1
3. 提交    POST /servers → nova-api(httpd + mod_wsgi)写 nova_api 库
4. 调度    nova-scheduler 读 placement 的库存 → 选主机(open88)
5. 消息    nova-conductor → RabbitMQ → nova-compute
6. 资源    nova-compute 调 glance 下载镜像、调 neutron 建 port、通过 privsep 调 libvirt
7. 网络    neutron OVS agent 把 veth 接入 br-int;L3/DHCP agent 建 qrouter/qdhcp 命名空间
8. 回写    compute 逐阶段上报 → DB 状态 ACTIVE;neutron 发 network-vif-plugged 通知 nova

任何一个箭头断掉,现象都可能是「实例 ERROR」或「一直 BUILD」,所以必须按链路自底向上查, 不能看到 ERROR 就只翻 nova 日志(详见 4.1 分层诊断法)。

1.5 本环境的边界(务必知道哪些"不是故障")

限制运维含义
单节点,未验证多计算节点/HA不要照搬多控文档中的 nova-manage cell_v2 扩容步骤
cinder 用单机 loop 文件做卷组,无副本、无 backup卷数据无冗余,宿主机磁盘损坏即丢卷;volumes.img 不可删除
libvirt 未开 autostart宿主机重启后实例是 SHUTOFF,需手动启动或改配置(见 4.10)
单网卡,管理面与实例出口共用 enp2s0网络改动有断网风险,见 5.5 危险操作
镜像已做 shrink 优化,元数据写回 DB换镜像文件必须同步 size/virtual_size/checksum,否则 glance 404/损坏

2. 运行环境与运维约定

2.1 路径约定(全部在 /data)

/data/
├── admin-openrc.sh                 # admin 凭据(权限 600,仅 root 可读)
├── src/                            # 各服务源码包
└── openstack/
   ├── venv/                       # 唯一的 Python 运行时(所有 CLI 都在 venv/bin)
   ├── mysql/                      # MariaDB datadir + mysql.sock
   ├── rabbitmq/{mnesia,log}/
   ├── keystone/{fernet-keys,fernet-keys-receipts,credential-keys}/
   ├── glance/images/              # 镜像文件实体
   ├── placement/wsgi.py
   ├── nova/{wsgi,lock,instances}/
   ├── neutron/                    # 含各 *.log
   ├── cinder/{volumes.img,...}    # loop 卷文件
   └── horizon/{wsgi,static,error.log}
类别路径
配置文件/etc/{keystone,glance,placement,nova,neutron,cinder}/
httpd vhost/etc/httpd/conf.d/{keystone,placement,nova,neutron,horizon,cinder}.conf
systemd 单元/usr/lib/systemd/system/<服务>.service
运维脚本/usr/local/sbin/br0-provider-veth.sh、/root/{phase1-br0,net-watchdog}.sh

为什么要反复强调 /data:Python 包、数据库、镜像、卷、日志全在这里。磁盘满、权限错、 或者 SELinux/属主不对,故障会以「看似无关的模块导入失败」形式出现——见 4.2。

2.2 每个 shell 会话开始时的两行准备

export PATH=/data/openstack/venv/bin:$PATH   # 让 openstack / nova-manage / glance-manage 可用
source /data/admin-openrc.sh                  # 注入 OS_* 认证变量(文件为 600)

权限提醒:/data/admin-openrc.sh 只应 root 可读;若被手工改过,恢复为 chmod 600 /data/admin-openrc.sh。

若没有现成的 openrc,可手工导出:

export OS_AUTH_URL=http://controller:5000/v3 OS_IDENTITY_API_VERSION=3
export OS_USERNAME=admin OS_PASSWORD=ADMIN_PASS
export OS_PROJECT_NAME=admin OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default OS_REGION_NAME=RegionOne

自检三连(任何操作前先确认地基是通的):

openstack token issue -f value -c expires          # 认证 OK 才有输出
openstack service list -f value -c Name            # 服务目录完整
openstack endpoint list --interface public -f value -c "Service Name" -c URL

2.3 服务清单与统一操作

本机共 18 个相关单元(基础 6 + OpenStack 12 + 网络自愈 1):

层次单元
基础mariadb、rabbitmq-server、memcached、openvswitch、libvirtd、httpd
OpenStackglance-api、nova-{compute,conductor,scheduler,novncproxy}、neutron-{rpc-server,openvswitch-agent,dhcp-agent,l3-agent,metadata-agent}、cinder-{scheduler,volume,volumes-loop}
网络自愈br0-provider-veth

统一的四条命令(把 <unit> 换成上表任意单元):

systemctl status <unit> --no-pager -l     # 状态 + 最近日志尾部
systemctl restart <unit>                  # 重启
journalctl -u <unit> -n 200 --no-pager    # systemd 视角日志(含启动失败原因)
systemctl enable --now <unit>             # 开机自启并立即启动

一次看全(巡检最常用):

systemctl --failed                                   # 只看失败的,空输出=健康
systemctl list-units --type=service --state=running | grep -E \
 'glance|nova|neutron|cinder|httpd|mariadb|rabbitmq|memcached|openvswitch|libvirtd'
systemctl is-active br0-provider-veth

不要用 nohup 起服务:宿主会话断开后进程会被回收,表现为「昨天还好好的,今天全没了」。 一律交给 systemd。

2.4 服务健康的三层判据

不要只看 systemctl is-active,它只能说明进程在。分层看:

# 第 1 层:进程在不在
systemctl is-active glance-api nova-compute neutron-openvswitch-agent cinder-volume

# 第 2 层:API 通不通(返回码,不看 body)
for p in 5000 9292 8778 8774 8775 9696 8776 80; do
 printf '%5s -> ' $p; curl -s -o /dev/null -w '%{http_code}\n' --max-time 3 http://controller:$p/ \
   || echo timeout
done

# 第 3 层:各服务自报的家底(agent/后端是否注册、是否 up)
openstack compute service list                   # nova-scheduler/conductor/compute
openstack network agent list                     # OVS/DHCP/L3/Metadata 四个 agent
openstack volume service list                    # cinder-scheduler/cinder-volume
openstack hypervisor list                        # 计算节点是否 up

第 3 层最关键:active (running) 却不注册,是本版本最常见的坑(例如缺 neutron-rpc-server、 cinder 卷组不存在),此时第 1、2 层都是"绿"的。

2.5 日志地图

OpenStack 日志完全分散在 /data/openstack/ 与 /var/log/ 两处,记住这张表能省一半排查时间:

服务日志路径适配场景
httpd(keystone/placement/nova-api/horizon)/var/log/httpd/{error_log,<vhost>_error.log}、<vhost>_access.log500/403、WSGI 导入错误
keystone/var/log/httpd/keystone_*.log(WSGI 无独立日志)认证失败、token 问题
glance/data/openstack/glance/glance-api.log镜像上传/下载失败
placement/var/log/httpd/placement_*.log调度报 409/资源不足
nova/data/openstack/nova/{nova-compute,nova-api-wsgi,nova-conductor,nova-scheduler}.log实例错误、privsep
neutron/data/openstack/neutron/{neutron-server,openvswitch-agent,dhcp-agent,l3-agent,metadata-agent,rpc-server}.log网络创建、端口绑定
cinder/data/openstack/cinder/{cinder-volume,cinder-scheduler,cinder-api-wsgi}.log卷创建/挂载失败
horizon/data/openstack/horizon/error.log、/var/log/httpd/horizon_*.log页面 500、按钮消失
libvirt/QEMU/var/log/libvirt/qemu/<instance>.log实例起不来、卡引导

配套查法:

tail -f /data/openstack/nova/nova-compute.log       # 边操作边看
grep -E 'ERROR|Traceback' /data/openstack/neutron/*.log | tail -50
journalctl -u nova-compute --since '10 min ago' --no-pager | tail -100
virsh domstate instance-00000004                    # 从虚拟化层看实例真实状态

3. 各组件运维命令

全章默认已执行 2.2 的两行准备: export PATH=/data/openstack/venv/bin:$PATH 与 source /data/admin-openrc.sh。 所有 <尖括号> 为占位符,替换后执行。

3.1 keystone(身份服务)

形态:httpd + mod_wsgi,入口 /data/openstack/keystone/wsgi.py,监听 :5000。 没有 keystone.service 单元——重启服务是重启 httpd,但只重启 keystone 的 vhost 更安全。

# 启停与重载(改配置后必须重载,否则仍是旧代码)
systemctl reload httpd          # 推荐:不中断其它 vhost
systemctl restart httpd         # 彻底重启(horizon/nova-api 会一起重启)
apachectl -t                    # 改完 /etc/httpd/conf.d/*.conf 先语法检查

健康检查

curl -s -o /dev/null -w '%{http_code}\n' http://controller:5000/v3          # 200
curl -s -o /dev/null -w '%{http_code}\n' http://controller:5000/v3/auth/tokens  # 405/400 也算通

# 取 token(验证口令/角色/scope 全链路)
openstack token issue -f table
openstack token issue -f value -c expires        # 令牌有效期

日常操作(用户 / 项目 / 角色)

# ---- 项目 ----
openstack project list
openstack project create --domain default --description "测试项目" demo
openstack project show demo -f yaml
openstack project set demo --disable          # 禁用(不删)
openstack project delete demo                 # 项目下有资源会拒绝

# ---- 用户 ----
openstack user list
openstack user create --domain default --project demo --password 'Str0ng!Pass' alice
openstack user set alice --password 'NewPass'  # 改密
openstack user set alice --enable / --disable
openstack user delete alice

# ---- 角色 ----
openstack role list
openstack role assignment list --user alice --project demo --names
openstack role add --project demo --user alice member
openstack role add --project demo --user alice admin     # 给项目管理员
openstack role remove --project demo --user alice admin

# ---- 服务账号(每个服务都需要 service 角色的项目成员关系)----
openstack role create service
for u in nova neutron glance placement cinder; do
 openstack role add --project service --user $u service
done

服务目录(endpoint)运维

openstack service list
openstack endpoint list --interface public -f value -c "Service Name" -c URL

# 新增/修正一个端点(例:glance)
openstack service create --name glance --description "OpenStack Image" image
for i in public internal admin; do
 openstack endpoint create --region RegionOne image $i http://controller:9292
done
# 端点地址写错时:先删再建(endpoint id 从 list 里取)
openstack endpoint delete <endpoint-id>

fernet 密钥与凭据加密

ls -l /data/openstack/keystone/fernet-keys/            # 0=staging 1..N 有效
keystone-manage fernet_rotate --keystone-user root --keystone-group root
keystone-manage fernet_setup --keystone-user root --keystone-group root   # 已存在会覆盖,慎用
keystone-manage credential_setup --keystone-user root --keystone-group root

不要删除 fernet-keys 目录:删了等价于所有 token 失效 + 加密凭据无法解密, 需要重新 fernet_setup 并让所有客户端重新认证。

数据库与升级

keystone-manage db_sync                  # 升级/初始化表结构(幂等)
keystone-manage token_flush              # 手工清理过期 token(fernet 一般不需要)
mysql -e "SELECT COUNT(*) FROM keystone.token;" 2>/dev/null   # 查 token 表(若启用 SQL 后端)

keystone 故障定位顺序::5000/v3 是否 200 → /var/log/httpd/keystone_error.log 首个 Traceback → 能否 token issue → openstack service list 是否为空(=数据库/初始化问题)。

3.2 glance(镜像服务)

形态:systemd 独立进程 glance-api,监听 :9292,镜像文件落 /data/openstack/glance/images/。

systemctl status glance-api --no-pager -l
systemctl restart glance-api
journalctl -u glance-api -n 100 --no-pager
tail -f /data/openstack/glance/glance-api.log

健康检查与镜像清单

curl -s -o /dev/null -w '%{http_code}\n' http://controller:9292        # 401/200 均可
openstack image list
openstack image list --status queued -f value -c ID -c Name   # 卡在 queued 的
openstack image show cirros -f yaml
ls -lh /data/openstack/glance/images/
du -sh /data/openstack/glance/images/                          # 容量监控

上传 / 导出 / 修改

# 上传(qcow2 最常见)
openstack image create --disk-format qcow2 --container-format bare --public \
 --file ./openeuler.qcow2 openeuler-24.03

# 上传大镜像时优先用 --progress,避免以为卡死
openstack image create --disk-format qcow2 --container-format bare --public \
 --progress --file ./big.qcow2 bigimage

# 属性与可见性
openstack image set <image> --property hw_disk_bus=virtio
openstack image set <image> --min-disk 10 --min-ram 1024
openstack image set <image> --private / --shared / --community
openstack image set <image> --name 新名字

# 导出(下载到本地文件)
openstack image save --file ./backup.qcow2 <image>

# 删除
openstack image delete <image>

换镜像文件后同步元数据(本仓库特有流程)

镜像做过 shrink 优化后,替换文件必须同步数据库,否则下载得到损坏文件或 404:

# 1) 计算新文件的三个值
NEW_SIZE=$(stat -c %s /data/openstack/glance/images/<file>)
NEW_MD5=$(md5sum /data/openstack/glance/images/<file> | cut -d' ' -f1)
NEW_SHA=$(sha256sum /data/openstack/glance/images/<file> | cut -d' ' -f1)
NEW_VSIZE=$(qemu-img info --output=json /data/openstack/glance/images/<file> | \
           python3 -c 'import sys,json;print(json.load(sys.stdin)["virtual-size"])')

# 2) 写回 glance 库(无 openstackclient 时的直改法)
mysql glance -e "UPDATE images SET size=$NEW_SIZE, virtual_size=$NEW_VSIZE,
 checksum='$NEW_MD5', os_hash_algo='sha512', os_hash_value='$NEW_SHA'
 WHERE id='<image-id>';"


# 3) 重载服务并校验
systemctl restart glance-api
openstack image show <image> -f value -c size -c checksum -c virtual_size

checksum 字段是 md5(varchar32),os_hash_value 是 sha256/sha512,两者不能混。 openstack image save 后务必比对本地 md5 与 openstack image show -c checksum。

glance 常见专属问题

症状检查
上传中断变 queued/savingopenstack image delete 后重传;查磁盘空间 df -h /data
下载 404 但 DB 有记录文件不在 /data/openstack/glance/images/,或 filesystem_store_datadir 配错
下载后镜像校验失败元数据(size/checksum)与实体文件不一致 → 按上面流程同步
401 无法认证/etc/glance/glance-api.conf 的 auth_url 必须带 /v3

3.3 placement(放置服务)

形态:httpd + mod_wsgi,入口 /data/openstack/placement/wsgi.py,监听 :8778。 配置段名必须是 [placement_database](不是 [database]),这是初次部署最常见的启动失败原因。

systemctl reload httpd
tail -100 /var/log/httpd/placement_error.log
placement-manage db sync            # 建表/升级

健康检查(必须带 token)

TOKEN=$(openstack token issue -f value -c id)
curl -s -o /dev/null -w '%{http_code}\n' -H "X-Auth-Token: $TOKEN" http://controller:8778/   # 200

资源账本查询(判断"为什么调度失败"的第一现场)

# 资源提供者清单
openstack resource provider list

# 某节点总容量 / 已用 / 剩余
openstack resource provider inventory list <rp-uuid>
openstack resource provider usage show <rp-uuid>

# 分配明细(谁占用了这些资源)
openstack resource provider allocation show <rp-uuid>

# 查看某台计算节点的资源类
openstack resource class list

典型判断:

usage 现象含义
VCPU: 0 却报 No valid host不是资源不足,查 nova-scheduler.log 的过滤原因(聚合/可用域/PCI)
MEMORY_MB 接近 total真的没内存,删实例或调 ram_allocation_ratio
资源提供者缺失nova-compute 未成功启动或未上报,查 compute 日志

placement 专属故障

症状根因修复
RequiredOptError: value required for option connection in group [placement_database]段名写成 [database]改 /etc/placement/placement.conf 为 [placement_database]
API 500 NoSuchOptError: no such option enforce_scope新版 oslo.policy 移除该选项改 placement/deploy.py:if not getattr(conf.oslo_policy, 'enforce_scope', True):
openstack server create 报 409 Conflict: Inventory for ...资源提供者库存未生成重启 nova-compute 触发 discover_hosts 上报

3.4 nova(计算服务)

形态:API 走 httpd(nova-api vhost,:8774 计算 API、:8775 metadata); 调度/数据库代理/计算/控制台代理是 4 个独立 systemd 单元。

单元端口作用挂了的现象
httpd(nova vhost)8774 / 8775接收 API、注入 metadataCLI 全部报连不上
nova-scheduler—选主机实例长期 BUILD 后 ERROR
nova-conductor—代理 DB 访问实例状态不更新、调度超时
nova-compute—调 libvirt 起虚机主机 down、无新实例
nova-novncproxy6080Web 控制台「控制台」打不开
systemctl status nova-{compute,conductor,scheduler,novncproxy} --no-pager -l
systemctl restart nova-compute            # 改 nova.conf 后四个都要重启
journalctl -u nova-compute -n 100 --no-pager

健康检查

openstack compute service list                     # 三行都要 up;State 列的 enabled 也要对
openstack hypervisor list                          # open88 / QEMU / up
openstack hypervisor show open88 -f yaml
nova-manage cell_v2 list_cells                     # cell0 + cell1
nova-manage cell_v2 discover_hosts                 # 新计算节点注册(幂等)

实例生命周期

openstack server list --all-projects --long
openstack server show <实例> -f yaml               # status / task_state / host / fault
openstack server start|stop|reboot|reboot --hard <实例>
openstack server delete <实例>
openstack server resize --flavor <新规格> <实例> && openstack server resize confirm <实例>
openstack server rebuild <实例> --image <镜像>     # 重建(会丢失系统盘改动)
openstack server create --flavor m1.small --image cirros --nic net-id=<net> \
 --security-group default --key-name <key> demo-vm

看 fault 字段是排障捷径:openstack server show <实例> -f value -c fault 会给出 message 与 code,通常直接指向根因(镜像、网络、配额、privsep)。

虚拟化层(绕过 nova 看真相)

virsh list --all                       # 域在不在、什么状态
virsh domstate instance-00000004       # running / shut off / paused
virsh dumpxml instance-00000004 | grep -E 'source file|mac address|target dev'
virsh domiflist instance-00000004      # 网卡与所属网桥(应为 br-int 的 tap)
virsh console instance-00000004        # 看引导卡在哪(Ctrl+] 退出)
tail -50 /var/log/libvirt/qemu/instance-00000004.log

数据库与 cell 运维

nova-manage api_db sync              # nova_api 库
nova-manage db sync                  # cell 库
nova-manage cell_v2 list_cells
nova-manage cell_v2 map_cell0
nova-manage cell_v2 create_cell --name cell1 --verbose
nova-manage db archive_deleted_rows --max_rows 1000    # 清理已删记录

nova 专属故障速查

症状根因处置
Compute driver option required, but not specifiednova.conf 缺 compute_driver[DEFAULT] compute_driver = libvirt.LibvirtDriver
ModuleNotFoundError: No module named 'libvirt'venv 缺绑定(pip 编译失败)dnf install -y libvirt-devel python3-libvirt,再软链 libvirt.py 与 libvirtmod*.so 进 venv
实例创建 500 / 调度失败缺 /etc/nova/rootwrap.conf 或 rootwrap.d/从源码 etc/nova/ 复制补齐
FailedToDropPrivileges ... exited non-zero (97)缺 vif_plug_ovs 的 privsep 过滤器新增 privsep-extra.filters(必须含 [Filters] 段头)
FailedToDropPrivileges ... (1)privsep-helper 不在 sudo secure_pathln -sf /data/openstack/venv/bin/privsep-helper /usr/local/bin/
Failed to allocate the network(s), not reschedulingneutron 未通知 network-vif-pluggedneutron.conf 开启 notify_nova_on_port_status_changes/_data_changes 并配 [nova] 段

3.5 neutron(网络服务)

形态:API 由 neutron-server(systemd,:9696)提供;数据面靠 4 个 agent 进程。 2025.2 新增 neutron-rpc-server,缺它 agent 会 active 但永不注册。

systemctl status neutron-{rpc-server,openvswitch-agent,dhcp-agent,l3-agent,metadata-agent} \
 --no-pager -l
systemctl restart neutron-rpc-server          # 改了 agent 配置后建议整体重启
for u in rpc-server openvswitch-agent dhcp-agent l3-agent metadata-agent; do
 systemctl restart neutron-$u
done

健康检查(四件套必须齐全)

openstack network agent list
# 期望:Open vSwitch agent / DHCP agent / L3 agent / Metadata agent,State=UP,Alive=True
openstack network agent list -f value -c 'Agent Type' -c Alive -c State

少任何一个 agent、或 Alive=False,都说明对应进程没连上 RPC。先查 neutron-rpc-server, 再查该 agent 的 .log 是否有 AMQP / Unauthorized。

网络对象运维

openstack network list
openstack network show <net> -f yaml
openstack network create --provider-network-type flat --provider-physical-network provider \
 --external public                    # 创建外部网络
openstack subnet create --network public --subnet-range 192.168.3.0/24 \
 --gateway 192.168.3.1 --allocation-pool start=192.168.3.200,end=192.168.3.250 \
 --no-dhcp public-subnet
openstack network set --external public

# 租户网络与路由
openstack network create demo-net
openstack subnet create --network demo-net --subnet-range 10.0.0.0/24 demo-subnet
openstack router create demo-router
openstack router add subnet demo-router demo-subnet
openstack router set --external-gateway public demo-router

# 端口(排查绑定问题的主力)
openstack port list
openstack port show <port> -f yaml          # 重点看 binding:vif_type / binding:host_id
openstack port set --security-group <sg> <port>

# 安全组(项目多时务必用 ID,不能用名字)
SG=$(openstack security group list --project admin -f value -c ID -c Name | awk '/default/{print $1}')
openstack security group rule create --ingress --proto tcp --dst-port 22 "$SG"
openstack security group rule list "$SG"

# 浮动 IP
openstack floating ip create public
openstack floating ip list
openstack server add floating ip <实例> <浮动IP>
openstack floating ip delete <浮动IP>

命名空间(数据面真相所在)

ip netns list                                  # qrouter-<id> / qdhcp-<id>
ip netns exec qrouter-<id> ip -4 addr show     # 看 qg(外部)/ qr(内部)地址
ip netns exec qrouter-<id> ip route show
ip netns exec qrouter-<id> ping -c2 192.168.3.1        # SNAT 出网关
ip netns exec qrouter-<id> bash -c 'exec 3<>/dev/tcp/223.5.5.5/53' && echo TCP-OK
ip netns exec qrouter-<id> ping -c2 <实例私有IP>
ip netns exec qdhcp-<id> ip -4 addr show

# OVS 侧
ovs-vsctl show
ovs-vsctl list-ports br-provider        # phy-br-provider + veth-brex
ovs-vsctl list-ports br-int | head -30  # tap / qvo / patch
ovs-ofctl dump-flows br-int | head -40

neutron 专属故障速查

症状根因处置
API 500 AttributeError: neutron_lib.constants has no attribute ...neutron-lib 过新pip install 'neutron-lib==3.21.1' 后重启
agent active 但不注册缺 neutron-rpc-serversystemctl enable --now neutron-rpc-server
OVS agent Bridge br-provider ... does not exist网桥没建ovs-vsctl --may-exist add-br br-provider(不接物理网卡)
OVS agent FailedToDropPrivileges缺 rootwrap 配置/软链补 /etc/neutron/rootwrap.conf + rootwrap.d/*.filters + neutron-rootwrap 软链
nova→neutron 调用 401服务令牌缺 service 角色openstack role create service 并授给各服务用户
实例 Failed to allocate the network(s)未通知 vif-plugged见 3.4 对应条目

3.6 horizon(仪表板)

形态:httpd + mod_wsgi,WSGIScriptAlias /dashboard /data/openstack/horizon/wsgi/django.wsgi,访问 http://192.168.3.88/dashboard/。

systemctl reload httpd
apachectl -t
tail -100 /data/openstack/horizon/error.log
tail -100 /var/log/httpd/horizon_error.log

健康检查

curl -s -o /dev/null -w '%{http_code}\n' http://192.168.3.88/dashboard/     # 200
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.3.88/dashboard/auth/login/
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.3.88/dashboard/static/dashboard/css/output.css

改配置 / 静态资源 / 会话

SP=/data/openstack/venv/lib/python3.11/site-packages
vi $SP/openstack_dashboard/local/local_settings.py     # OPENSTACK_HOST / CACHES / WEBROOT

# 静态资源变更后必须重收集
cd $SP/openstack_dashboard && /data/openstack/venv/bin/python3 manage.py collectstatic --noinput
chown -R apache:apache /data/openstack/horizon/static

# 会话异常(登录后立刻掉、按钮显示不全)先清缓存会话
systemctl restart memcached
echo 'flush_all' | nc -q1 127.0.0.1 11211              # 或直接刷缓存
systemctl restart httpd

local_settings.py 中与本机强相关的四项(写错即页面 500):

OPENSTACK_KEYSTONE_URL = "http://controller:5000/v3"     # 必须带 /v3
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
                     'LOCATION': 'controller:11211'}}
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'  # 新版 Django 无 Pickle
STATIC_ROOT = '/data/openstack/horizon/static'

horizon 专属故障速查

症状根因处置
登录 500 ModuleNotFoundError: pymemcache缓存后端依赖缺失pip install pymemcache 后 systemctl restart httpd
collectstatic 找不到 manage.pypip 包不含该文件cp /data/src/horizon-*/manage.py $SP/openstack_dashboard/
sass.CompileError: font-awesome.scss not foundXStatic-Font-Awesome 新版目录变化pip install 'XStatic-Font-Awesome==4.7.0.0' 再 collectstatic
实例的删除/启动/停止按钮消失policy 作用域误判(详见 4.7)修 openstack_auth/policy.py 的 _user_to_credentials()
登录后立即退出memcached 挂或会话序列化不兼容查 memcached 状态与 SESSION_SERIALIZER

3.7 cinder(块存储服务)

形态:3 个 systemd 单元,其中 cinder-volumes-loop 是前置条件(建 loop 设备 + LVM 卷组), 它失败则 cinder-volume 必然 down。

systemctl status cinder-{volumes-loop,scheduler,volume} --no-pager -l
systemctl restart cinder-volumes-loop && systemctl restart cinder-volume
journalctl -u cinder-volume -n 100 --no-pager
systemctl-analyze verify /usr/lib/systemd/system/cinder-volumes-loop.service 2>/dev/null || \
 systemd-analyze verify /usr/lib/systemd/system/cinder-volumes-loop.service

健康检查

openstack volume service list        # cinder-scheduler / cinder-volume 都要 up
openstack volume list --all-projects
vgs                                   # cinder-volumes 卷组存在且有剩余空间
lvs --noheadings -o lv_name,size,vg_name | grep cinder-volumes
losetup -j /data/openstack/cinder/volumes.img
df -h /data

卷生命周期

openstack volume create --size 10 --description 'test' vol1
openstack volume show vol1 -f yaml                    # status 应 available
openstack volume set vol1 --name vol1-renamed
openstack server add volume <实例> vol1 --device /dev/vdb
openstack server remove volume <实例> vol1
openstack volume snapshot create --volume vol1 snap1
openstack volume create --snapshot snap1 --size 10 vol2
openstack volume delete vol1                          # 挂载中会拒绝

后端与卷组维护

# 卷组容量(loop 文件占满会导致创建卷失败)
vgs cinder-volumes
pvs
lvs -a

# 扩容 loop 卷组(宿主磁盘允许时)
systemctl stop cinder-volume
truncate -s +50G /data/openstack/cinder/volumes.img
LOOP=$(losetup -j /data/openstack/cinder/volumes.img | cut -d: -f1)
losetup -c "$LOOP"
pvresize "$LOOP"
vgextend cinder-volumes "$LOOP"
systemctl start cinder-volumes-loop cinder-volume

# 服务列表里出现 down 后的恢复顺序
systemctl start cinder-volumes-loop
systemctl restart cinder-volume
openstack volume service list

cinder 专属故障速查

症状根因处置
cinder-volume 反复退出 FileNotFoundError: cinder-rtstool单元 PATH 不含 venv单元加 Environment=PATH=/data/openstack/venv/bin:...
卷创建失败 / cinder-volume down卷组不存在(loop 单元未成功)建 loop + vgcreate cinder-volumes,或修 cinder-volumes-loop 单元
Manager for service ... not sending heartbeat后端初始化失败(多数是卷组缺)先 vgs,再查 cinder-volume.log 首个 Traceback
bad unit file setting(单元起不来)单元文件里有非法字段systemd-analyze verify <unit> 定位后修正

4. 故障解决方法

4.1 分层诊断法

OpenStack 的故障几乎都以「上层报错、根因在下层」的形式出现。固定按下面 7 层自底向上走, 每层都有明确判据,不通就停在该层,不要跳到上层猜:

层判据命令不通的典型含义
① 磁盘/内存df -h /data、free -g/data 满 → 镜像/卷/日志全挂,报错五花八门
② 数据库mysqladmin ping、mysql -e 'show databases;'所有服务 500,日志 Can't connect to MySQL
③ 消息队列rabbitmqctl status、rabbitmqctl list_queues服务 active 但状态永不更新、agent 不注册
④ 缓存nc -z 127.0.0.1 11211keystone token 慢、horizon 掉登录
⑤ 认证openstack token issue、openstack service list401/403、service catalog 为空
⑥ APIcurl -o /dev/null -w '%{http_code}' http://controller:<port>/500/502 看 httpd 或对应服务日志
⑦ agent/后端openstack compute service list / network agent list / volume service list进程在但资源不可用

一次跑完前 5 层(建议存成别名):

df -h /data | tail -1
mysqladmin ping 2>&1 | tail -1
rabbitmqctl status 2>&1 | grep -E 'Runtime|Uptime' | head -2
timeout 2 nc -z 127.0.0.1 11211 && echo memcached-OK
openstack token issue -f value -c expires >/dev/null 2>&1 && echo keystone-OK

常见误判:

  • 看到 ERROR 就重启 nova-compute——多数时候它只是"受害者",真因在 neutron 未发 vif-plugged 或 glance 镜像取不到。

  • 看到 active (running) 就认为服务正常——本版本 neutron agent 与 cinder-volume 都可能"活着但不干活",必须看第 ⑦ 层。

  • 只看 /var/log/messages 或 journalctl——WSGI 类服务(keystone/placement/nova-api/horizon) 的真正堆栈在 /var/log/httpd/*_error.log。

4.2 WSGI / httpd 与 venv:六类典型故障

本环境 4 个服务跑在 httpd 下,它们的故障几乎都落在「Python 找不到包」和「apache 用户读不到 / 写不了 /data」这两件事上。

① ModuleNotFoundError: No module named 'keystone'(WSGI 找不到 venv 包)

根因:mod_wsgi 用的是系统 Python,不会继承 venv 的 site-packages。 修复:每个 WSGI 入口文件第一行就要插路径:

import sys
sys.path.insert(0, "/data/openstack/venv/lib/python3.11/site-packages")

本机同时存在 lib 与 lib64 两个 site-packages 目录,缺包时先确认软链是否齐全: ls /data/openstack/venv/lib64/python3.11/site-packages | head。

② PermissionError: [Errno 13] ... /data/openstack/...

根因:apache 用户无法进入 /data(目录缺 o+x)或无权读写日志目录。 修复:

chmod o+x /data /data/openstack
chown apache:apache /data/openstack/{nova,neutron,cinder,horizon,glance,placement}/*.log 2>/dev/null
# 若日志目录属主被改成服务用户(nova/neutron),一并纠正
chown -R apache:apache /var/log/httpd

③ API 500 且日志里 PermissionError ... api.py.log

根因:/data/openstack 下的日志文件属主是 nova(systemd 进程建的),apache 不可写。 修复:chown apache:apache <该日志> 并删除旧的不可写文件后重启 httpd。

④ ConfigFilesNotFoundError: /etc/nova/api-paste.ini

根因:源码包只提供模板,pip 安装不会自动落地到 /etc。 修复:cp /data/src/nova-32.2.2.dev2/etc/nova/api-paste.ini /etc/nova/(其它服务同理)。

⑤ OSError: [Errno 13] Permission denied: '/etc/<svc>/<svc>.conf'

根因:配置文件曾被 chmod 成 600 且属主不是 apache。 修复:chown root:apache /etc/nova/nova.conf && chmod 640 /etc/nova/nova.conf。

⑥ 配置文件含中文导致服务起不来

根因:oslo.config 按 ASCII 解码配置文件。httpd 下 locale 为 C,一旦 /etc/nova/nova.conf、l3_agent.ini 等含中文注释,就报 UnicodeDecodeError: 'ascii' codec can't decode byte ...。 规则:所有 oslo 配置文件(nova/neutron/cinder/keystone/placement/glance)的注释一律用英文, 中文说明只写在文档里。systemd 直起的服务因 locale=UTF-8 可容忍,但 httpd 下的服务会直接崩。

# 快速定位非 ASCII 字符
grep -nP '[^\x00-\x7F]' /etc/nova/nova.conf /etc/neutron/*.ini /etc/neutron/plugins/ml2/*.ini

4.3 基础组件:MariaDB / RabbitMQ / memcached

这三者任一异常,表现都是"所有服务一起出问题",所以它们排最前。

MariaDB

症状根因修复
改了 datadir 不生效,仍是 /var/lib/mysqlopenEuler 上 /etc/my.cnf 可能不存在,只往 /etc/my.cnf.d/ 写不被读创建 /etc/my.cnf 作为主配置,写入 datadir 与 socket
mysql 客户端连不上(socket 不匹配)客户端默认 socket 是 /var/lib/mysql/mysql.sock/etc/my.cnf 增加 [client] socket=/data/openstack/mysql/mysql.sock
mysql -e "SELECT @@datadir, @@socket;"          # 校准是否落 /data
systemctl restart mariadb
journalctl -u mariadb -n 50 --no-pager
mysql -e "SHOW PROCESSLIST;"                     # 长事务/锁等待
mysql -e "SELECT table_schema, ROUND(SUM(data_length+index_length)/1024/1024) mb
         FROM information_schema.tables GROUP BY table_schema ORDER BY mb DESC;"

RabbitMQ

症状根因修复
启动失败 failed_to_create_feature_flags_file_directory/data 下 mnesia/log 目录属主或权限不对chown -R rabbitmq:rabbitmq /data/openstack/rabbitmq && chmod 750
所有服务报 AMQPLAIN ... ACCESS_REFUSED (403)全新安装没有 openstack 用户建用户 + 授权限 + 给权限
systemctl status rabbitmq-server
rabbitmqctl status | head -20
rabbitmqctl list_users
rabbitmqctl list_queues name messages consumers | head -20

# 标准修复(用户缺失场景)
rabbitmqctl add_user openstack RABBIT_PASS
rabbitmqctl set_permissions openstack ".*" ".*" ".*"
rabbitmqctl set_user_tags openstack administrator
systemctl restart rabbitmq-server

# 队列堆积(agent 长期不消费)
rabbitmqctl list_queues name messages | sort -k2 -n -r | head

403 与 530 的区别:403 是认证通过但无 vhost 权限;530 多是用户不存在或口令错。 两者都先 rabbitmqctl list_users + list_permissions -p /。

memcached

症状根因修复
启动失败 Maximum connections must be greater than 0变量写成 OPTIONS="-c ...",openEuler 用的是 MAXCONN/etc/sysconfig/memcached 里改 MAXCONN="1024"
systemctl status memcached
ss -lntp | grep 11211
nc -z 127.0.0.1 11211 && echo OK
echo -e 'stats\r' | timeout 2 nc 127.0.0.1 11211 | head -20   # 看 curr_connections / evictions

evictions 持续增长说明缓存不够,会引发 keystone token 反复重建、horizon 掉登录。

4.4 placement 故障

症状根因修复
RequiredOptError: value required for option connection in group [placement_database]配置段名写成 [database]改为 [placement_database] 后 systemctl reload httpd
API 500 NoSuchOptError: no such option enforce_scope新版 oslo.policy 已删除该选项,placement/deploy.py 直接引用它改成 if not getattr(conf.oslo_policy, 'enforce_scope', True):
调度报 No valid host was found资源不足 或 资源提供者库存未上报先 openstack resource provider inventory list,再查 nova-scheduler.log 的 Filter 行
实例创建 409 Conflict库存为 0/未生成systemctl restart nova-compute 触发上报
# placement 端到端三步(用 token 才算真验证)
TOKEN=$(openstack token issue -f value -c id)
curl -s -o /dev/null -w '%{http_code}\n' -H "X-Auth-Token: $TOKEN" http://controller:8778/
openstack resource provider list
openstack resource provider usage show <rp-uuid>
tail -100 /var/log/httpd/placement_error.log

4.5 nova 与 privsep 故障

这是本版本实例创建失败最高发的一组问题,四处配置缺一不可:

/etc/nova/rootwrap.conf                     ← 存在
/etc/nova/rootwrap.d/compute.filters        ← 存在
/etc/nova/rootwrap.d/privsep-extra.filters  ← 自建,必须含 [Filters] 段头
/usr/local/bin/privsep-helper、nova-rootwrap ← 指向 venv 的软链(sudo secure_path 可达)
报错根因修复
FailedToDropPrivileges: privsep helper command exited non-zero (97)rootwrap 过滤器缺失(vif_plug_ovs 上下文)新增 privsep-extra.filters,必须有 [Filters] 段头,否则文件被忽略
FailedToDropPrivileges ... (1)sudo privsep-helper 在 secure_path 里找不到(装在 venv)ln -sf /data/openstack/venv/bin/privsep-helper /usr/local/bin/privsep-helper
ModuleNotFoundError: No module named 'libvirt'venv 无 libvirt 绑定dnf install -y libvirt-devel python3-libvirt,再软链 .py 与 .so
Compute driver option required缺 compute_driver[DEFAULT] compute_driver = libvirt.LibvirtDriver

标准补齐动作:

mkdir -p /etc/nova/rootwrap.d
cp /data/src/nova-32.2.2.dev2/etc/nova/rootwrap.conf /etc/nova/
cp /data/src/nova-32.2.2.dev2/etc/nova/rootwrap.d/compute.filters /etc/nova/rootwrap.d/
cat > /etc/nova/rootwrap.d/privsep-extra.filters <<'EOF'
[Filters]
privsep-rootwrap-vif_plug: RegExpFilter, privsep-helper, root, privsep-helper, --config-file, /etc/(?!\.\.).*, --privsep_context, vif_plug_ovs.privsep.vif_plug, --privsep_sock_path, /tmp/.*
EOF
ln -sf /data/openstack/venv/bin/privsep-helper /usr/local/bin/privsep-helper
ln -sf /data/openstack/venv/bin/nova-rootwrap /usr/local/bin/nova-rootwrap
systemctl restart nova-compute
# 验证 privsep 是否真的通了(手工跑一次过滤器)
sudo -n /usr/local/bin/privsep-helper --config-file /etc/nova/nova.conf 2>&1 | head -3
grep -c '^\[Filters\]' /etc/nova/rootwrap.d/*.filters

rootwrap 过滤器任何语法错误都会静默退化为"找不到命令",表现为 (97) 而非配置错误。 改完必须重启 nova-compute(过滤器在进程启动时加载)。

4.6 neutron 故障

症状根因修复
API 500 AttributeError: neutron_lib.constants has no attribute ...neutron-lib 版本过新pip install 'neutron-lib==3.21.1' 后重启全部 neutron 进程
agent active 却不在列表中2025.2 agent 依赖独立 neutron-rpc-serversystemctl enable --now neutron-rpc-server
OVS agent Bridge br-provider ... does not exist网桥未建ovs-vsctl --may-exist add-br br-provider(不接物理网卡)
OVS agent FailedToDropPrivileges缺 rootwrap.conf / rootwrap.d/ / neutron-rootwrap 软链从源码复制 + ln -sf ... /usr/local/bin/
nova→neutron 401服务令牌缺 service_token_roles 要求的角色openstack role create service 并授予所有服务用户
实例 Failed to allocate the network(s), not reschedulingneutron 没把 network-vif-plugged 通知 nova开 notify_nova_on_port_status_changes/_data_changes 并配 [nova] 段
# 端口绑定状态是网络类故障的第一证据
openstack port show <port> -f yaml | grep -E 'binding|status|device'
# 期望:binding:vif_type=ovs、binding:host_id=open88、status=ACTIVE

grep -E 'Error|ERROR|Traceback' /data/openstack/neutron/openvswitch-agent.log | tail -30
ovs-vsctl show | head -40
ovs-ofctl dump-flows br-int | wc -l

「实例能 ping 自己但不同网段不通」→ 多半是 L3 agent 未起或 qrouter 命名空间缺 NAT 规则; 「同网段不通」→ 查 OVS 流表与 port security(port_security 扩展驱动是否启用)。

4.7 horizon:带策略校验的按钮全部消失

现象:admin 登录后,实例表里带 policy_rules 的动作(Delete / Start / Stop / Reboot / Resize…) 全部不显示,而不带策略的动作(Create Snapshot、Console、Attach Interface)正常;菜单完整、 静态资源全部 200、无报错。

根因(两层叠加):

  1. oslo.policy 6.0.1 已移除 enforce_scope 选项,作用域校验恒为开启,Horizon 的 policy_opts.set_defaults(conf, enforce_scope=False) 被静默忽略。

  2. openstack_auth._user_to_credentials() 把用户所属域写进了凭据的 domain_id,而 oslo_policy 按下面优先级判定令牌作用域:

    if creds.get('system'):      token_scope = 'system'
    elif creds.get('domain_id'): token_scope = 'domain'    # ← 命中,误判
    else:                        token_scope = 'project'

    于是项目作用域令牌被当成域作用域,凡 scope_types=['project'] 的规则一律返回 False。

进程内验证(在 site-packages 目录执行,直接看判定值):

cd /data/openstack/venv/lib/python3.11/site-packages && /data/openstack/venv/bin/python3 -c "
import sys,os,django; sys.path.insert(0,'.')
os.environ.setdefault('DJANGO_SETTINGS_MODULE','openstack_dashboard.settings'); django.setup()
from django.test import Client, RequestFactory
from django.contrib import auth as dj_auth
from openstack_auth import policy as ap
c=Client(); c.post('/auth/login/',{'username':'admin','password':'ADMIN_PASS','region':'default','domain':'Default'})
rf=RequestFactory(); req=rf.get('/'); req.session=c.session; dj_auth.get_user(req)
print(ap.check((('compute','os_compute_api:servers:delete'),), req))   # False 即命中本故障
"

修复(对齐上游:凭据里不再返回 domain_id):

F=$(/data/openstack/venv/bin/python3 -c "import openstack_auth,os;print(os.path.join(os.path.dirname(openstack_auth.__file__),'policy.py'))")
cp -a "$F" "$F.bak.$(date +%Y%m%d%H%M%S)"
vi "$F"      # 在 _user_to_credentials() 中删除 'domain_id': user.user_domain_id, 这一行
systemctl restart httpd

check() 内对 target 注入 domain_id(供 domain_id:%(target.domain_id)s 类规则使用)必须保留, 只能删 credentials(令牌作用域)里的那一行。

验证:重启后页面上 Delete Instance / Start Instance 应重新出现;上述 python 片段应打印 True。

4.8 cinder:cinder-volume down 与卷组依赖环

现象:openstack volume service list 中 cinder-volume open88@lvm 状态 down, 无法创建卷,日志反复出现:

Manager for service cinder-volume open88@lvm is reporting problems, not sending heartbeat.

根因:cinder-volumes-loop.service 启动失败(bad unit file setting / 依赖环), 导致 loop 设备未挂接、cinder-volumes 卷组不存在,LVM 后端初始化失败。

本机实测的两个硬伤与规避:

  1. 单元文件中存在 Requires 自环(loop 与 volume 互相 Requires)→ 去掉环,改用 Before=cinder-volume.service shutdown.target。

  2. vgscan --mknodes 在部分环境返回非零(码 5),脚本 set -e 下会误伤中止 → 加 || true。

修复与验证:

systemd-analyze verify /usr/lib/systemd/system/cinder-volumes-loop.service   # 定位 bad-setting
systemctl start cinder-volumes-loop
vgs cinder-volumes
systemctl restart cinder-volume
openstack volume service list                                                # 恢复 up
openstack volume create --size 1 testvol && openstack volume delete testvol

判断顺序(顺序错了会白折腾):loop 设备 → 卷组 → cinder-volumes-loop 单元 → cinder-volume 进程 → volume service list。

4.9 metadata 服务链路故障

实例的密钥注入 / 重置密码 / cloud-init 全依赖 metadata,链路是:

实例 169.254.169.254 → qrouter/qdhcp 命名空间 → neutron-metadata-agent (:8775 转发)
                    → nova-api metadata(httpd,/etc/nova/nova.conf [api] metadata)
症状根因修复
实例拿不到密钥(登录被拒)metadata 链路断,cloud-init 无数据可拉按下方顺序逐段验证
Unexpected response code: 300metadata_agent.ini 的 nova_metadata_port 写成 8774,拿到 API 版本列表改为 8775
metadata 500WSGI 入口签名不对/data/openstack/nova/wsgi/metadata.py 用 init_application('metadata')(本版本只接受 1 个参数)
# 逐段验证(自下而上)
curl -s -o /dev/null -w '%{http_code}\n' http://controller:8775/openstack     # 400 属正常(裸请求)
grep -E 'nova_metadata_(host|port)' /etc/neutron/metadata_agent.ini            # port 必须 8775
systemctl status neutron-metadata-agent --no-pager
ip netns exec qrouter-<id> curl -s -m 3 http://169.254.169.254/openstack      # 命名空间内直取
tail -50 /data/openstack/neutron/metadata-agent.log

只影响新实例的密钥注入;存量实例若不生效,检查 /root/.ssh/authorized_keys 是否被 command="echo Please login as ..." 前缀拦截(镜像内 disable_root 导致)。

4.10 宿主机重启后的三类假故障

重启后报「不通/打不开」,先分清是三类里的哪一类,避免瞎改配置:

类别现象判定处置
① 实例没起来(最常见)浮动 IP 不通、SSH 拒绝openstack server list 显示 SHUTOFF,virsh list --all 域关闭openstack server start <实例>,等 20–40 秒
② 网络自愈未完成br0 无管理 IP、veth 未 forwardingip -4 addr show br0、cat /sys/class/net/veth-br0/brport/statesystemctl restart br0-provider-veth;仍不行按 5.5 回滚
③ 服务未自启API 500/连不上systemctl --failed逐个 systemctl enable --now <unit>

为什么实例不会自动起:libvirt 未开 autostart。两种解法:

# 方式 A:单实例 libvirt autostart
virsh autostart instance-00000004
virsh list --all --autostart

# 方式 B:nova 全局开关(推荐,对所有 nova 管理的实例生效)
# /etc/nova/nova.conf → [DEFAULT] resume_guests_state_on_host_boot = True
systemctl restart nova-compute

方式 B 要求实例的 libvirt 域可被重建;磁盘/配置缺失时会被跳过并记告警,查 nova-compute.log。

开机后 20 秒自检(建议做成登录提示或 systemd 单元):

systemctl is-active br0-provider-veth
ip -4 addr show br0 | grep 192.168.3.88
ovs-vsctl list-ports br-provider | grep veth-brex
systemctl --failed
openstack compute service list
openstack network agent list
openstack volume service list

4.11 实例创建失败的通用排查路径

按顺序执行,每步不过就停,可以覆盖绝大多数 ERROR:

# ① 状态与报错原文(最快命中根因)
openstack server show <实例> -f value -c status -c task_state -c fault

# ② 是否镜像问题:镜像 active?min_ram/min_disk 是否满足 flavour?
openstack image show <镜像> -f value -c status -c size -c min_disk -c min_ram
openstack flavor show <flavour> -f value -c vcpus -c ram -c disk

# ③ 是否配额问题
openstack quota show <project> -f yaml

# ④ 是否资源/调度问题(placement 账本 + scheduler 日志)
openstack resource provider usage show <rp-uuid>
grep -E 'No valid host|Filter|Weight' /data/openstack/nova/nova-scheduler.log | tail -20

# ⑤ 是否网络问题(port 是否绑定成功)
openstack port list --server <实例>
openstack port show <port> -f yaml | grep -E 'binding|status'

# ⑥ 是否计算节点侧问题(这步命中率最高)
grep -E 'ERROR|Traceback|privsep|FailedToDropPrivileges' \
    /data/openstack/nova/nova-compute.log | tail -40
tail -50 /var/log/libvirt/qemu/instance-*.log
virsh list --all

task_state 的值直接指明卡在哪一步:

task_state卡住的环节去哪看
scheduling调度/资源不足nova-scheduler.log、placement
networking建 port / 绑定失败neutron-* 日志、port show
block_device_mapping卷挂载/镜像下载cinder-volume.log、glance
spawning起虚机失败nova-compute.log、libvirt
powering-on虚机起不来/var/log/libvirt/qemu/*.log
image_snapshot / deleting长期挂住清理残留后重试

4.12 通用陷阱

陷阱说明正确做法
pkill -f <关键字> 杀掉自己模式串会匹配到执行它的 shell 自身,表现为 [process terminated by signal]ps -eo pid,cmd | grep "[v]env/bin/<svc>" 定位后再 kill <pid>
nohup 起服务会话结束即被回收一律 systemd 托管
pip 安装看似"卡死"源码编译耗时长,命令超时属正常后台跑 + pgrep -f "venv/bin/pip" 轮询
eventlet 版本漂移0.41.2 可用;0.36.x 触发 'HubThread' object has no attribute 'kill'锁版本,勿随意升级
配置文件写中文注释httpd 下 locale=C,ASCII 解码失败oslo 配置文件注释全用英文
用名字操作安全组多项目下 default 重名,命令静默失败一律用 ID:SG=$(openstack security group list ... -c ID)
在宿主根命名空间改默认路由一条 ip route replace default 即可全网黑洞只在 ip netns exec 内改,见 5.5
只重启 httpd 就以为换了代码WSGIDaemonProcess 会缓存已导入模块改 venv 内 Python 代码后 systemctl restart httpd;必要时先杀 daemon 进程

5. 附录

5.1 端口与服务目录

端口进程 / 服务类型端点
5000keystone(httpd)identityhttp://controller:5000/v3/
9292glance-apiimagehttp://controller:9292
8778placement(httpd)placementhttp://controller:8778
8774nova-api(httpd)computehttp://controller:8774/v2.1
8775nova metadata(httpd)metadatahttp://controller:8775
6080nova-novncproxyconsoleWeb 控制台代理
9696neutron-servernetworkhttp://controller:9696
8776cinder-apivolume / volumev3http://controller:8776/v3/%(project_id)s
80httpddashboardhttp://controller/dashboard/
3306MariaDBDB/data/openstack/mysql/mysql.sock
5672RabbitMQMQrabbit://openstack:***@controller:5672/
11211memcachedcachecontroller:11211

Region:RegionOne。一个服务必须注册 public / internal / admin 三套端点,缺一套时 CLI 会挑不到地址(表现为 Could not determine a suitable URL)。

openstack endpoint list -f value -c "Service Name" -c Interface -c URL | sort
openstack catalog list

5.2 路径与单元速查

项目值
admin 凭据/data/admin-openrc.sh(600)
Python / CLI/data/openstack/venv/bin(含 openstack、*-manage)
源码包/data/src/<svc>-<ver>/
配置文件/etc/{keystone,glance,placement,nova,neutron,cinder}/<svc>.conf
WSGI 入口/data/openstack/{keystone,placement,nova/wsgi,horizon/wsgi}/
数据与日志/data/openstack/<svc>/
虚拟机磁盘/data/openstack/libvirt/images/
镜像实体/data/openstack/glance/images/
卷(loop)/data/openstack/cinder/volumes.img
单元目录/usr/lib/systemd/system/
网络自愈脚本/usr/local/sbin/br0-provider-veth.sh
断网看门狗/root/net-watchdog.sh、确认标记 /root/net-switch-OK

5.3 巡检清单

每日(30 秒)

systemctl --failed
openstack compute service list -f value -c Binary -c State -c Status
openstack network agent list -f value -c "Agent Type" -c Alive
openstack volume service list -f value -c Binary -c State
df -h /data | tail -1
vgs cinder-volumes

变更后(改配置 / 升级 / 换镜像)

systemctl daemon-reload
systemctl restart <受影响单元>
systemctl --failed
openstack token issue -f value -c expires
openstack image list
openstack server create --flavor m1.tiny --image cirros --nic net-id=<net> smoke-test
openstack server delete smoke-test

重启后:见 4.10 的三类判定与自检命令。

验收脚本(一次性把 55 项过一遍)

cd /opt/openstack-Flamingo/deploy/install
sudo ./90-verify.sh              # 全量(含端到端创建实例)
sudo ./90-verify.sh --quick      # 只查服务与端口

5.4 备份与恢复

必须备份的四类东西(其余可重建):

对象命令
数据库(keystone/nova/neutron/cinder/placement)mysqldump --single-transaction --all-databases > /data/backup/db-$(date +%F).sql
fernet / credential 密钥tar czf /data/backup/keys-$(date +%F).tgz /data/openstack/keystone/fernet-keys* /data/openstack/keystone/credential-keys
全部配置tar czf /data/backup/etc-$(date +%F).tgz /etc/keystone /etc/glance /etc/placement /etc/nova /etc/neutron /etc/cinder /etc/httpd/conf.d
关键自定义代码补丁把 venv 内改过的文件(如 openstack_auth/policy.py、placement/deploy.py)单独留档

恢复要点:先停 OpenStack 单元(保留 mariadb/rabbitmq)→ 恢复 DB 与密钥 → 恢复配置 → daemon-reload → 按依赖顺序启动(keystone → glance/placement → nova → neutron → cinder → horizon)。 fernet 密钥与数据库必须成对恢复,只恢复其一会导致全部 token/凭据不可用。

5.5 危险操作与回滚

⚠️ 绝对禁止的操作

操作后果
在宿主根命名空间执行 ip route replace/add default ...全局默认路由被覆盖,SSH 与外网立即中断
删除 /data/openstack/keystone/fernet-keys所有 token 失效、加密凭据无法解密
删除或缩小 /data/openstack/cinder/volumes.img卷数据丢失且不可恢复
直接替换 glance 镜像文件而不改 DB元数据与实体不一致,实例无法启动
ovs-vsctl del-br br-provider所有实例网络中断,需重建网桥并重启 OVS agent

网络出口变更的回滚(br0 + veth)

# ① 拆 veth 对
ovs-vsctl --if-exists del-port br-provider veth-brex
ip link del veth-br0
systemctl disable --now br0-provider-veth 2>/dev/null

# ② 拆 br0,把管理 IP 还给 enp2s0
nmcli con down br0
nmcli con delete br0-slave-enp2s0 2>/dev/null
nmcli con delete br0 2>/dev/null
nmcli con mod enp2s0 connection.autoconnect yes
nmcli con up enp2s0

# ③ 校验
ip -4 addr show enp2s0            # 应恢复 192.168.3.88/24
ip route show default             # default via 192.168.3.1 dev enp2s0
ping -c2 192.168.3.1

变更前必须做的三件事:

  1. ip route show default 与 ip -4 addr show 先留底(出事时照抄恢复);

  2. 用 setsid <脚本> </dev/null & 让切换脱离 SSH 会话,断开也能跑完;

  3. 另开一个 SSH 窗口守候,并在 300 秒内 touch /root/net-switch-OK,否则看门狗自动回滚:

setsid /root/net-watchdog.sh 300 40 >/dev/null 2>&1 < /dev/null &

单个实例网络排障的安全做法

# 只在隔离命名空间里试路由,绝不动宿主默认路由
ip netns add t
ip netns exec t ip route add default via 192.0.2.1
ip netns del t

5.6 维护约定

  1. 改配置 = 改完就重启对应层:httpd 类 systemctl reload httpd;systemd 类 systemctl restart <unit>;改 Python 代码必须 restart(reload 不换已导入模块)。

  2. 改完必验:systemctl --failed + 三张 openstack ... service list 表 + 一次 token issue,任何一项不绿都不算完成。

  3. 配置注释只用英文(oslo ASCII 解码),中文说明写进本手册或部署文档。

  4. 不用 nohup、不用 pkill -f 裸杀、不在宿主根命名空间改路由。

  5. 镜像/卷文件变动后同步 DB 元数据,并 openstack image save 回验 checksum。

  6. 重启后先看实例是否 SHUTOFF,再怀疑网络。

5.7 相关文档

文档用途
OpenStack-2025.2-Flamingo-部署文档.md从零安装的完整过程与逐条踩坑记录
deploy/README.md一键部署脚本用法(断点续装、干跑、阶段开关)
deploy/scripts/出口切换、看门狗、开机自检、loop 卷组脚本

本手册中的所有命令与判据均来自 open88 上实际验证通过的环境。 更换主机名、IP、网卡或发行版后,请同步替换:controller、192.168.3.88、 enp2s0、/data、RegionOne。


浏览10 评论0
返回
目录
返回
首页
Openeuler2509 fcitx5 输入法排查与修复记录
↑