惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
N
News and Events Feed by Topic
S
Schneier on Security
G
GRAHAM CLULEY
Scott Helme
Scott Helme
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
CERT Recently Published Vulnerability Notes
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
T
The Blog of Author Tim Ferriss
Cisco Talos Blog
Cisco Talos Blog
P
Privacy & Cybersecurity Law Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
Blog — PlanetScale
Blog — PlanetScale
Project Zero
Project Zero
MyScale Blog
MyScale Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
The Last Watchdog
The Last Watchdog
Vercel News
Vercel News
The Cloudflare Blog
C
Check Point Blog
Help Net Security
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
腾讯CDC
NISL@THU
NISL@THU
S
Security @ Cisco Blogs
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
S
SegmentFault 最新的问题
MongoDB | Blog
MongoDB | Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
AWS News Blog
AWS News Blog
Cloudbric
Cloudbric
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Vulnerabilities – Threatpost
S
Secure Thoughts

卡瓦邦噶!

服务器高性能网络调优 | 卡瓦邦噶! 为何写作 | 卡瓦邦噶! 读《金阁寺》 | 卡瓦邦噶! 雨季又来 | 卡瓦邦噶! MTU Probe 引起的初始延迟 | 卡瓦邦噶! 3.5 秒的固定延迟问题 | 卡瓦邦噶! 学习网络的一点经验 | 卡瓦邦噶! ARP 问题诊断 | 卡瓦邦噶! 网络断断续续…… | 卡瓦邦噶! Piccolo P2P 镜像分发 | 卡瓦邦噶! 一起看电影 | 卡瓦邦噶! 《征服C指针》 | 卡瓦邦噶! 我的姥姥 | 卡瓦邦噶! Python的哲学 Python 3.5的新特性 学校不教的计算机课 垃圾回收(GC)的三种基本方式 在编程中体验纯粹的快乐 从《美丽新世界》谈自由 在快钱实习 迷人的嗓音和迷人的故事——《Sleepyhead》 Python 的十个自然语言处理工具 记一个愚蠢的bug 一年炉石传说的游戏体验 《以撒的结合:重生》网页版图鉴 分清 C++的指针、引用和数组 笑话三则 自由比皇帝更伟大——《悲惨世界》笔记 Git 10 周年访谈:Linus 讲述背后故事 用 0x3f3f3f3f 设定最大int值的优点 Joel给计算机系学生的建议 一个词法分析器的简单实现 怎样才算健康的生活方式 MacVim 配置攻略 学习培训课程的视频效果好吗? 语言的控制 可悲的大多数 CSS样式思维导图 2014年终总结 奥巴马成为首位写程序的美国总统 青岛老城区的下水道好在哪里? 做优秀 UI 的七个建议(第二部分) 选择爱情的骑士 Git简明教程 Java集合总览 读 《1984》 java问答:终极父类(六)——等待/唤醒和接口 Java 问答:终极父类(五)——toString() Hyperlapse快速视频背后的技术细节 平庸之恶 Java程序员须知的七个日志管理工具 苏州 逛书摊随想 关于考试作弊 你的工作不仅仅是编程 推荐在线学习Java的英文资源 关注女性命运——《千禧年三部曲》 用好你的幻灯片——《演说之禅》 使用ReentrantLock和Lambda表达式让同步更纯净 新手学编程,从哪里开始? 程序员都是工程师吗? 不要学习代码,要学会思考 Java 问答:终极父类(四)——hashCode() Java 问答:终极父类(三)——finalize()和 getClass() 程序员职业之路的选择 我是一名摄影家 写给何小树的城市指南 为什么一些语言会比别的快? Java的常见误区与细节 跟朋友在一起玩游戏 死神永生——读《三体》 五种类型的程序员 创业圣经——读《黑客与画家》 纪念加西亚·马尔克斯 Junit中处理异常的另一种方式:catch-exception Java8采用Martin Fowler的方法创建内部DSL Linux HotSopt虚拟机GC线程的CPU占用率 J2EE概念介绍 如何成为一名黑客 Java 问答:终极父类(二)——equals()方法 为什么我喜欢Java Java 问答:终极父类(一)——clone()方法 七个改变世界的Java项目 java中默认类型转换的小问题 传统与创新 欢迎来到互联网 莫言和马尔克斯——读《生死疲劳》 位运算的妙用 读《人为什么活着》 写博客教会我的事情 中国特色操作系统 2013年总结 《永不妥协》影评 恨不相逢未嫁时——《廊桥遗梦》影评 如何优雅地使用PPT 给明年依然年轻的我们 天才与柱子 黑客守则和黑客精神 Looking for Freedom——《被解救的姜戈》 简洁之道
Keepalived 脑裂问题排查
laixintao · 2024-12-29 · via 卡瓦邦噶!

用户报告问题,说在虚拟机里面启动的 Keepalived 有脑裂问题,一启动就开始脑裂了。

Keepalived1 是一个基于 LVS 的负载均衡和高可用框架。负载均衡主要是通过 VRRPv2 协议来实现的。VRRP 协议2在这个博客中介绍过,主要场景是两个路由器可以通过 VRRP 协议来协商出来一个 master,对外提供服务,当 master 挂的时候,slave 会成为 master 继续提供服务。

VRRP 的全称是 Virtual Router Redundancy Protocol,Keepalived 可不是 router,为什么用这个协议呢3?简单来说,Keepalived 要提供的是一个高可用的 VIP 服务,而 Virtual Router 本质上也是一个 VIP 来给其他的 Host 当作网关,这样一想,就很合理了。

Keepalived 实例之间无法达成一致,肯定是 VRRP 协商失败,而 VRRP 又是机器简单的协议,只有一种包的类型。出现 2 个 master 节点,那就肯定是 slave 的节点收不到 master 的 VRRP 协议包,认为 master 挂了,所以站出来当 master。

