給Kubernetes集群下的容器配置內(nèi)核參數(shù)
問題
在Kubernetes集群下運(yùn)行的容器的內(nèi)核參數(shù)是默認(rèn)的,但是對于某型類型的應(yīng)用如Nginx Ingress controller而言,默認(rèn)的內(nèi)核參數(shù)配置是不夠的,需要做出調(diào)整,例如somaxconn是限制了接收新TCP 連接偵聽隊(duì)列的大小,它的默認(rèn)值是128,但是對于反向代理的服務(wù)器而言,這個(gè)配置實(shí)在是太小了。那么我們自然想到需要去調(diào)整這個(gè)應(yīng)用的容器的內(nèi)核配置參數(shù)。
解決之道
Docker Daemon的處理方式
對于Docker引擎而言,可是使用--sysctl運(yùn)行參數(shù)來設(shè)定需要更改的內(nèi)核參數(shù),例如:
- docker run -it --sysctl net.core.somaxconn=65535 busybox
- #在容器看看是否配置成功:
- cat /proc/sys/net/core/somaxconn
然后我們可以看看容器的詳情:
可以看到,Docker引擎對容器進(jìn)行了相關(guān)的配置,而無需使用特權(quán)模式來設(shè)置內(nèi)核參數(shù)
Kubernetes的處理之道
在Kubernetes里,Kubernetes可以利用Docker引擎的這個(gè)--sysctl的能力,也可以利用privilege init container的方式。目前sysctls的能力還依然在alpha階段,選擇時(shí)需要注意。
Kubernetes Sysctls
具體可以參考:Using Sysctls in a Kubernetes Cluster
實(shí)踐過程如下:
- 需要在kubelet啟動參數(shù)上配置對應(yīng)的開關(guān)--experimental-allowed-unsafe-sysctls。例如在阿里云的kubernetes服務(wù),可以在node節(jié)點(diǎn),修改/etc/systemd/system/kubelet.service.d/10-kubeadm.conf,增加對應(yīng)的配置并重新加載systemctl daemon-reload,然后重啟kubelet。如下是允許配置和net相關(guān)的內(nèi)核參數(shù):
Kubernetes允許配置的內(nèi)核參數(shù)如下:
- kernel.shm*,
- kernel.msg*,
- kernel.sem,
- fs.mqueue.*,
- net.*.
- 啟動Pod的時(shí)候設(shè)置對應(yīng)的annotation,申明需要修改的內(nèi)核參數(shù),以啟動一個(gè)nginx為測試?yán)?
- apiVersion: v1
- kind: Pod
- metadata:
- name: test-sysctl
- annotations:
- security.alpha.kubernetes.io/unsafe-sysctls: net.core.somaxconn=65535
- spec:
- containers:
- - image: nginx
- name: nginx
- ports:
- - containerPort: 80
- protocol: TCP
- nodeSelector:
- kubernetes.io/hostname: cn-shenzhen.i-xxxxx
注意:對于需要變更內(nèi)核參數(shù)的應(yīng)用,建議部署到特定的機(jī)器上。為了方便,我是使用了node selector。
如果對應(yīng)的機(jī)器的kubelet沒有打開這個(gè)對應(yīng)的開關(guān),那么pod是部署不成功的。我們可以通過kubectl get event來看看對應(yīng)的日志:
那么這個(gè)方式背后的原理是什么呢?其實(shí)就是docker的--sysctl,我們可以pod到對應(yīng)的node接點(diǎn)去docker inspect看看。但是奇怪的是,docker inspect看不到任何sysctl的跡象,是不是那里有誤?
其實(shí)不是的,因?yàn)檎嬲龍?zhí)行sysctl是kubernetes的pause container也叫做infra container,我們找到對應(yīng)的這個(gè)容器,再docker inspect看看:
這個(gè)時(shí)候,我們發(fā)現(xiàn),這個(gè)pause容器配置了sysctls。
Kubernetes Init Container
Init container的用法可以參考:Init Containers
使用init container的好處是,無需去改變kubelet的配置,但是需要給這個(gè)init container配置成privilege的權(quán)限。
以下是一個(gè)啟動Pod的例子:
- apiVersion: v1
- kind: Pod
- metadata:
- name: test-sysctl-init
- namespace: default
- spec:
- containers:
- - image: nginx
- imagePullPolicy: Always
- name: nginx
- ports:
- - containerPort: 80
- protocol: TCP
- initContainers:
- - image: busybox
- command:
- - sh
- - -c
- - echo 10000 > /proc/sys/net/core/somaxconn
- imagePullPolicy: Always
- name: setsysctl
- securityContext:
- privileged: true
至于使用那種方式,可以自行選擇。后續(xù)也要留意kubernetes對于sysctls的演進(jìn)。
【本文是51CTO專欄作者“VIPDOCKER-了哥 ”的原創(chuàng)文章,如需轉(zhuǎn)載請通過51CTO與作者聯(lián)系】