NX-OS(N7K) 也能跑崩(Nexus 7000 Stuck Sending TCNs Every 2 Seconds)

题目有点夸张,但是确实对我们的生产环境造成了很大的影响,越是基础的部件出现问题造成的损失越大。这个是触发该 bug 的两个时间段内,一台前端机器到部分后端机器的丢包情况监控。

这个 bug 跟我两年前碰到的 2.6.32 内核的 208.5 bug(1, 2) 倒是很像,弄不好又是哪个无证码农犯了除以 0 了。

发现这个 unicast flooding 的特征还是蛮明显的,比如 iftop 发现竟然出现了其他主机之间交互的流量,tcpdump 抓包也能观察到类似的现象,除了一些 ARP、HSRP 的请求回应之外不应该有大量的其他的包了。这篇文档总结了出现了该情况的几种可能。

总的来说,NX-OS 虽然已经上市好几年了,但还是不够成熟,无意中还发现可能存在 kernel panic 的风险。考虑到可能有人因为权限的问题无法打开上面的链接,我这里附一份完整的存档:

Nexus 7000 Stuck Sending TCNs Every 2 Seconds
CSCuo80937

Symptom:
If there is any TC after upgrade to 6.2.(6), 6.2.(6a) or 6.2.(8), then after
approximately 90 days of active supervisor uptime, STP TC BPDUs are sent out
every 2 seconds for a long period of time.

Conditions:
Nexus 7000 or 7700 running 6.2(6), 6.2.(6a), or 6.2(8).

Workaround:
In order to circumvent this issue until an upgrade to fixed code can be
performed,
execute the appropriate workaround depending on whether you have a
dual-supervisor or single-supervisor
configuration before each 90 days of Active supervisor uptime.

For dual-supervisor setups:
1. Reload the standby supervisor using cli "reload module x" where x is
standby supervisor slot number.
2. Use the 'show module' command to confirm that the standby supervisor is up
and in the ha-standby mode.
3. Use the system 'switchover command' to switch to the standby supervisor.

For single-supervisor setups:
1. Upgrade to 6.2.6b or 6.2.8a, depending on your business requirements.
2. Reload the switch.

Further Problem Description:
Active Supervisor Uptime can be found from "show system uptime":
N7K-7009-3# show system uptime
System start time: Fri Oct 25 09:40:58 2013
System uptime: 236 days, 8 hours, 56 minutes, 59 seconds
Kernel uptime: 110 days, 23 hours, 7 minutes, 49 seconds
Active supervisor uptime: 110 days, 23 hours, 2 minutes, 23 seconds <<<<<<<<<<<

startup 的安全问题

