容器的网络是有network namespace的,也就是相互隔离的。

那么在容器网络初始化,也就是network namespace初始化的时候,网络相关的参数是如何设置的呢?

答案是一部分继承host namespace,另一部分重新初始化。在函数tcp_sk_init() 里,tcp_keepalive 的三个参数都是重新初始化的,而 tcp_congestion_control 的值是从 Host Namespace 里复制过来的。

为了安全,容器mount的时候,会对/proc/sys目录做只读处理,这样就无法在启动容器之后修改/proc/sys/net下的网络参数了。因此需要在只读挂载之前就处理好网络参数

而 Docker 的–sysctl或者 Kubernetes 里的allowed-unsafe-sysctls特性允许容器在启动时修改容器 Namespace 里的参数。

# 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

总结一下就是,在宿主机上修改的网络参数,可能容器在初始化network namespace时候会重新赋值导致无法生效。而修改容器网络需要使用docker的-sysctl或者k8s的allowed-unsafe-sysctls特性。