
简介这份《OpenStack技术源码模块解读》面向云计算开发与运维人员、源码阅读爱好者以及希望从IaaS层理解开源云平台架构的中高级学习者。资源以Nova项目为切入点系统梳理OpenStack从早期Nova、Swift两大组件到Cinder、Glance、Neutron、Ironic、Keystone、Horizon、Heat等衍生服务的演化脉络并深入讲解Nova的调度器、计算节点、API服务器与数据库接口等核心结构。内容涵盖setup.cfg服务入口、console_scripts入口函数、api.py与rpcapi.py及manager.py的通用骨骼脉络还涉及all-in-one开发环境搭建、pdb断点调试、vim代码跳转配置等实用技巧帮助读者掌握从单组件到整体生态的源码阅读方法。压缩包共1个docx文件约759KB以图文文档形式呈现便于对照源码逐步研读。目前已有105人学习适合作为深入OpenStack源码与二次开发的入门参考。1. 从一份 docx 说起OpenStack 源码模块到底该怎么读很多人第一次拿到「OpenStack技术源码模块解读.docx」这类资料时第一反应是把它当成一本电子书从头翻到尾结果翻到 Nova 的调度器就卡住了——满屏的filter_scheduler、host_manager、resource_tracker不知道哪个才是真正要改的地方。这份文档的价值不在于「读完」而在于它给了你一张地图告诉你 OpenStack 这个庞然大物是由哪些模块拼起来的每个模块负责什么源码入口在哪。OpenStack 本身是云平台搭建的底座Nova 管计算、Neutron 管网络、Cinder 管块存储、Keystone 管认证、Glance 管镜像而源码解读要解决的核心问题是当你要做二次开发、排查线上故障、或者只是想搞懂 openstack 部署之后那些进程到底在干什么时应该从哪个文件、哪个类、哪个方法切进去。这篇笔记面向的是已经能跑起一套 all-in-one 环境、但面对源码不知道从哪下手的工程师也适合正在做 openstack 云平台搭建、想提前理解内部机制的人。我会按「模块怎么分 → 关键调用链怎么走 → 怎么动手验证 → 坑在哪」的顺序把这份 docx 里最值得深挖的部分拆开讲。2. Nova 源码模块拆解从 API 到 Hypervisor 的调用链2.1 Nova 的模块分层与源码目录对应关系Nova 是 OpenStack 里源码量最大、调用链最长的模块也是「OpenStack技术源码模块解读.docx」里篇幅最重的部分。要读懂它先得把它的分层和源码目录对上号。Nova 在逻辑上分四层API 层接收 REST 请求Conductor 层做数据库操作和任务编排Scheduler 层决定虚拟机落到哪台计算节点Compute 层真正调用虚拟化驱动干活。对应到源码目录nova/api/是 API 层nova/conductor/是 Conductornova/scheduler/是调度器nova/compute/是计算层nova/virt/下则是各种 Hypervisor 驱动比如libvirt、qemu、vmwareapi。读源码时最容易迷路的地方是 RPC 调用。Nova 各层之间不是直接函数调用而是通过 oslo.messaging 发 RPC 消息所以你在nova/compute/api.py里看到self.compute_rpcapi.build_and_run_instance()时实际执行体在另一端的nova/compute/manager.py。如果不知道这个机制就会以为代码「断」了。常见做法是先用grep -rn def build_and_run_instance nova/找到所有定义和调用点再顺着 RPC 的topic和server参数确认消息发往哪个服务。下面这段命令用来快速定位一个 API 请求从入口到 RPC 出口的路径以创建虚拟机为例# 在 nova 源码根目录执行 # 1. 找到创建虚拟机的 API 入口 grep -rn def create nova/api/openstack/compute/servers.py # 2. 顺着看它调用了 compute api 的哪个方法 grep -rn def create nova/compute/api.py # 3. 找到 RPC 调用点确认发往哪个 topic grep -rn build_and_run_instance nova/compute/api.py nova/compute/rpcapi.py # 4. 在 compute 层找到真正的执行体 grep -rn def build_and_run_instance nova/compute/manager.py这几条命令的逻辑是先定位 HTTP 入口再定位业务层方法然后找到 RPC 边界最后落到执行端。参数上要注意nova/api/openstack/compute/servers.py里的create方法只做参数校验和策略检查真正的业务逻辑在nova/compute/api.py的create里而rpcapi.py是 RPC 的客户端封装它里面的build_and_run_instance才是跨服务调用的起点。如果你在manager.py里找不到对应方法大概率是版本差异导致方法名变了这时候用grep -rn build_and_run nova/compute/模糊匹配更稳。2.2 Scheduler 调度器Filter 与 Weight 的源码执行顺序调度器是 Nova 里最容易被「玄学」问题缠上的模块——明明资源够虚拟机就是调度失败。要排查这类问题必须读懂nova/scheduler/filter_scheduler.py和nova/scheduler/host_manager.py。调度分两步先过滤Filter掉不满足条件的节点再称重Weight选出最优节点。Filter 在nova/scheduler/filters/下每个文件是一个过滤器比如RamFilter看内存、DiskFilter看磁盘、ComputeFilter看节点是否可用。Weight 在nova/scheduler/weights/下常见的是RAMWeight内存越大的节点权重越高。源码里FilterScheduler._schedule方法是总入口它先调用host_manager.get_filtered_hosts()做过滤再调用host_manager.get_weighed_hosts()做排序。过滤阶段任何一个 filter 返回 False该节点就被剔除。这里有个血泪经验RamFilter默认会考虑ram_allocation_ratio如果你在nova.conf里把ram_allocation_ratio设成 1.5那 8G 内存的节点会被当成 12G 来用调度器认为放得下但实际可能超分导致虚拟机启动失败。读源码时要把配置项和 filter 逻辑对照看。下面这段 Python 片段模拟了 filter 的执行逻辑方便你在本地验证某个节点为什么被过滤掉# 模拟 FilterScheduler 的过滤流程帮助理解源码逻辑 # 实际源码在 nova/scheduler/filter_scheduler.py class FakeHost: def __init__(self, name, ram_mb, disk_gb, vcpus, ram_ratio1.5): self.name name self.ram_mb ram_mb self.disk_gb disk_gb self.vcpus vcpus self.ram_ratio ram_ratio property def free_ram_mb(self): # 源码中 RamFilter 会用 ram_allocation_ratio 放大可用内存 return self.ram_mb * self.ram_ratio def ram_filter(host, requested_ram_mb): # 对应 nova/scheduler/filters/ram_filter.py 的核心判断 if host.free_ram_mb requested_ram_mb: return False, f{host.name} 内存不足: 可用 {host.free_ram_mb}MB, 需要 {requested_ram_mb}MB return True, 通过 hosts [ FakeHost(compute01, 8192, 100, 8), FakeHost(compute02, 4096, 50, 4), ] for h in hosts: ok, msg ram_filter(h, 6000) print(f{h.name}: {msg})这段代码的关键参数是ram_ratio它对应nova.conf里的ram_allocation_ratio。运行后你会看到 compute01 通过、compute02 不通过因为 4096×1.56144 虽然大于 6000但源码里还会减去已用内存实际判断更严格。读源码时要注意RamFilter里用的是host_state.free_ram_mb这个值来自resource_tracker周期上报有延迟所以刚创建完虚拟机立刻再调度可能读到旧数据这就是「明明刚释放了资源却调度不上去」的常见原因。2.3 用 pdb 在源码里下断点验证调用链光看代码容易自欺欺人最有效的验证方式是在源码里下断点让请求真实走一遍。OpenStack 的服务都是 Python 进程可以直接用pdb或debugpy挂上去。以 Nova 的build_and_run_instance为例在nova/compute/manager.py对应方法里插入import pdb; pdb.set_trace()然后重启nova-compute服务再发起创建虚拟机请求进程就会停在断点处。# 1. 编辑源码在目标方法第一行插入断点 # 在 nova/compute/manager.py 的 build_and_run_instance 方法内加 # import pdb; pdb.set_trace() # 2. 重启 nova-compute 服务以 systemd 为例 sudo systemctl restart nova-compute # 3. 另开终端发起创建请求 openstack server create --flavor m1.small --image cirros --nic net-idnet-id test-vm # 4. 回到 nova-compute 的日志终端会看到 (Pdb) 提示符 # 常用命令 # l 查看当前代码上下文 # n 单步执行下一行 # s 进入函数内部 # p var 打印变量值 # c 继续执行这里的关键是pdb会阻塞服务进程生产环境千万别这么干只在测试环境用。参数上l看上下文时注意行号p self可以看当前对象p instance能看虚拟机对象的状态。如果断点没生效先确认改的是不是正在运行的代码路径——OpenStack 部署方式不同代码可能在/usr/lib/python3/dist-packages/nova/而不是你 clone 的源码目录用python -c import nova; print(nova.__file__)确认实际加载路径。这个习惯能帮你省下大量「改了没反应」的后悔药时间。3. 避坑与排查读 OpenStack 源码时最容易翻车的 5 个点3.1 现象改了源码重启服务不生效原因OpenStack 通过pip安装时代码在site-packages下你改的是 clone 的源码目录两者不是同一份。解决用python -c import nova; print(nova.__file__)确认实际路径要么改对路径要么用pip install -e .以开发模式安装让源码目录直接生效。3.2 现象RPC 调用报MessagingTimeout原因Nova 各服务通过消息队列通信nova-compute没起来、rabbitmq连接异常、或者transport_url配置不一致都会导致。解决先systemctl status nova-compute看服务状态再检查/etc/nova/nova.conf里所有服务的transport_url是否一致最后用rabbitmqctl list_queues看队列是否堆积。3.3 现象调度失败但资源明明够原因resource_tracker上报有周期默认update_resources_interval是 60 秒刚释放的资源不会立刻反映到调度器。解决临时调小该参数方便调试但生产环境别调太小会增加消息队列压力。另外检查ram_allocation_ratio和cpu_allocation_ratio是否被改过。3.4 现象源码里找不到文档提到的类或方法原因OpenStack 版本差异大N 版和 Yoga 版的模块拆分可能完全不同比如nova/api/openstack/compute/下的文件在不同版本里增删频繁。解决先确认版本nova-manage version再对照对应版本的源码分支看别拿旧文档套新代码。3.5 现象pdb 断点导致服务卡死原因pdb.set_trace()会阻塞整个进程而 OpenStack 服务是多线程/多协程的一个请求卡住可能拖垮整个服务。解决只在测试环境用且用完立刻删掉断点重启服务。更安全的做法是用debugpy远程调试或者用日志 oslo.log的DEBUG级别打点。4. 从源码到落地用 Kolla 部署一套可调试的 OpenStack 环境读源码最怕没有可复现的环境。用 Kolla 部署一套容器化的 OpenStack是当前比较省心的方式而且容器里可以直接进源码目录调试。Kolla 把每个服务打包成容器源码在容器内的/var/lib/kolla/venv/lib/python3.x/site-packages/下你可以docker exec进去直接看、直接改。# 1. 安装 kolla-ansible以 pip 为例 pip install kolla-ansible # 2. 准备配置文件 sudo mkdir -p /etc/kolla sudo chown $USER:$USER /etc/kolla cp -r /usr/local/share/kolla-ansible/etc_examples/kolla/* /etc/kolla/ cp /usr/local/share/kolla-ansible/ansible/inventory/all-in-one . # 3. 生成密码 kolla-genpwd # 4. 引导部署all-in-one 模式 kolla-ansible -i all-in-one bootstrap-servers kolla-ansible -i all-in-one prechecks kolla-ansible -i all-in-one deploy # 5. 部署完成后进入 nova_compute 容器看源码 docker exec -it nova_compute bash python -c import nova; print(nova.__file__)这套流程的关键参数在/etc/kolla/globals.yml里kolla_base_distro选ubuntu或centosopenstack_release选版本号network_interface填你的网卡名。部署完成后docker ps能看到一堆容器nova_compute、nova_api、nova_scheduler各司其职。进容器后源码路径就是python -c import nova; print(nova.__file__)输出的那个目录直接vim改改完docker restart nova_compute就生效。这比在物理机上折腾依赖省事得多也方便你反复试错。提示Kolla 部署对资源有要求all-in-one 至少 8G 内存、40G 磁盘否则 prechecks 阶段就会报资源不足。5. 进阶技巧用 osprofiler 追踪跨模块调用耗时当你已经能读懂单个模块的源码后下一步是搞清楚一次请求跨了多少模块、每段耗时多少。OpenStack 内置了osprofiler可以在 API 请求里带上 trace id把 Nova、Neutron、Cinder 的调用链串起来。开启方式是在/etc/nova/nova.conf里加[profiler]段enabled true、trace_sqlalchemy true然后发请求时加--os-profiler参数。# 1. 在 nova.conf 中启用 profiler # [profiler] # enabled true # hmac_keys SECRET_KEY # trace_sqlalchemy true # 2. 重启 nova 相关服务 sudo systemctl restart nova-api nova-compute nova-scheduler # 3. 发起带 trace 的请求 openstack --os-profiler SECRET_KEY server create --flavor m1.small --image cirros --nic net-idnet-id trace-vm # 4. 请求返回的 header 里会有 X-Trace-Info用它去查调用链 # 如果接了 osprofiler 的存储后端如 MongoDB可以直接看火焰图osprofiler的价值在于它把 RPC 调用、数据库查询、HTTP 请求都打上了时间戳你能一眼看出是调度慢、数据库慢还是 Hypervisor 慢。参数上hmac_keys是签名密钥防止 trace 被伪造trace_sqlalchemy打开后会记录 SQL 耗时排查数据库瓶颈特别有用。我一般会在测试环境常开 profiler生产环境只在排查特定问题时临时开因为它的性能开销在 5% 到 10% 左右。最后说个我自己的习惯读 OpenStack 源码千万别从第一行读到最后一行而是带着一个具体问题去读比如「创建虚拟机时安全组规则在哪生效」然后顺着调用链一路 grep 下去。每读通一条链就在 docx 上补一张自己的调用图几个月下来这份文档就变成了你自己的源码地图。希望帮到你。本文还有配套的精品资源点击获取