在宿主机修改的网络参数为何在容器不生效
- 大部分网络参数都在/proc/sys/net/目录中。
修改这些参数主要有两种方法:一种方法是直接到/proc/sys/net/目录里对参数做修改;还有一种方法是使用sysctl这个工具来修改。- Network Namespace 隔离的资源:每个 Namespace 独立的
- 网络设备:ip link 查看
- IPv4 和 IPv6 协议栈
- IP 路由表:ip route 查看
- 防火墙规则
- 网络的状态信息:可以从 /proc/net 和 /sys/class/net 里得到(即前4种资源的状态信息)
- 可以通过系统调用 clone() 或者 unshare() 这两个函数来建立新的 Network Namespace
宿主机运行 lsns -t net 查看namespaces
- A:由于安全的原因,普通容器的 /proc/sys 是 read-only mount 的,所以在容器启动以后,我们无法在容器内部修改 /proc/sys/net 下网络相关的参数。
修改方法:
Docker 的--
sysctl或者 Kubernetes 里的allowed-unsafe-sysctls特性都利用了 runC 的 sysctl 参数修改接口,允许容器在启动时修改容器 Namespace 里的参数。
饭粒1:修改docker容器网络参数
饭粒2:使用nsenter修改容器网络参数# docker run -d --name net_para --sysctl net.ipv4.tcp_keepalive_time=600 centos:8.1.1911 sleep 3600 7efed88a44d64400ff5a6d38fdcc73f2a74a7bdc3dbc7161060f2f7d0be170d1 # docker exec net_para cat /proc/sys/net/ipv4/tcp_keepalive_time 600
nsenter -t <pid> -n bash -c 'echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time'
其中pid表示容器init进程在宿主机的PID - network namespace 工具包
- Q:容器网络接口对容器中应用程序网络延时怎么办?
- 容器通常缺省使用 veth 虚拟网络接口,不过 veth 接口会有比较大的网络延时。我们可以使用 netperf 这个工具来比较网络延时,相比物理机上的网络延时,使用 veth 接口容器的网络延时会增加超过 10%。
因为veth 接口是成对工作(下图),在对外发送数据的时候,peer veth 接口都会 raise softirq 来完成一次收包操作,这样就会带来数据包处理的额外开销。
- A:要减小容器网络延时,就可以给容器配置 ipvlan/macvlan 的网络接口来替代 veth 网络接口。
Ipvlan/macvlan 直接在物理网络接口上虚拟出接口,在发送对外数据包的时候可以直接通过物理接口完成,没有节点内部类似 veth 的那种 softirq 的开销。容器使用 ipvlan/maclan 的网络接口,它的网络延时可以非常接近物理网络接口的延时。
- 但是由于 ipvlan/macvlan 网络接口直接挂载在物理网络接口上,对于需要使用 iptables 规则的容器,比如 Kubernetes 里使用 service 的容器,就不能工作了。
- Q:如何处理容器中网络包乱序引起重传的问题?
- 快速重传:如果发送端收到 3 个重复的 ACK,那么发送端就可以立刻重新发送 ACK 对应的下一个数据包,而不用等待发送超时。
- RPS 和 RSS 的作用类似,都是把数据包分散到更多的 CPU 上进行处理,使得系统有更强的网络包处理能力。它们的区别是 RSS 工作在网卡的硬件层,而 RPS 工作在 Linux 内核的软件层。
- A:在把数据包分散到各个 CPU 时,RPS 保证了同一个数据流是在一个 CPU 上的,这样就可以有效减少包的乱序。那么我们可以把 RPS 的这个特性配置到 veth 网络接口上,来减少数据包乱序的几率。
RPS 的配置还是会带来额外的系统开销,在某些网络环境中会引起 softirq CPU 使用率的增大。可按需配置。
想要减少网络数据包的重传,我们还可以考虑协议栈中其他参数的设置,比如 /proc/sys/net/ipv4/tcp_reordering。