安全这个问题好像离绝大多数的 startup 比较遥远,好像谈到安全只有 BAT 这类规模的才会重视。
绝大多数的 startup 起家都是短糙快,怎么好搞怎么搞,怎么方便怎么搞,怎么省事怎么搞。再加上「绝大多数的创业公司都喜欢宣称自己是「平均年龄25 的年轻团队。」,正面理解起来是有活力的团队,反面理解起来,其实代表的是「招不到人,只能忽悠年轻人,组建的一只没经验靠人力时间堆砌的弱逼团队」」,其整体的安全性可想而知。
这或许在初期并没有什么问题,因为本来知道你的人就不多嘛,cracker 们也没兴趣花时间在只有几千几百用户的上团体上。
但是如果你很幸运,成为了那百分之几甚至千分之几的存活下来的,那就是另外一回事了,你们的产品会在短期内被很多的用户知道,得到了不少用户的认可,用户数量逐渐变多,接下来可能要经过一段爆发性的增长,一方面来说是好事,但是,另外一方面,对公司整体的技术也是一个非常大的挑战,再加上很多都是没什么经验的工程师,真的就是摸着石头过河了,在这期间,会经历若干次的宕机服务不可用事故,为了尽快的 available,不得不牺牲很多方面,正所谓 tradeoff,比如牺牲了安全。
然后名气慢慢大了,积累的用户数量在圈子里面也数一数二了,白帽子也好黑帽子也罢,都对其产生了很大的兴趣,随便扫扫,就发现了不少有价值的信息,至于什么信息大家自己补脑吧。
好在有类似 wooyun 这样的平台,突然有一天 startup 在 wooyun 上收到了一封「弱口令」(关于弱密码的危害,请看这里)的漏洞提交,至此,公司开始对安全有了一定的认识,发现原来弱口令还是导致直接渗透到内网,于是上上下下一顿整改,但这毕竟只是冰山一角,前几年为了方便留下的祸患太多了,接下来,不停的收到若口令、权限绕过、设计缺陷等等各种各样的漏洞报告。虽然大多数人都很重视这类问题,积极的配合整改,但总会有那么些人不以为然,认为这些事情不值一提,根据 2/8 原则,80% 的漏洞都是由 20% 的人造成的,直到某一天,发现公司的用户信息、代码被拖库了,傻眼了。
上面可能是很多 startup 都要经历的过程:为了方便随便上线,携带敏感信息的配置文件不加任何处理,无任何限制的开放对内服务的访问权限,弱密码,以上还仅仅是技术层面的因素,如果遇到叼炸天的工程师自以为是等人为非技术因素,后期需要改进沟通的更是难上加难。
出几次事故也未必是坏事,最起码让我们明白,不好好对待这个问题,迟早是要出大事的,用户信息泄漏了导致公司陷入危机的不在少数,那些处在风华正茂认为老子(或许有老娘这么一说)天下第一无人能敌写代码如行云流水天马行空 bug free 的也是会出些非常低级的错误的。很多东西,尤其是安全,仅仅是从技术层面加以控制是完全不够的,更多的是需要从行政手段上加以干预,有奖有惩,才能从根源控制。当然,上面说的这些尤其是最后一点在一个仅仅发展了两三年,连基本的工程师制度惩处措施都没有,没有强大的执行力或者说是重视此问题的有话语权工程师的干预下,是不可能做到的。

最近半个月的工作[14P]

5 月发生的事,6 月补充完,9 月发出来 ;-)


5 月 13 日周二
开始我们另外一个核心 IDC 最后一次常规性 10G 升级,下面的一部分我们后来把他总结成了《5 月故障总结(post-mortem)》
回家睡了会儿,3:00 am 起床,4:00am 开始连续干了 6h
回公司休息了 1h,塞了点巧克力复活
中午去水立方进行了常规的 1h 训练
回来面(对了,我们目前招高级应用运维工程师 PE,有兴趣的给我简历,邮箱是 w 在 umeng 点 com)了一个候选人,结果在我问到第二个问题的时候就怂了,第一个问题是常规性的自我介绍,第二个问题也是我最喜欢问的问题之一,最近半个月在做什么
由于 uplink 依然在老的网络环境中,我们老的 3750X 到新的 Nexus 中间的 8G port channel 链路中的一条物理链路由于 LB 的算法不科学,导致其打满丢包的状态,当机立断,直接让 NE 更改了 LB 的算法,效果明显

5 月 14 日周三
由于 uplink 这个不稳定因素的存在,开会讨论最后一次也是最重要的升级以及收尾工作,由原本的周四凌晨升级提前到了周三凌晨进行
10G 的最后一次也是最重要的升级,应为涉及到切换我们的 uplink,迁移我们的 GW 以及我们两地双机房中间的互联链路迁移
晚上去和颐休息了 3h,凌晨 3 点干到早上 7 点,期间除了 uplink 切换成功之外,其他的均已失败回滚告终,回酒店休息了 3h
中午回公司继续,讨论了凌晨出现的一些问题以及解决方案,其中我们两地双机房互联链路不通的问题最后发现是 HSRP 的问题
凌晨 GW 迁移失败之后,我跟我们 ne, director 回公司模拟了一下当时出现问题的场景,想了几种可能的原因,不过都被实际的模拟结果所否定,唯一的可能性就是服务器会自动的更新 arp 表,找到新的 GW 地址
下班之前,上面遇到的所有问题都已经找到了问题的根源,想到了对策,唯独 GW 的问题,这个对我们整个生产环境的影响绝对是毁灭性的,一旦 GW 迁移失败,我们所有跨 VLAN 的访问都将失败,由于当时时间太紧迫,根本没有时间让我去 debug 就回滚了,我也就无法得知当时真正的现象以及后续的细节
临走之前,我们 director 问我要不要他过去帮忙,我当时是拍着胸脯说的「相信我,你回家休息吧」,虽然我当时有 95% 的把握确认了上面提到的迁移失败的原因以及 80% 左右的把握让我在非常短的时间内 debug 找到问题并且修复,其后者是最具有挑战性的

