Kubernetes各組件參數配置優化建議

Kubernetes各組件參數配置優化建議

kubernetes雖然默認配置下已經足夠可用滿足常見的中小規模場景,但是若是將各組件參數、內核參數進行適當的調整,以達到更貼合使用場景的參數值,對集羣運行的穩定性、故障切換能力等方面會有不小的提升。下面介紹一下各組件生產運行常做的一些參數調整。

Kubelet參數配置

kubelet在各個組件之中,作爲唯一的分佈在每個節點上的daemon控制程序,應該也是需要調整參數最多的組件了,從此前的flag形式的傳參,到自1.11版本起的改用專屬配置文件,充分說明了其配置調整是很常用的場景,下面舉幾個常見的配置項,如node狀態彙報頻率、pod最大數量、以及生產運行非常重要的pod驅逐、資源保留等。

舊版本kubelet配置

在1.11版本之前,kubelet通過命令flag的方式指定和調整參數,例如:

  • --node-status-update-frequency=5s # 向apiserver刷新node狀態的時間間隔,默認10s
  • --serialize-image-pulls=false # 是否串行拉取鏡像,默認爲true,false改爲並行,提升拉取鏡像速度
  • --max-pods=200 # 單node運行的最大pod數量,默認110,注意調整不要超過pod CIDR的單個子網可用地址數量。
  • --eviction-hard=memory.available<1024Mi,nodefs.available<10%# 節點資源小於指定值時開啓硬驅逐上嗎的pod

資源保留配置

爲防止pod使用過多的資源,從而擠佔和影響了k8s控制組件(例如kubelet)、系統管理進程的正常運行,指定以下配置爲這兩者保留一部分的資源。與pod QOS 一樣,資源保留的方式同樣也是使用cgroup來做資源隔離保證。

  • --enforce-node-allocatable=pods,kube-reserved,system-reserved # 開啓針對這幾者的cgroup資源管理。
  • --kube-reserved-cgroup=/system.slice/kubelet.service # 指定k8s組件保留資源對應的cgroup路徑
  • --system-reserved-cgroup=/system.slice # 指定系統組件保留資源對應的cgroup路徑
  • `–kube-reserved=cpu=1,memory=2Gi # 指定k8s組件保留1g/1c的資源
  • `–system-reserved=cpu=1,memory=1Gi # 爲系統運行保留1g/1c的資源

以上參數配置在kubelet systemd啓動服務內,例如kubeadm安裝的集羣,kubelet啓動服務一般在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf路徑內,配置環境變量的形式來修改啓動配置,例如:

# 增加一個變量
Environment="RESOUCE_RESERVE_CONFIG_ARGS=--kube-reserved-cgroup=/system.slice/kubelet.service  --system-reserved-cgroup=/system.slice  --kube-reserved=cpu=1,memory=2Gi,ephemeral-storage=1Gi --system-reserved=cpu=1,memory=1Gi,ephemeral-storage=1Gi

# 啓動命令末尾加入參數變量
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS $RESOUCE_RESERVE_CONFIG_ARGS

新版本kubelet配置

1.11及以後的版本,開始使用配置文件的形式指定kubelet配置,不再建議使用flag參數的形式。配置文件的路徑在啓動服務的文件裏可以找到,如果使用的是kubeadm安裝的,路徑一般是/var/lib/kubelet/config.yaml各版本可能有些許不同。參數其實還是與上方一致,只不過abc-def式寫法變成了go更推薦的駝峯式寫法,這裏不再對參數作解釋,直接貼出配置

address: 0.0.0.0
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
cgroupDriver: cgroupfs
cgroupsPerQOS: true
clusterDNS:
- 10.112.0.10
clusterDomain: cluster.local
configMapAndSecretChangeDetectionStrategy: Watch
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuCFSQuotaPeriod: 100ms
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
# 這裏添加kube-reserved, system-reserved僅作參考,官方建議不要開啓
enforceNodeAllocatable:
- pods
- kube-reserved
- system-reserved
eventBurst: 10
eventRecordQPS: 5
evictionHard:
  imagefs.available: 15%
  # 加到1G
  memory.available: 1024Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 3m0s
failSwapOn: true
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kind: KubeletConfiguration
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
# 調整爲200
maxPods: 200
nodeLeaseDurationSeconds: 40
nodeStatusReportFrequency: 1m0s
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
port: 10250
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: false
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
kubeReservedCgroup: /system.slice/kubelet.service
kubeReserved:
  cpu: "1"
  memory: 2Gi
systemReservedCgroup: /system.slice
# 官方不建議開啓systemReserved,因爲可能會帶來某些不可控的系統關鍵進程的異常,這裏列出僅作參考
systemReserved:
  cpu: "1"
  memory: 2Gi

