給Kubernetes集群下的容器配置內核參數
問題
在Kubernetes集群下運行的容器的內核參數是默認的,但是對于某型類型的應用如Nginx Ingress controller而言,默認的內核參數配置是不夠的,需要做出調整,例如somaxconn是限制了接收新TCP 連接偵聽隊列的大小,它的默認值是128,但是對于反向代理的服務器而言,這個配置實在是太小了。那么我們自然想到需要去調整這個應用的容器的內核配置參數。
解決之道
Docker Daemon的處理方式
對于Docker引擎而言,可是使用--sysctl運行參數來設定需要更改的內核參數,例如:
- docker run -it --sysctl net.core.somaxconn=65535 busybox
- #在容器看看是否配置成功:
- cat /proc/sys/net/core/somaxconn
然后我們可以看看容器的詳情:
可以看到,Docker引擎對容器進行了相關的配置,而無需使用特權模式來設置內核參數
Kubernetes的處理之道
在Kubernetes里,Kubernetes可以利用Docker引擎的這個--sysctl的能力,也可以利用privilege init container的方式。目前sysctls的能力還依然在alpha階段,選擇時需要注意。
Kubernetes Sysctls
具體可以參考:Using Sysctls in a Kubernetes Cluster
實踐過程如下:
- 需要在kubelet啟動參數上配置對應的開關--experimental-allowed-unsafe-sysctls。例如在阿里云的kubernetes服務,可以在node節點,修改/etc/systemd/system/kubelet.service.d/10-kubeadm.conf,增加對應的配置并重新加載systemctl daemon-reload,然后重啟kubelet。如下是允許配置和net相關的內核參數:
Kubernetes允許配置的內核參數如下:
- kernel.shm*,
- kernel.msg*,
- kernel.sem,
- fs.mqueue.*,
- net.*.
- 啟動Pod的時候設置對應的annotation,申明需要修改的內核參數,以啟動一個nginx為測試例子:
- 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
注意:對于需要變更內核參數的應用,建議部署到特定的機器上。為了方便,我是使用了node selector。
如果對應的機器的kubelet沒有打開這個對應的開關,那么pod是部署不成功的。我們可以通過kubectl get event來看看對應的日志:
那么這個方式背后的原理是什么呢?其實就是docker的--sysctl,我們可以pod到對應的node接點去docker inspect看看。但是奇怪的是,docker inspect看不到任何sysctl的跡象,是不是那里有誤?
其實不是的,因為真正執行sysctl是kubernetes的pause container也叫做infra container,我們找到對應的這個容器,再docker inspect看看:
這個時候,我們發現,這個pause容器配置了sysctls。
Kubernetes Init Container
Init container的用法可以參考:Init Containers
使用init container的好處是,無需去改變kubelet的配置,但是需要給這個init container配置成privilege的權限。
以下是一個啟動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
至于使用那種方式,可以自行選擇。后續也要留意kubernetes對于sysctls的演進。
【本文是51CTO專欄作者“VIPDOCKER-了哥 ”的原創文章,如需轉載請通過51CTO與作者聯系】