OpenVPN Connectivity Issue in Public Network

We established a ovpn tunnel between 2 IDCs in September 2014, and we have monitored the availability and performance of two ends for a long time. The geographical distance between 2 IDCs are quite short, but with different telecom carries. mtr shows that there exits ahout 7 hops from one end to the other. The below screenshot shows the standard ping loss.


The result is quite interesting. At first we used UDP protocol, and we often experienced network disconnection issue, later we switched to TCP, and it improved a lot. From the digram, the average package is 1.11%.
Why 1.11%, what I can explain is the tunnel is often fully saturated during the peak hour, and this can't solved at the moment, so no matter what protocol, the package loss should exists. Another possible reason is the complexity of public network which I can't quantitate.
The current plan works during current background, but no "how many 9s" guarantee. Anyway, if we want to achieve more stable connectivity, a DLL(dedicated leased line) is a better choice.

Router Matters

We are transfering PBs of our HDFS data from one data center to another via a router, we never thought the performance of a router will becomes the bottleneck until we find the below statistic:

#show interfaces Gi0/1
GigabitEthernet0/1 is up, line protocol is up
  Hardware is iGbE, address is 7c0e.cece.dc01 (bia 7c0e.cece.dc01)
  Description: Connect-Shanghai-MSTP
  Internet address is 10.143.67.18/30
  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
     reliability 255/255, txload 250/255, rxload 3/255
  Encapsulation ARPA, loopback not set
  Keepalive set (10 sec)
  Full Duplex, 1Gbps, media type is ZX
  output flow-control is unsupported, input flow-control is unsupported
  ARP type: ARPA, ARP Timeout 04:00:00
  Last input 00:00:06, output 00:00:00, output hang never
  Last clearing of "show interface" counters 1d22h
  Input queue: 0/75/0/6 (size/max/drops/flushes); Total output drops: 22559915
  Queueing strategy: fifo
  Output queue: 39/40 (size/max)

The output queue is full, hence the txload is obviously high.

How awful it is. At the beginning, we found there were many failures or retransmissions during the transfer between two data centers. After adding some metrics, everything is clear, the latency between two data centers is quite unstable, sometimes around 30ms, and sometimes reaches 100ms or even more which is unacceptable for some latency sensitive application. we then ssh into the router and found the above result.

After that, we drop it and replace it with a more advanced one, now, everything returns to normal, latency is around 30ms, packet drop is below 1%.

通过 tcpcopy(pf_ring) 对 BCM 5719 小包做的多组 benchmark

tcpcopy 在文档化、用户参与方式方面有很大的提升空间这个问题在之前已经专门说过。最终,在我们自己阅读代码的情况下,结合 pf_ring,坚持跑通了整个流程,用其对目前 BCM 5719 型号的网卡做了多组对比,结论见结尾。
使用 tcpcopy 做 benchmark,务必确定 tcpcopy 语法使用的正确性, 尽管互联网上绝大多数的文档以及官方文档都写的含糊不清。
比如,我们之前把过滤条件 -F "tcp and dst port 80" 写成了 -F "tcp and src port 80",造成的结果是在错误的基础上得出了一些奇葩的数据以及无法解释的现象,比如到 target server 的流量特别小,并且及其的不稳定,得到的 pps 也是非常的不稳定大到 400kpps/s,小到 20k  甚至 0。

这里列举我们测试环境使用的一组配置。
所有机器都是 RedHat 6.2 2.6.32-279.el6.x86_64,Tcpcopy 1.0 版本,PF_RING 6.0.1,BCM 5719,双网卡 bonding。另外,我们单台生产机器的流量都比较大,并且绝大多数都是 100B 以下的小包,所以对系统的要求还是比较高的。
为了避免后续的误解,先确定几个用语:
1. online server(OS): 即我们线上生产环境的机器
2. target server(TS): 是我们想做 benchmark 的那台机器,以测试其究竟能支撑多大的量
3. assistant server(AS): 是安装了 intercept 的机器
4. mirror server(MS): 通过 tcpcopy 的 mirror 工具把 OS 的流量复制到该台机器上

我们一共做了三大组 benchmark,每组下面包含若干小的 benchmark,包括:
1. tcpcopy + intercept
2. tcpcopy + intercept + tcpcopy mirror,加一个 mirror 是为了减少对 OS 的负载,这样 tcpcopy 在 MS 上运行
3. tcpcopy + intercept + 交换机 mirror,更直接的方式复制线上流量,保证对 OS 没有干扰,并且能保证 100% 全量复制 OS 的流量

