kubernetes高階之叢集中使用sysctls

周國通發表於2019-06-25

系列目錄

在linux系統裡,sysctls 介面允許管理員在執行時修改核心引數.引數存在於/proc/sys/虛擬程式檔案系統裡.引數涉及到很多子模組,例如:

  • 核心(kernel)(常見字首kernel.)

  • 網路(networking)(常見字首net.)

  • 虛擬記憶體(virtual memory) (常見字首 vm.)

  • MDADM(常見字首dev.)

啟用非安全sysctls

sysctls分為安全和非安全的.除了合理地劃分名稱空間外一個安全的sysctl必須在同一個節點上的pod間是隔離的.這就意味著為一個pod設定安全的sysctl需要考慮以下:

  • 必須不能影響同一節點上的其它pod

  • 必須不能危害節點的健康

  • 必須不能獲取自身pod所限制以外的cpu或記憶體資源

截至目前,大部分名稱空間下的sysctls都不被認為是安全的.以下列出被kubernetes安全支援:

  • kernel.shm_rmid_forced

  • net.ipv4.ip_local_port_range

  • net.ipv4.tcp_syncookies

如果日後kubelete支援更好的隔離機制,這份支援的安全列表將會擴充套件

所有安全sysctls預設被開啟

所有的非安全sysctls預設被關閉,管理員必須手動在pod級別啟動.包含非安全sysctls的pod仍然會被排程,但是將啟動失敗.

請牢記以上警告,叢集管理員可以在特殊情況下,比如為了高效能或者時實應用系統優化,可以啟動相應的sysctls.sysctl可以通過kubelet在節點級別啟動

即需要在想要開啟sysctl的節點上手動啟動.如果要在多個節點上啟動則需要分別進入相應的節點進行設定.

kubelet --allowed-unsafe-sysctls \
  'kernel.msg*,net.ipv4.route.min_pmtu' ...

對於minikube,則可以通過extra-config來配置

minikube start --extra-config="kubelet.allowed-unsafe-sysctls=kernel.msg*,net.ipv4.route.min_pmtu"...

僅有名稱空間的sysctls可以通過這種方式開啟

為pod設定Sysctls

一系列的sysctls被劃分在不同的名稱空間內.這意味著他們可以為節點上的pod單獨地設定.僅有名稱空間的sysctls可以通過pod的securityContext被設定

以下列出的是已知的有名稱空間的.在日後的linux核心版本中可能會改變

  • kernel.shm*,

  • kernel.msg*,

  • kernel.sem,

  • fs.mqueue.*,

  • net.*.

沒有名稱空間的systls被稱作節點級別sysctls.如果你需要設定它們,你必須在每個節點的作業系統上手動設定,或者通過有特權的DaemonSet來設定

使用pod的安全上下文(securityContext)來設定有名稱空間的sysctls.安全上下文對pod內的所有容器都產生效果.

以下示例通過pod的安全上下文來設定一個安全的sysctl kernel.shm_rmid_forced和兩個非安全的sysctls net.ipv4.route.min_pmtu以及kernel.msgmax .在pod的spec裡面,安全的sysctl和非安全的sysctl宣告並沒有區別

在生產環境中,僅僅在你明白了要設定的sysctl的功能時候才進行設定,以免造成系統不穩定.

apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
spec:
  securityContext:
    sysctls:
    - name: kernel.shm_rmid_forced
      value: "0"
    - name: net.ipv4.route.min_pmtu
      value: "552"
    - name: kernel.msgmax
      value: "65536"
  ...
由於非安全sysctls的非安全特徵,設定非安全sysctls產生的後果將由你自行承擔,可能產生的後果包含pod行為異常,資源緊張或者節點完全崩潰

pod安全策略(PodSecurityPolicy)

你可以通過設定pod安全策略裡的forbiddenSysctls(和)或者allowedUnsafeSysctls來進一步控制哪些sysctls可以被設定.一個以*結尾的sysctl,比如kernel.*匹配其下面所有的sysctl

forbiddenSysctlsallowedUnsafeSysctls均是一系列的純字串sysctl名稱或者sysctl模板(以*結尾).*匹配所有的sysctl

forbiddenSysctls將排除一系列sysctl.你可以排除一系列安全和非安全的sysctls.如果想要禁止設定任何sysctls,可以使用*

如果你在allowedUnsafeSysctls欄位設定了非安全sysctls,並且沒有出現在forbiddenSysctls欄位裡,則使用了此pod安全策略的pods可以使用這個(些)(sysctls).如果想啟用所有的非安全sysctls,可以設定*

警告,如果你通過pod安全策略的allowedUnsafeSysctls把非安全sysctl新增到白名單(即可以執行),但是如果節點級別沒有通過sysctl設定--allowed-unsafe-sysctls,pod將啟動失敗.

以下示例允許以kernel.msg開頭的sysctls被設定,但是禁止設定kernel.shm_rmid_forced

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: sysctl-psp
spec:
  allowedUnsafeSysctls:
  - kernel.msg*
  forbiddenSysctls:
  - kernel.shm_rmid_forced
 ...

相關文章