现在看到的我们的还是 1G 的上联,等你看到这篇博客的时候,应该已经升级到了 10G 的上联了

5 月 15 日周四
这次升级提前预留了充足的时间,从 3:30 – 6:00,我觉得 3h 的时间足够我 debug 一个中等难度的线上问题了
跟昨晚一样,先是回酒店休息了一下,凌晨 2 点开足马力一直干到了早上 8 点多,GW 的问题也在我们开始的第一步被我很快的发现了问题的原因并且修复,两地双机房互联 HSRP 的问题也后续被我们 ne 一举解决,「基本完美」收官,为什么这么说?因为后续的几天出现了若干的问题,好在都不是我们核心的 Nexus 引起的
回酒店休息到 11 点,打车回家准备继续休息,结果在车上就收到报警说我们的一台前端的 ngx 挂了,当时电话跟我们工程师沟通了下,看现象不大像是新升级的网络造成的,回家又花了 1h 时间救了把火,最后查明原因发现确实跟网络没有关系,只不过在这个敏感的时间点上,出现任何的问题,正常人都会不由得往网络上面倾斜
下午先赶到公司跟我们 director 沟通了进展的,然后赶到清华,在那儿度过了下午剩余的时间,干嘛的了?我花了 3h 的时间去拜拜 RMS 大神,花了 1h 的时间跑到教室外面的走廊插上了 3G 网卡排查了一起路由问题
RMS 大神确实蛮有意思的,下面这三段视频是我当时在现场拍的,虽然 RMS 说不要把这些视频照片传到 youtube, instgram 上,但我还是本着共享的精神跟大家分享了:

  1. Windows is malware
  2. Dancing during class break
  3. St. iGNUcius avatar

下午在会场收到反馈说,我们某个 storm cluster 的处理性能出现了问题,时间点跟我们升级网络的时间几乎吻合,但是从我们内网的各项监控指标来看,数值得到了前所未有的好转,pkg loss 由原来的 8% 直接变为了 0,latency 也由原来高峰时期动辄 4, 5ms 直接下降到了 0.2ms 以下,直觉告诉我几乎不可能是核心网络引起的,但是,没有更有力的数据来证明这些
看码农们在邮件里面以 「猜测」、「推脱」的姿态开始了问题的 debug 之后,我直接以「明天人齐了一起讨论下吧。」结束了这场闹剧
听完演讲之后本想回公司报个销就回去休息的,结果的结果,碰巧我们一个核心业务线上出现了很严重的性能问题,伴着麦当劳雪碧继续搞到了接近凌晨,没找到的问题原因,但是紧急扩容了一些机器,情况有所好转

两个出口的 ngx 都挂了


两个出口的流量一个跌没了一个直接爆了

Continue reading

调整 ring buffer & interrupts affinity 的重要性

最近线上出现了不少由于 ring buffer 设置过小而导致的丢包问题问题,这个值在这之前我们一直使用的是出场的默认值,因此跟动辄 2048 的 max 相比,200 或者 500 确实小了点。
比如看看某台 web server 的监控

看了下 ring buffer 以及 interrputs 的分布
# ethtool  -S em2 | grep dis
     tx_discards: 0
     rx_discards: 77491