Continue reading

10G 网络升级(经验教训总结)

前年兼职搞的时候规模还没这么大,整个步骤也很顺利,基本做的就是些插拔网线的操作。这次规模较前年比,已经是翻了几番(30 组机架),不可能再由一人带一实习生这种套路来完成。增加人手首当其冲,所幸,这次升级的人手还是比较充裕的,我们这边包括我在内一个网络工程师,两个运维;我们的服务供应商驻守了两位网络工程师以及若干的布线人员;我们的托管商将驻场的值班工程师由原先的 1 位临时增加到了 5 位。

升级最终的结果当然是成功的,但是中间的过程确是崎岖无比,原本计划从 2 月 18 日 10:00pm 到 19 日 4:00am 6h 的 scheduled downtime 由于遇到了种种事先没有预想到的问被迫被延期到了 20 日的凌晨 3:00am,中间经历了难熬的 30h。

下面先写些"八卦"。
第一天晚上最大的失败就是在升级网络的时候连同服务器也一起带着升级了,其实这是两件事,完全可以独立开来做。最终导致内网任何一点之间的丢包高达 50%,处于完全瘫痪的状态。从拔第一跟网线的 11:00 pm 开始到最后一根网线插上,已经到了 19 日的 7:00am 多,在现场 debug 了 2h 多小时,基本确定是网卡 mode 的问题。
回去休息,感觉基本是锁定了问题所在,起床后在高度兴奋的状态下扫了若干的文档,有九成以上的把握是 bonding mode 的问题。
晚上吃完饭买完能量补给,跟我们的工程师再次亲临现场,花了一个多小时的时间,拿一组整机柜做了实验,100% 确认了是 bonding mode 造成的问题。接下来一直到 3:00am 的这段时间就是一人操作一人配合改完了所有服务器的 bonding mode 以及测试确认,现场还出现了一些人为操作的失误,多花了些时间去排查,如果细心点应该 2 点左右就能结束。
至此,整体框架已经升级完毕,剩下的一些诸如服务器无法启动、路由不通等问题这是后话。

下面逐条总结这次升级终于到的问题以及改进措施,我相信我说的这些绝大多数成长中的公司都应该会遇到,不管是基础网络、系统、上层服务以及面向客户的业务层面。
1. 太过于相信我们的服务供应商的工程师(暂且以 S 表示这个群体)或者说其他人的经验
之前得知 S 处理的项目的经验不少,基本北京这边几个巨头都是他们的客户。最初咨询他们建议使用哪种 bonding mode 时,心安理得没有任何思考以及查证的情况下就相信了他们说的话。而这最终的结论是从哪里来的了?根据 S 的陈述,他们其实也不大了解,转而咨询 A 公司(收购我们的那家)的驻场工程师。当时非常幼稚脑子烧掉的认为这么大的公司都按照这套路来,我们肯定也没问题了。于是我们就是照猫画虎,没理解里面的细节,连 A 那边最基本的环境都不了解,就屁颠屁颠的用上去了,结果可想而知。
不要迷信厂商,厂商里面很少有技术过硬强烈责任感的工程师,大部分的都是油腔滑调满嘴跑火车(Redhat 除外)。我们这次如此不顺利的升级也是过分的听信了厂商的满嘴跑火车。所以,不管什么时候,首先阅读官方文档,这上面的绝大多数内容都是正确的,再配合实际操作。

Continue reading

10G 网络升级(服务器端 bonding)

本次升级最大的"意外"之一就是关于服务器 bonding 的问题,归根到底还是在升级之前文档看的不够充分,调研的不够仔细。下面会对其做一个比较全面的分析。
说到 bonding,最重要的问题之一就是模式的选择,这个是要根据各自不同业务来选择的,切勿人云亦云,我整理了一份表格,说明每一种模式的一些特性以及交换机对其的支持情况。

选哪个模式最合适?很明显,正常情况下,mode4 是一个比较好的选择,但是需要注意的是端对端尤其是交换机 active/on 选择,对于服务器来说,稍微有点繁杂,需要根据网口的情况来分:

  • 四口的,如果有内外网,没有问题
  • 两口的,如果仅仅有内网或者公网,也没有问题
  • 两口的,如果既要有内网又要有公网,很明显,还缺少两个端口,这时候在 Linux 上做 VLAN  的价值就体现出来了

