Linux 网络相关
Table of Contents
1 Debian 网络配置的基本写法
/etc/network/interfaces 文件存储了网络相关的配置,两个接口的配置必须用空行隔开。
更全面的配置信息可以查看 man interfaces ,这里只给例子。
1.1 静态 IP
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface # eno1 is the interface name auto eno1 iface eno1 inet static address 192.168.1.110/24 gateway 192.168.1.3 # dns-* options are implemented by the resolvconf package, if installed dns-nameservers 192.168.1.6 dns-search debian.local
1.2 从 DHCP server 获取 IP
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface # eno1 is the interface name auto eno1 iface eno1 inet dhcp
2 链路聚合
2.1 链路聚合前置概念
IEEE 802.3ad 标准定义了 Static LAGs 和 LACP 两种链路聚合方式。但是,标准早期只定义了 Static LAGs,后来才更新了 LACP 相关的内容。
要注意,Static LAGs 和 LACP 都符合 802.3ad 标准。它们的区别在于,Static LAGs 只符合了 802.3ad 标准;LACP 除了符合标准外,还用了 802.3ad 中 LACP 这个协议 (会产生额外的,用于协议协商的数据包)。
Static LAGs 是静态聚合,群晖管 Static LAGs 叫 IEEE 802.3ad draft v1 ,有些地方也管它叫手工聚合,TP-Link 管它叫静态端口汇聚。LACP 是动态聚合,没有其他奇怪的叫法。
LACP 也分 Static LACP 和 Dynamic LACP,要注意把 Static LACP (符合 802.3ad 标准并使用 LACP 协议) 和 Static LAGs (只符合 802.3ad 标准) 区分开,不做更多展开。
在使用链路聚合的端口组中,主机或交换机通过对数据包头中的信息计算 hash 值来为流量选择流出端口 (hash 算法可以指定)。需要注意,主机与交换机的 hash 算法需要分别配置,主机与交换机使用的 hash 算法可以不同,但最好相同。
2.2 链路聚合中的负载均衡算法
Linux 系统中的 xmit_hash_policy
(cat /sys/class/net/<bond-name>/bonding/xmit_hash_policy
) 指定了 hash 算法,对于一台连接到交换机的 Linux 主机来说,算法的可选值及其效果为:
layer2 (0)
将到达同一 MAC 地址的流量分配到同一个网络接口上。- 如果流量的目标 MAC 地址与源 MAC 地址在同一个广播域中,这个算法效果很好。
- 广播域中的设备 (目标 MAC 地址) 越多,负载均衡效果越好。
- 如果所有流量到达目的地前都要先过一层网关,那么这个算法会导致只有一条链路有流量。
layer3+4 (1)
将到达同一 ip:port 地址的流量分配到同一个网络接口上。对于非 IP 流量,使用 layer2 算法。- 该算法不兼容 802.3ad 标准。如果本机被聚合的端口有 n 个,那么这个算法可以让本机到同一目标 IP 的不同端口的 n 个 TCP 链接的出向流量分布在这 n 个端口上 (每个 TCP 链接的流量只从一个端口流出),并且可以让这 n 个链接占满本机的所有出向带宽。但如果每个主机之间的 TCP 链接不够多,反而同一网络中的 IP 地址很多,那么 layer2+3 算法的负载均衡效果更好。
layer2+3 (2)
将到达同一 (mac,ip) 地址的流量分配到同一个网络接口上。对于非 IP 流量,使用 layer2 算法。- 同一网络中的 IP 地址越多,该算法的负载均衡效果越好。
- 如果所有流量到达目的地前首先要过一层网关,这个算法可以避免 layer2 算法导致的只有一条链路有流量的问题。
encap2+3 (3)
与layer2+3
使用相同算法,但它依赖于 skb_flow_dissect 来获取数据包头的字段。encap3+4 (4)
它与layer3+4
使用相同算法,但它依赖于 skb_flow_dissect 来获取数据包头的字段。
需要注意的是,上面的内容只提及连接到交换机的设备的 bond 接口的出向流量的负载均衡策略,即,从 bond 接口流出的流量会均匀分布在 bond 接口中的每个物理接口上。想要让 bond 接口的入向流量也做到负载均衡还需要交换机上的 hash 策略的配合,让交换机做好交换机的出向流量的负载均衡,这就是前文提到 主机与交换机的 hash 算法可以不同,但最好相同 的原因。
交换机做好出向流量的负载均衡,就会使得流出交换机的数据被均匀分布在被聚合的端口间,连接到这些端口的设备也能在其自身的 bond 接口上收到被负载均衡过的流量,即,bond 接口所包含的物理接口收到的流量也是均匀分布的。
设备对出向流量做好负载均衡,交换机也对出向流量做好负载均衡,就可以让设备的双向流量都做到负载均衡。下面给个例子
环境:
- Linux 主机 A 作为交换机,在其上创建一个 vbridge 和两个 bond
- bond0 对应 a1, a2 两个接口
- bond1 对应 a3, a4 两个接口
- bond0, bond1 被连接到这个 bridge 上
- Linux 主机 B 上的 Bond 接口叫做 bond_b
- bond_b 包含主机 B 上 b1, b2 两个接口
- bond_b 连接到主机 A 上的 bond0
- Linux 主机 C 上的 Bond 接口叫做 bond_c
- bond_c 包含主机 C 上 c1, c2 两个接口
- bond_c 连接到主机 A 上的 bond1
- 主机 B 要和主机 C 通信
- 所有 Bond 接口使用 balance-xor 模式
hash 算法的不当配置:
- 交换机 A 上 bond0, bond1 使用的 hash 算法为 layer2
- 主机 B 和主机 C 上的 Bond 接口使用的 hash 算法为 layer3+4
- 主机 B 上的程序使用 2 个 TCP 连接与主机 C 通信
现在 B 给 C 发数据,可以观察到:
- bond_b 所属的两个物理端口的出向流量相等,负载均衡生效,
- bond_b 出向流量的总带宽相当于 bond_c 中一个物理接口的入向带宽
- bond_c 所属的两个物理端口上只能观察到一个端口承担了所有入向流量,另一个端口几乎没有流量
原因出在交换机上: 与 bond_c 连接的 bond1 使用的 layer2 算法把流向同一 MAC 地址 (即 bond_c 的 MAC 地址) 的流量分配到了同一条链路上,所以 bond1 所属的两个物理接口中只有一个接口有出向流量,所以 bond_c 所属的两个物理接口中也就只有一个接口有入向流量了。
要纠正这个问题,只需要把 bond1 的 hash 算法改成 layer3+4 即可。使用 layer3+4 算法的 bond1 会把流向不同 ip:port 地址的流量分布在不同的端口上。在本例中有 2 个 TCP 连接,会使用 2 个端口,对应 2 条链路。bond1 的每条物理链路负责一个连接的出向流量,所以 bond_c 的每条链路都能接收到一个入向流量的连接。然后就可以观察到 bond_c 所属的两个物理接口都有入向流量,且入向流量带宽接近,并且 bond_b 可以跑满出向带宽,bond_c 也可以跑满入向带宽。
但是这还没完,上面的方案只解决了数据从 B 流向 C 的问题。果数据是从 C 流向 B 的,那么还会再在 bond_b 上观察到和 bond_c 一样的现象,即,bond_b 所属的两个物理接口中,一个端口承担了所有流量,另一个端口几乎没有流量。
所以,还需要把 bond0 的 hash 算法改成 layer3+4。此时,整个系统中的 hash 算法被统一成了 layer3+4。
2.3 Linux kernel v[4.2, 4.14) 中的 layer+3+4 算法存在问题
Linux kernel v4.2 之前,程序调用 connect() 建立 TCP 连接时,内核会按照使用顺序分配端口号。连接较多时,可能会造成 bind(0) 调用失败。主机端口被扫描时也可能出现性能问题。
Linux kernel v4.2 (2015) 中,为了解决上述问题,Google 的开发人员修改了端口分配逻辑 (commit 07f4c90)。程序调用 connect() 建立 TCP 连接时,内核偏向于为程序分配一个偶数数字的端口号。但这个改动影响了链路聚合中所有涉及 layer4 (src-dest-port) 的算法: 程序被分配的端口号有了特征 。即,增加了端口号的二进制值的末位为 0 的概率。
本应被分配在两个链路上的两个连接被分配在了同一个链路上的情况出现的概率变大了
Linux kernel v4.14 (2017) 中,为了解决偶数端口号产生的问题,Linux kernel 的开发人员修改了链路聚合的 hash 算法 (commit b5f8621): 抛弃计算结果的最后一位。
其基本思路是,抛弃计算结果中受特征影响的部分。端口号的特征是二进制值末位为 0 的概率变大,其特征在二进制值最后一位上。根据 layer3+4 hash 算法的逻辑,在 hash 运算的结果中,端口号的特征也被保留在了二进制值的最后一位上。
所以,只要抛弃计算结果中保留了端口号特征的最后一位,就可以使计算结果恢复到不带特征的状态,从而让连接尽量均匀地分布在所有链路上。
3 bond 网络接口
执行 sudo apt install ifenslave
安装 bond 功能包。
bond 是 Linux 上实现了链路聚合的驱动程序,可以让多个网络接口被组合成一个虚拟的网络接口。
bond 提供了七种工作模式,在使用的时候需要指定一种:
工作模式 | 简写 | 需要交换机支持 | 容错 | 负载均衡 | 简略描述 |
---|---|---|---|---|---|
balance-rr 默认 | mode=0 | Y | Y | Y | 各网口轮流发包,吞吐量均衡。 |
active-backup | mode=1 | Y | 仅一个接口在工作,故障时切换到另一个接口。 | ||
balance-xor | mode=2 | Y | Y | Y | 根据算法选择数据包流出端口。 |
broadcast | mode=3 | Y | 每个接口都要发送每个要发出的数据包。 | ||
802.3ad | mode=4 | Y | Y | Y | IEEE 802.3ad 动态链路聚合。 |
balance-tlb | mode=5 | Y | Y | 用 ARP 协商实现发包负载均衡,但只有一个接口收包。 | |
balance-alb | mode=6 | Y | Y | 基于 balance-tlb,再用 ARP 协商实现收包负载均衡。 |
在需要链路聚合时,高端交换机常用 4 模式;中低端交换机常用 0 2 模式;傻瓜交换机常用 6 模式。下面是详细说明。
3.1 balance-rr
特点: 传输数据包顺序是依次传输。比如,第 1 个包走 eth0,第 2 个包走 eth1,第 n 个包走 eth<n-1>,第 n+1 个包走 ethn… 如此排列循环。需要在交换机上配置静态聚合。
效果: 支持负载均衡,容错。
缺点: 如果一个连接的数据包从不同的接口发出,中途再经过不同的链路到客户端,有可能出现数据包无序到达的问题。如果数据包无序地到达目标机器,目标机器会要求服务器重发数据包,从而导致网络吞吐量降低,负载均衡效果也受影响。
3.2 active-backup
特点: 只有一个接口在 active 工作状态,剩下的所有接口在 standby 待机状态。当工作状态的接口不工作,系统将会按顺序选择下一个待机状态的接口作为主接口。所有接口共享一个 MAC 地址。不需要交换机配置。
效果: 支持容错。
缺点: 只有一个接口处于工作状态,资源利用率低。在有 N 个网络接口的情况下,资源利用率为 1/N。
3.3 balance-xor
特点: 基于 xmit_hash_policy
(cat /sys/class/net/<bond-name>/bonding/xmit_hash_policy
) 参数指定的 hash 策略来选择发送数据包的端口。需要在交换机上配置静态聚合。
效果: 多个物理接口合并为一个逻辑接口。保证到达特定对端的流量总是从同一个接口上发出。支持负载均衡,容错。
缺点: 任何连接的速度上限都不能大于一个接口的速度上限。但如果程序支持使用多个连接,配合对应的 hash 算法,那么该程序可以使用的带宽上限为接口带宽*接口数量。本机网络中负载均衡的效果取决于 xmit_hash_policy 所选择的算法,但系统整体的网络性能还与交换机配置的 hash 算法有关。但并不是所有的 hash 策略都兼容 802.3ad 协议。
3.4 broadcast
特点: 在每个网络接口上传输每个数据包。适用于金融等需要有高可靠性的网络的行业。
效果: 所有包从所有网络接口发出。
缺点: 只有提供了冗余机制,浪费资源。
3.5 LACP
特点: 根据 802.3ad 标准中的 LACP 协议将多个网络接口汇聚在一起。需要交换机配置 LACP 聚合。
效果: 支持负载均衡,支持容错。
缺点: 任何连接的速度上限都不能大于一个接口的速度上限。但如果程序支持使用多个连接,配合对应的 hash 算法,那么该程序可以使用的带宽上限为接口带宽*接口数量。本机网络中负载均衡的效果取决于 xmit_hash_policy 所选择的算法,但系统整体的网络性能还与交换机配置的 hash 算法有关。但并不是所有的 hash 策略都兼容 802.3ad 协议。
3.6 balance-tlb
特点: 单向 (发送) 负载均衡。不需要交换机配置。
效果: 单向 (发送) 负载均衡,容错。
缺点: 收包时仅使用一个网卡的 MAC 地址,即,仅有一张网卡用于收包。这种模式适合用在 出向流量巨大而入向流量小 的情况下。如果 server 也要负责大量数据的接收,那么无法充分利用多个接口。
发送负载均衡实现思路: 当服务器要传数据出去给单一一个客户端时,bonding 模块会主动的拦截封包,通过 ARP 协商机制,将不同的网卡要送出到同一个客户端的封包,都改写成单一一个固定的发送端 MAC 地址。
3.7 balance-alb
特点: 在 balance-tlb 基础上,加入针对 IPv4 流量的接收负载均衡 RLB (receive load balance) 策略。不需要交换机配合。接收负载均衡通过 ARP 协商实现。不需要交换机配置
效果: 收发双向负载均衡,容错。
缺点: 在实际使用上 balance-alb 与 balance-rr 的主要区别在于,balance-alb 先把 eth0 流量占满,再占 eth1 … ethX。也就是第一个端口负载很高,后面的接口负载很小。而 balance-rr 所有接口的流量都很稳定,负载基本平衡。
接收负载均衡实现思路: 当有数据封包要送出到多个不同的客户端时,bonding 模块通过 ARP 协商机制,找出 bonding 管理的比较闲置的网卡 MAC 分配给下个客户端。如此,不同的用户端回传给服务器的数据,就可以透过不同的网卡来接收,达到接收流量也负载均衡的功能。
3.8 配置写法
给个例子:
# The loopback network interface auto lo iface lo inet loopback iface eno1 inet manual iface enp4s0 inet manual auto bond0 iface bond0 inet dhcp bond-mode balance-alb bond-slaves eno1 enp4s0 bond-miimon 100
bond-miimon 100
表示系统每 100ms 监测一次链路连接状态,根据链路状态决定是否进行其他操作。比如 active-backup 策略下,如果检测到正在使用的网络接口无法使用导致链路不通,则切换到另一个接口,两次检测间隔 100ms。
4 bridge 网络接口
执行 sudo apt install bridge-utils
安装工具包, man brctl
查看命令行工具的用法。
bridge 把所有的物理网络接口组合在一起,创建了一个虚拟的交换机。bridge 主要是为虚拟机或容器创造通信条件,它有和物理交换机一样的功能。虚拟交换机所在的宿主机也被接在这个虚拟交换机上。
被用来创建 bridge 的网络接口,可以是物理接口,也可以是 bond 接口。
使用物理接口:
# The loopback network interface auto lo iface lo inet loopback iface eno1 inet manual iface enp4s0 inet manual auto br0 iface br0 inet dhcp bridge-ports eno1 enp4s0 bridge-stp off bridge-fd 0
使用 bond 接口:
# The loopback network interface auto lo iface lo inet loopback iface eno1 inet manual iface enp4s0 inet manual auto bond0 iface bond0 inet manual bond-mode balance-alb bond-slaves eno1 enp4s0 bond-miimon 100 auto br0 iface br0 inet dhcp bridge-ports bond0 bridge-stp off bridge-fd 0