问题Kubernetes集群下运行的容器的内核参数是默认的,但是对于某些类型的应用,比如NginxIngresscontroller,默认的内核参数配置是不够的。需要进行调整。例如,somaxconn限制用于接收新TCP连接的侦听队列的大小。它的默认值是128,但是对于反向代理服务器来说,这个配置太小了。那么我们很自然地想到,我们需要调整应用容器的内核配置参数。解决方案DockerDaemon的处理方式是针对Docker引擎的,但是使用--sysctl运行参数设置需要更改的内核参数,例如:dockerrun-it--sysctlnet.core.somaxconn=65535busybox#检查是否在容器中配置成功:cat/proc/sys/net/core/somaxconn然后我们可以查看容器的详细信息:可以看到Docker引擎已经配置了容器,没有使用特权模式设置Kubernetes处理前的内核参数在Kubernetes中,Kubernetes可以使用Docker引擎的--sysctl能力,或者特权init容器方法。目前sysctls的能力还处于alpha阶段,选择时需要注意。KubernetesSysctls的详细介绍可以参考:在Kubernetes集群中使用Sysctls实际过程如下:kubelet启动参数需要配置对应的开关--experimental-allowed-unsafe-sysctls。比如在阿里云的kubernetes服务中,可以在node节点上修改/etc/systemd/system/kubelet.service.d/10-kubeadm.conf,添加相应的配置并reloadsystemctldaemon-reload,然后重启kubelet.net相关的内核参数允许配置如下:Kubernetes允许配置的内核参数如下:kernel.shm*,kernel.msg*,kernel.sem,fs.mqueue.*,net.*.启动Pod时,设置相应的注解,声明需要修改的内核参数,并启动一个nginx作为测试示例:apiVersion:v1kind:Podmetadata:name:test-sysctlannotations:security.alpha.kubernetes.io/unsafe-sysctls:net.core.somaxconn=65535spec:containers:-image:nginxname:nginxports:-containerPort:80protocol:TCPnodeSelector:kubernetes.io/hostname:cn-shenzhen.i-xxxxx注意:对于需要换内核的应用参数,建议部署到特定机器。为方便起见,我使用节点选择器。如果对应机器的kubelet没有打开对应的开关,则pod部署不成功。我们可以通过kubectlgetevent查看对应的日志:那么这个方法背后的原理是什么呢?其实就是docker的--sysctl,我们可以pod到对应的node节点去dockerinspect看看。但是奇怪的是,dockerinspect看不到任何sysctl的迹象,是不是哪里出了问题?其实不是,因为sysctl真正的实现是kubernetes的pause容器,也叫infra容器。我们找到对应的容器,然后dockerinspect查看:这时候我们发现pause容器配置了sysctls。KubernetesInitContainerInit容器的使用可以参考:InitContainers使用init容器的好处是不需要更改kubelet的配置,但是init容器需要配置特权权限。下面是启动Pod的例子:apiVersion:v1kind:Podmetadata:name:test-sysctl-initnamespace:defaultspec:containers:-image:nginximagePullPolicy:Alwaysname:nginxports:-containerPort:80protocol:TCPinitContainers:-image:busyboxcommand:-sh--c-echo10000>/proc/sys/net/core/somaxconnimagePullPolicy:Alwaysname:setsysctlsecurityContext:privileged:true至于使用哪种方式,可以自己选择。后续还要关注kubernetesforsysctls的演进。【本文为专栏作者“VIPDOCKER-Leoge”原创文章,如需转载请通过联系作者】点击此处查看该作者更多好文