看到網上有很多內容高度一致的文章將systemReserved和kubeReserved兩者都同時開啓了,其實官方不建議開啓systemReserved,因爲這可能會導致系統關鍵進程遭遇不可控的風險,說明如下:

Be extra careful while enforcing system-reserved

注:非常重要!kubelet並不會自動創建cgroup,因此,需要在啓動服務前爲其指定創建相應cgroup的命令,建議寫入啓動服務文件內,無論是傳統指定flag方式,還是配置文件方式,都需要在啓動服務文件內添加創建cgroup的命令,否則kubelet服務會啓動失敗

這裏貼一個新版本的啓動服務文件內容:

~# cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
# 下面兩條命令提前創建cgroup
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/hugetlb/system.slice/kubelet.service
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

修改完以上配置後,執行systemctl daemon-reload && systemctl restart kubelet重啓kubelet,若無意外,kubelet重啓正常後,可檢驗cgroup是否如期創建指定的內存限制,如下剛好是2g,說明cgroup指定已成功:

cat /sys/fs/cgroup/memory/system.slice/kubelet.service/memory.limit_in_bytes
2147483648

當然,以上的kubelet配置修改需要重啓kubelet,如果你需要直接在線更新kubelet配置的話,可以參考官方的的步驟進行修改配置:

Reconfiguring the Kubelet on a Live Node in your Cluster

Controller參數配置

controller常調整的參數是針對其驅逐功能的,即在node進入離線狀態後,將node置爲ConditionUnknown狀態,並在持續一段時間後開始依一定的次序驅逐問題node上面pod到其他node上,以儘快恢復到聲明數量的ready副本數。

  • --node-cidr-mask-size # node上的pod cidr掩碼位數,默認爲24位,即最多253個可用地址,視地址空間和pod數量調整。
  • --node-monitor-period # 檢查當前node健康狀態的週期間隔,默認5s
  • --node-monitor-grace-period # 當前node超過了這個指定週期後,即視node爲不健康,進入ConditionUnknown狀態,默認40s
  • --pod-eviction-timeout # 當node進入notReady狀態後,經過這個指定時間後,會開始驅逐node上的pod,默認5m
  • --large-cluster-size-threshold # 判斷集羣是否爲大集羣,默認爲 50,即 50 個節點以上的集羣爲大集羣。
  • --unhealthy-zone-threshold:# 故障節點數比例,默認爲 55%
  • --node-eviction-rate # 開始對node進行驅逐操作的頻率,默認0.1個/s,即每10s最多驅逐某一個node上的pod,避免當master出現問題時,會有批量的node出現異常,這時候如果一次性驅逐過多的node,對master造成額外的壓力
  • --secondary-node-eviction-rate: # 當集羣規模大於large-cluster-size-threshold個node時,視爲大集羣, 集羣中只要有55%的node不健康, 就會認爲master出現了故障, 會將驅逐速率從0.1降爲0.001; 如果集羣規模小於large-cluster-size-threshold個node, 集羣中出現55%的node不健康,就會停止驅逐。

配置建議:

  • 中大規模集羣(500+ node)

    大規模集羣一般節點數較多,優勢是可用性、抗風險能力強,劣勢是組件之間的交互頻繁,會給apiServer和etcd帶來較大的壓力,因此配置建議:

    • --node-monitor-period 適當增加
    • --large-cluster-size-threshold 適當增加
    • --unhealthy-zone-threshold 適當減小
    • --pod-eviction-timeout 視服務可用性保障級別適當調整
    • --node-eviction-rate 視服務可用性保障級別適當增加
    • --secondary-node-eviction-rate 視服務可用性保障級別適當增加
  • 小規模集羣(100- node)

    小規模集羣一般節點數不多,因此副本數量一般也較小,對節點中斷的容忍度和容忍時間較低,因此配置建議:

    • --node-monitor-period 不變或可適當減小
    • --pod-eviction-timeout大幅減小,如1m-2m,單節點故障儘快轉移上面的pod
    • --node-eviction-rate 建議減小,避免問題pod轉移導致集羣快速雪崩,預留防範處理時間

如果使用kubeadm部署的,修改yaml文件即可自動觸發 apiserver/scheduler/controller這幾個static pod的重啓, 3者的yaml文件都位於:/etc/kubernetes/manifests/下,修改保存pod即會自動重啓加載新配置。

另注:默認驅逐pod的優先級

根據pod的QOS保證級別,優先驅逐調度保證保障質量高級別的pod最先恢復正常:

BestEffort > Burstable > Guaranteed

ApiServer參數配置

  • --max-mutating-requests-inflight # 單位時間內的最大修改型請求數量,默認200
  • --max-requests-inflight # 單位時間內的最大非修改型(讀)請求數量,默認400
  • --watch-cache-sizes # 各類resource的watch cache,默認100,資源數量較多時需要增加

