Netflix的工程师们发现了容器扩缩容中深层次的性能瓶颈,其根源并非仅在于Kubernetes或 containerd,而是深入到了 CPU 架构与 Linux 内核本身。在一篇详细的博客文章中,Netflix 技术专家解释了他们迁移到现代容器运行时后,如何在内核的虚拟文件系统(virtual filesystem,VFS)中发现了全局挂载锁(global mount lock)上出人意料的竞争问题,这表明,即便在性能强劲的云服务器上,底层硬件拓扑与锁竞争也会限制数百个容器的并发扩缩容。
该问题最初显现时,运行 Netflix 工作负载的节点在高并发下开始出现数十秒的停顿,简单的健康检查探针会超时,容器创建被冻结。调查显示,在多层容器镜像启动过程中,挂载表(mount table)会急剧膨胀,当 containerd 执行数千次绑定挂载操作以映射每个镜像层的用户命名空间时,内核的全局挂载锁承受了巨大压力。每个容器都需要数十次挂载与卸载操作,在大规模流量突增时,累计的挂载系统调用很容易超过 20000 次,而所有这些调用都需要访问同一个内核锁,这是操作系统深处一个典型的并发瓶颈。
Netflix 性能团队发现,并不是所有 CPU 架构在此类负载下都有相同的表现。在较旧的双路(dual-socket)AWS r5.metal 实例(具有多个NUMA域与基于网状结构的缓存一致性)上,高并发会加剧共享缓存与全局锁的竞争,使性能严重下降。相比之下,较新的单路实例,比如,AWS m7i.metal(Intel)和 m7a.24xlarge(AMD),采用了分布式缓存架构,扩缩容流畅得多,即使容器数量上升,停顿也更少。分析表明,NUMA 效应、超线程与缓存微架构等因素会显著影响全局锁竞争在系统中的传播方式。
Netflix 工程师证实,硬件设计在大规模场景下至关重要:NUMA带来的远端内存访问延迟与竞争的超线程会加剧锁等待,而分布式缓存设计则能减轻瓶颈。例如,在某些配置下禁用超线程可以将延迟降低最高达到了 30%,而单路实例则完全避免了跨节点内存访问的性能损失。这些实验表明,要为容器密集型工作负载实现可靠扩缩容,需要同时理解软件并发与硬件行为。
凭借这一发现,团队探索了两种主要的缓解方案:采用更新的内核挂载API,这个新的 API 会使用文件描述符完全避免全局锁,以及重新设计叠加(overlay)文件系统的构建方式,使每个容器的挂载操作次数从与镜像层数呈线性关系(O(n))降至每个容器均是常量时间(O(1))。Netflix 选择了后者,因为它可以更广泛地部署,无需依赖新版本内核,并在实践中消除了挂载竞争。通过将多层挂载归组到同一个公共父节点下,内核的挂载负载大幅下降,即使在高负载下容器启动也更加平稳。
Netflix 同时从硬件层面进行优化,将高负载工作负载调度到能更优雅处理全局锁的 CPU 架构上,将硬件感知调度与软件改进相结合。他们的发现揭示了一个可广泛适用于大规模组织的教训:要在分布式系统中实现可预测的性能,通常需要全栈协同设计,从容器编排、文件系统使用,到内核的内部机制与 CPU 微架构。
Netflix 团队发布这篇深度分析的目的是向更广泛的工程社区分享这些性能见解,并强调,现代云平台中的瓶颈可能出现在极少有开发者会关注的地方,而解决这些问题可能既需要底层系统调优,也需要清晰理解运行工作负载的硬件。
目前,已经有多家组织发布了与 Netflix 在容器扩缩容和内核级竞争方面的发现高度一致的最佳实践。这些实践强调硬件感知的工作负载放置,尤其是在运行高密度容器工作负载的场景中,需要理解 NUMA 拓扑、缓存一致性设计与超线程行为。同时,推荐优先使用单路架构,或谨慎选择能最小化跨域内存延迟的实例系列,以及在系统密集型操作中使用裸机或专属实例。在软件层面,Kubernetes与容器运行时社区提倡通过减少挂载与卸载操作、合并文件系统层,并尽可能采用更新的内核 API 来避免共享瓶颈,从而降低全局锁竞争。
此外,谷歌、Meta等均组织强调,深度的系统级可观测性是扩缩容实践的关键,可以使用eBPF、perf、火焰图(flame graphs)等工具检测高并发下隐藏的内核停顿与锁竞争。云厂商也建议利用本地临时存储进行镜像缓存、优化叠加文件系统,并调优运行时配置以降低启动时的放大效应。这些实践共同反映了行业向软硬件协同设计方向的更广泛转变:可预测的容器扩缩容不仅依赖于编排与运行时改进,还依赖于对 CPU 微架构、文件系统行为与内核内部机制的理解,而这正是 Netflix 分析中强调的全栈方法。
查看英文原文:Netflix Uncovers Kernel-Level Bottlenecks While Scaling Containers on Modern CPUs