# ethtool  -g em2
Ring parameters for em2:
Pre-set maximums:
RX:   2047
RX Mini:  0
RX Jumbo: 0
TX:   511
Current hardware settings:
RX:   511
RX Mini:  0
RX Jumbo: 0
TX:   511

默认的太小了,适当的调大。 另外,由于这台机器网卡本身的问题,无法均匀的分散 interrupts,只能先把能分散的给分散了。记得把 irqbalance 给关了,这玩意儿没什么用:
# /etc/init.d/irqbalance status
irqbalance is stopped

关键还是配置管理做的不到位,不然不会出现这么低级的错误。

Velocity 2014

这是第三次参加 Velocity,去年的整体感觉不怎么样的,今年的比去年进步不少,我选择听的几个主题都激发了不少的灵感。
第一天
上午的错过了没去听的成,源于 google Calendar 提醒我的时候我还在时差 1h 的济州,等上午去公司的时候才发现今天是 Velocity 的第一天,于是吃完饭赶了过去。
下午第一个是《Building Operable Systems》,演讲者 Mark Imbraco。总结了相当有价值的经验,高度的凝练,包括 configuration management 的是适用场景,metric collection 的重要性,metric report,logging,process inspection(passive, active),feature flags 这个有点像 proc 下面的开关,1 既可以开启,0 即可关闭,要做到这点是需要开发发不少精力的,还有 timeout 的检测,这个包括从基础的网络层到 app 的所有涉及 timeout 的监控。还包括 failure testing,里面有提到 chaos monkey 以及 post-mortem
第二个是搜狗的《商业数据库自动化运维平台》,整体感觉是基本完全独立的一套系统,连用户权限、ssh 之类的都是自己搞的一套,这个话题比较小,DBA 更需要关注。
然后是阿里的《阿里 CDN 技术揭秘》,讲的最无聊的一个主题,很多是在展示自己研发的一套系统多么的牛逼,对于绝大多数的公司没有什么可借鉴性。
最后一个是 yahoo 的两个工程师负责部署上万台服务器的感想,总结起来就是要保持环境的一致,模块的解耦合,接口的标准化,单包部署以及去中心化,还是揭露了 yahoo 内部的不少工具链,包括对应的 haproxy、daemontools(start, stop, restart, status etc.) jekins 等等。

第二天
上午第一场还是昨天 DigitalOcean 那位回顾了自己从业 20 多年的 turning point,真的是看着互联网长大的。
第二场是 Linkedin 的工程师介绍了 SPDY&HTTP/2 协议,下一代 web 协议基本是毋庸置疑了,并且经过他们的实践发现,在半径七八百公里之内,实用 SPDY 的的综合效果会比使用 CDN 好。
最后一场是 apple 的 Leif Hedstrom 分享了如何使用 ATS 构建开源的 CDN,里面涉及了不少跟 Nginx、Varnish、Squid 的对比,基本是完暴后面三个了。有意思的,他列举了构建自己的 CDN 以及不构建自己 CDN 而是使用第三方 CDN 的理由,都说的有理有据,关键还是看自己的需求。
下午先是阿里业务网络服务质量分析,
然后是美团的通用性能监控平台,这个在他们的技术博客上已经有所涉及,更多的是前端上的优化,顺便推荐下他们的技术博客,写的蛮有价值的。
最后一场是七牛云存储的成本计算,涉及的面非常广,从各个角度分析了存储的成本构成以及为什么构建在云上的存储在正常情况下会比自己构建一整套的存储成本更低。
下面这个是我整理的一个简单内部分享文档

NAT 跟默认网关的问题(dual NAT)

由于要做数据同步,需要对我们内网的机器做 1 对 1 IP nat map,这样可以通过访问一台 nat 路由设备 map 到我们内网的机器。

先说常规性的做法。
一般情况下,这台 nat 设备会充当内网的 gateway,这样在这台 nat 上做一个 dnat 就可以顺利解决了。比如我 GW 的地址是 192.168.1.24,我想通过一对一的方式 map 到后面的 192.168.1.33 这台开放了 28017 TCP 的机器:
# iptables -t nat -A PREROUTING -d 192.168.1.24 -j DNAT –to-destination 192.168.1.33