Scheduler參數配置

scheduler的配置項比較少,因爲調度規則已經是很明確了,不過可以自定義預選和優選策略。

  • --kube-api-qps # 請求apiserver的最大qps,默認50
  • --policy-config-file # json文件,不指定時使用默認的調度預選和優選策略,可以自定義指定,樣例參考:scheduler-policy-config.json

調度策略分爲預選和優選兩個步驟,建議對其過程或源碼有一定了解後,再做策略調整,調度過程可以參考我的源碼筆記:

《Kubernetes Source Code Note》

調度策略的調整要與自身的環境結合,默認的優選策略中,每一項計算緯度的權重默認幾乎都是1,在我的環境中,比較重視資源平均利用率以及服務副本的高可用性,因此,將SelectorSpreadPriorityBalancedResourceAllocation調高。下面是我的json文件:

scheduler-policy-config.json

{
    "apiVersion": "v1",
    "kind": "Policy",
    "predicates": [
        {"name": "NoVolumeZoneConflict"},
        {"name": "MaxEBSVolumeCount"},
        {"name": "MaxGCEPDVolumeCount"},
        {"name": "MaxAzureDiskVolumeCount"},
        {"name": "MatchInterPodAffinity"},
        {"name": "NoDiskConflict"},
        {"name": "GeneralPredicates"},
        {"name": "PodToleratesNodeTaints"},
        
        // 下面三項在v1.12及之後的版本下需要刪除掉,這是一個bug,刪掉不影響正常工作。
      	// 參考:https://github.com/kubernetes/kops/issues/7740
        {"name": "CheckNodeMemoryPressure"},
        {"name": "CheckNodeDiskPressure"},
        {"name": "CheckNodeCondition"},
        {
            "argument": {
                "serviceAffinity": {
                    "labels": [
                        "region"
                    ]
                }
            },
            "name": "Region"
         }
    ],
    "priorities": [
        {
            "name": "SelectorSpreadPriority",
            "weight": 3
        },
       {
            "name": "BalancedResourceAllocation",
            "weight": 3
        },
        {
            "name": "InterPodAffinityPriority",
            "weight": 1
        },
        {
            "name": "LeastRequestedPriority",
            "weight": 1
        },
        {
            "name": "NodePreferAvoidPodsPriority",
            "weight": 10000
        },
        {
            "name": "NodeAffinityPriority",
            "weight": 1
        },
        {
            "name": "TaintTolerationPriority",
            "weight": 1
        },
        {
            "argument": {
                "serviceAntiAffinity": {
                    "label": "zone"
                }
            },
            "name": "Zone",
            "weight": 2
        }
    ]
}

注意

指定policy配置啓動scheduler後,會完全覆蓋默認註冊的所有調度策略,因此,即使是無需改動的策略緯度,必須完全顯示的在policy json中寫出來,如果不寫出,scheduler重啓後該項緯度不再使用。

配置完成後,修改scheduler的啓動參數,指定此json文件,同時,最好將此文件使用configMap形式或其他形式持久化掛載。

內核參數配置

fs.file-max=1000000
# max-file 表示系統級別的能夠打開的文件句柄的數量

# 配置arp cache 大小
net.ipv4.neigh.default.gc_thresh1=1024
# 存在於ARP高速緩存中的最少層數,如果少於這個數,垃圾收集器將不會運行。缺省值是128。

net.ipv4.neigh.default.gc_thresh2=4096
# 保存在 ARP 高速緩存中的最多的記錄軟限制。垃圾收集器在開始收集前,允許記錄數超過這個數字 5 秒。缺省值是 512。

net.ipv4.neigh.default.gc_thresh3=8192
# 保存在 ARP 高速緩存中的最多記錄的硬限制,一旦高速緩存中的數目高於此,垃圾收集器將馬上運行。缺省值是1024。
以上三個參數,當內核維護的arp表過於龐大時候,可以考慮優化

net.netfilter.nf_conntrack_max=10485760
# 允許的最大跟蹤連接條目,是在內核內存中netfilter可以同時處理的“任務”(連接跟蹤條目)
net.netfilter.nf_conntrack_tcp_timeout_established=300
net.netfilter.nf_conntrack_buckets=655360
# 哈希表大小(只讀)(64位系統、8G內存默認 65536,16G翻倍,如此類推)
net.core.netdev_max_backlog=10000
# 每個網絡接口接收數據包的速率比內核處理這些包的速率快時,允許送到隊列的數據包的最大數目。
關於conntrack的詳細說明:https://testerhome.com/topics/7509

fs.inotify.max_user_instances=524288
# 默認值: 128 指定了每一個real user ID可創建的inotify instatnces的數量上限

fs.inotify.max_user_watches=524288
# 默認值: 8192 指定了每個inotify instance相關聯的watches的上限
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章