确认完模式,接下来就是 bonding 的安装,bonding 这个 module 默认应该都是随发型版本加载的,可以在 /etc/modprobe.d/ 目录下面加载;接下来就是修改网卡对应的配置了,各个不同的发型版本大同小异,这里分别给一个 Ubuntu 以及 RHEL 的范例。这两个主流发型版本的 bonding 的配置还是比较灵活的,除了可以在 /etc/modprobe.d/ 里面指定 bonding 的各种参数之外,还可以在 network-scripts/ 以及 interface 里面指定,比如可以在 ifcfg-bond0 里面指定 bonding opts:
# cat /etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE=bond0

BONDING_OPTS="mode=4 miimon=100"

跟 bonding 有关的几个实时文件分别在 /proc/net/bonding/:
# cat /proc/net/bonding/bond0

以及 /sys/class/net/ 下面:
# cat /sys/class/net/bonding_masters
bond0

# cat /sys/class/net/bond0/bonding/mode
balance-alb 6

# cat /sys/class/net/bond0/address
99:11:11:11:dd:dd

要让 bonding 生效,我认为最 KISS 的办法还是直接重启机器,尽管可以通过 ifenslave 或者在加载完 bonding 之后直接在 /sys/(/sys/class/net/ 下面) 里面 "on the fly"。官方的建议是通过 iproute2(ip link set eth0 master bond0) 或者 sysfs 修改生效,ifenslave 会被逐渐抛弃。
在启动的时候,注意查看系统的 /var/log/messages,这个文件里面能看到很多跟 bonding 相关的信息。

对于 bonding 一对或者多对网卡的监控,可以二选一:
1. miimon
2. arp_interval 以及 arp_ip_target
不用任何监控的弊端之一就是一个网卡挂了无法及时的切换到另外一块网卡上,这个明显是不容许的。
对于 ARP 的监控方式,一般用在兼容 etherchannel 的模式里面,也就是交换机会将流量分散到多条链路上;如果是以 XOR 的方式(单条链路)则不可行。除此之外,ARP 的方式不可以跟 miimon 同时使用。
对于 miimon 来说,有 downdelay, updelay, user_carrier 几个参数比较重要。
如果想使用 balance-xor 或者 802.3ad,还需要了解下 xmit_hash_policy 以便更好的平衡流量。

既然是端到端的系统,除了要考虑服务器方面的 bonding 状态,也要考虑对端 FEX 的支持情况,在上篇已经说过,主流的 2k 跟 5k 的接法无外乎 single-homed 也就是一台 2k 仅连接一台 5k 或者是 dual-homed 也就是一台 2k 同时连接两台 5k。其中前者的 topo 支持 2k 的到服务器的 vPC、FCOE 以及 static pinning,而后者是不可以对 2k 下挂的服务器做 vPC,单凭这一点就没什么优势了,更何况这种接法还有其他不少的缺点。

这里有一篇文章提到遇到 Orphan Port 也就是单上联的情况,这个在实际情况中还时有发生,尤其是比较早期的服务器,那时候网口的数量还不足以达到双上联的标准,对于这类情况,文中分析在 peer link 参与的情况下流量的分布以及需要注意的地方,值得看看。

还有几个需要注意的地方:
1. 路由问题,原先由 eth0 单块网卡处理的现在将由 bond0 接替处理,如果是通过 ifensalve、modprobe 等方式启动的 bonding,注意也要修改对应的路由,重启不存在这类问题。
2. SNMP 问题,需要确保 bonding  这个模块在其他的网络模块之前加载,否则 SNMP 取得的数据会有错乱。
3. 在混杂(promiscuous) 模式下,balance-rr, balance-xor, broadcast 以及 802ad 这四种模式会将混杂模式的设定会传播到所有的 slave 接口;而 active-backup, balance-tlb 以及 balance-alb 这三种则只会传播到 active 的 slave 接口。
4. duplicated 包的问题,最常见的是在初次或者闲置一段时间之后 ping 某台机器的过程中发现不少 (DUP!) 表示的包,正常现象,主要在于交换机广播的机制,最简单的方式是清空一次 MAC 转发表,Nexus 上的示例:
# clear mac address-table dynamic


update: 服务器端的注意 xmit_hash_policy 这个参数,默认值为 layer2,也就是 mac 层的 hash,在某些业务下,会出现带宽跑不满,上不去的情况,可以考虑使用 xmit_has_policy=1(layer3+4) 的组合,这个还是要根据具体的业务来定。