像上面这样就可以了,但是如果 192.168.1.24 这台机器本身就开放了 28017 端口则会比较悲剧,因此,另外一种做法是选一个不存在的 IP,比如 192.168.1.200,这样可以任意的建立 socket 而不用担心其 TCP 端口被占用:
# iptables -t nat -A PREROUTING -d 192.168.1.200 -j DNAT –to-destination 192.168.1.33

当然,上面这两种方式都不是很规范,比较好的还是指定 IP 以及 port,像下面这样:
# iptables -t nat -A PREROUTING -p tcp -m tcp -d 192.168.1.24 –dport 10000 -j DNAT   –to-destination 192.168.1.33:28017


上面的情况比较简单,现在来看看下面这种情况,也就是非常规性的做法,专业术语叫 "dual NAT"。
环境跟上面的不大一样,最终要访问的机器的 default gateway 并非指向了 nat 设备,也就是他们二者没有任何关系。具体的环境可以看 superuser 上的这个案例,在这种情况下,仅仅做一个 dnat 是不够的,还需要再做一次 snat 这样才能在回包的时候走正确的路由。
以他为例,在 client 把包发给 PC1 后,首先经过下面这条规则:
# iptables -t nat -A PREROUTING -p tcp -m tcp -d 1.0.0.1 –dport 80 -j DNAT  –to-destination 172.16.0.3:80

于是该包的 src(假设为 192.168.1.1:22222) 不变,dst 由 1.0.0.1:80 变成了 172.16.0.3:80,紧接着,经过 POSTROUTING:
# iptables -t nat -A POSTROUTING -p tcp -m tcp -d 172.16.0.3 –dport 80 -j SNAT –to-source 172.16.0.1:22222

于是该包的 src 由 192.168.1.1:22222 变成了 172.16.0.1:22222,这样修改后的包变成了 src 172.16.0.1:22222,dst 172.16.0.3:80,通过这种方式,成功的绕过了 PC3 default gateway 的问题。
如果仅仅包含 PREROUTING 这条 rule,那么包就变成了 src 192.168.1.1:2222,dst 172.16.0.3:80,虽然包能抵达 PC3,但是在返回的时候,PC1 发现原来的 (192.168.1.1:2222 <-> 1.0.0.1:80) 变成了 (192.168.1.1:2222 <-> 172.16.0.3:80),就直接发 R(Unskilled Attackers Pester Real Security Folks)标志了。可以看看我下面这个模拟的抓包结果:
16:06:36.694253 IP 192.168.1.1:2222 > 172.16.0.3.80: Flags [SEW], seq 868362120, win 5840, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
16:06:36.694279 IP 172.16.0.3.80 > 192.168.1.1:2222: Flags [S.E], seq 1535533077, ack 868362121, win 5840, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
16:06:36.694591 IP 192.168.1.1:2222 > 172.16.0.3.80: Flags [R], seq 868362121, win 0, length 0

所以,记住,如果是这种非网关的形式,务必要 PREROUTING 跟 POSTROUTING 同时做。

理解了上面的问题,再说下我们线上的问题。当时脑子昏了随便找了台开启了 ip_forward 的服务器充当这台 NAT 设备,并且我只开启了 PREROUTING,结果可想而是,没法建立 TCP 链接,搞清楚了问题之后就找了台网关的机器,同时配备了内外网,从外界的客户端通过这个公网 IP 访问内部的机器就很简单了。同样的还是分两种情况,如果要访问的内部机器的 GW 指向这台 nat 设备,很简单,直接 PREROUING,如果没有指向,那么记得再添加一个 POSTROUTING:
# iptables -t nat -A PREROUTING -d nat_public_ip -j DNAT –to-destination  dst_server_ip
# iptables -t nat -A POSTROUTING -d dst_server_ip -j SNAT –to-source nat_private_ip

ref:

http://blog.peter-b.org/2011/08/01/using-iptables-to-map-an-internal-address-to-an-external-one/