首先,用 tcpdump 检查了一下两个 keepalived,确实都在发送 VRRP 的包。而且VRRP 包的内容,如 auth,组 id,权重等,都正确。并且都只看得到自己发送出去的包,无法收到对方的包。

那接下来就来排查为什么这个包无法发送给 VRRP 的 slave。

虚拟机环境的网络简化如下。

虚拟机环境的网络架构

这个图看起来复杂,其实逻辑很简单。物理机 Host 使用 bonding 连接交换机,在 bond0 接口上配置 VLAN 封装,和交换机做 trunking,这一层对物理机内的网络使用几乎是透明的。然后虚拟机内网络使用 TAP4,所有 VM 内 eth0 发送的包会出现在 macvtap1 上,然后从 Host 的 bond0.1000 出去。 macvtap 其实就是 TAP 设备加上一个 bridge5,macvtap 基于 macvlan driver,使用一个 module 解决了原来 TAP + Bridge 的工作。

下一步就是定位 VRRP 包丢在了哪里,虽然涉及的网络 interface 很多,但是一个一个来排查就行了。首先给这个网络做了个简单的体检套餐,发现 ICMP 还是 TCP 都是一点问题没有,只有 VRRP 协议有问题。VRRP 协议是基于组播 Multicast 的,直觉上觉得可能是什么 ACL 把组播网络给 DROP 了。

从 Keepalived 发包的实例开始抓包,下一步直接抓发包的物理机接口 eth0 (二分查找定位么),确认 VRRP 正确发出去了,然后去收包的物理机上抓 eth0,也收到了,直接排除了交换机的问题。再抓 bond0.1000 接口,也抓得到,排除了 bonding 和 VLAN 问题。

下一步是 [email protected],也抓得到,然后去收包的 VM2 抓包 eth0,抓不到。那丢包就发生在 macvtap1 -> eth0 中。感觉已经接近真相了!

实际上并没有……

定位到这里之后,后面花了几个小时来研究为什么 macvtap1 的包没有转发到 eth0 中。

期间研究了 macvtap 设备的原理,libvirt 相关的文档,中间还有 chatGPT 这个半吊子瞎出主意,甚至把相关的 sysctl 参数都看了一遍,rp_filterxx_forwarding 之类的,仍然没有解决问题。这些没有用的排查就不记录了。

物理机的 macvtap 的 TAP 设备是由 qemu libvirt 接管的,负责转发到虚拟机中去。在研究 libvirt 和 multicast 流量的时候,发现了这个问题和回答6,虽然没有直接解决我的问题,但是感觉脑中一道闪电划过,有一个重要的本质问题被我忽略了——VRRP 是组播网络

单播是点对点发,广播是点对所有点群发,组播的特点是点对多点群发,「多点」指的是哪些点呢?怎么知道多点包括了哪些点呢?本质的原理是「订阅」,订阅了特定流量则会收到,如果不订阅,则收不到。

在网络上,多个设备之间订阅组播是通过 IGMP 协议7实现的。在同一个设备上,就是设备自己的实现了。

有了这个想法之后,我马上在 VM 中和 Host 中运行了 ip maddr show dev 命令进行验证。结果如下。

在 VM 中的运行结果
在 Host 中的运行结果

这条命令的含义是,列出来当前这个接口订阅的组播流量。通过结果可以看到,在 VM 中订阅了 VRRP 协议规定的组播地址,但是在物理机的 macvtap 接口上,就没有订阅这个地址。所以物理机的接口在收到发给 224.0.0.1 的 VRRP 流量之后,会认为当前这个接口没有订阅过这个组播,所以不需要这些流量,直接忽略。这是组播协议预期的工作方式,所以当我在排查接口的丢包参数的时候,都没有发现什么异常,因为这不算做是丢包吧,而算作是正常的处理方式。

那么为什么会出现这种情况呢?

按照组播协议的工作方式,当需要组播流量的时候,需要向操作系统通过 syscall 来发出「订阅」8,因为协议是由操作系统来处理的。但是我们这里存在 2 个操作系统,VM 是一个操作系统,Host 是一个操作系统。如上图所示,虽然 VM 知道订阅了这个组播地址,但是 Host 操作系统并不知情,两个系统是隔离的。所以当 Host 收到组播流量的时候,直接忽略了。

解决办法是,对接口设置 ip link set dev macvtap8 allmulticast on,意思是告诉接口,把所有的 multicast 都给收了,这样 VM 内的接口决定处理还是忽略,就正常了。(libvirt 也有 trustGuestRxFilters9 的配置选项)

VRRP 脑裂问题需要避免,在物理网络中,网关之间的 vrrp keepalive 会使用专用的 keepalive 线路,并且多条物理线路做 LACP 高可用。

  1. https://keepalived.readthedocs.io/en/latest/introduction.html ↩︎
  2. 数据中心网络高可用技术之从服务器到网关:首跳冗余协议 VRRP ↩︎
  3. Keepalived 的系统设计:https://keepalived.readthedocs.io/en/latest/software_design.html ↩︎
  4. TAP 设备在 VPN 和虚拟机网络中比较常见:https://en.wikipedia.org/wiki/TUN/TAP ↩︎
  5. https://virt.kernelnewbies.org/MacVTap ↩︎
  6. https://superuser.com/questions/944678/how-to-configure-macvtap-to-let-it-pass-multicast-packet-correctly ↩︎
  7. https://en.wikipedia.org/wiki/Internet_Group_Management_Protocol ↩︎
  8. 如何使用组播的教程 https://tldp.org/HOWTO/Multicast-HOWTO-6.html ↩︎
  9. https://libvirt.org/formatnetwork.html ↩︎