成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

生產環境 Kubernetes 中出現了很多 Evicted Pod,我該怎么辦呢?

系統 Linux
本文會分析為什么為產生 Evicted 實例、為什么 Evicted 實例沒有被自動清理以及如何進行自動清理。

 [[439064]]

線上被驅逐實例數據

最近在線上發現很多實例處于 Evicted 狀態,通過 pod yaml 可以看到實例是因為節點資源不足被驅逐,但是這些實例并沒有被自動清理,平臺的大部分用戶在操作時看到服務下面出現 Evicted 實例時會以為服務有問題或者平臺有問題的錯覺,影響了用戶的體驗。而這部分 Evicted 狀態的 Pod 在底層關聯的容器其實已經被銷毀了,對用戶的服務也不會產生什么影響,也就是說只有一個 Pod 空殼在 k8s 中保存著,但需要人為手動清理。本文會分析為什么為產生 Evicted 實例、為什么 Evicted 實例沒有被自動清理以及如何進行自動清理。

kubernetes 版本:v1.17 

  1. $ kubectl get pod | grep -i Evicted  
  2. cloud-1023955-84421-49604-5-deploy-c-7748f8fd8-hjqsh        0/1     Evicted   0          73d  
  3. cloud-1023955-84421-49604-5-deploy-c-7748f8fd8-mzd8x        0/1     Evicted   0          81d  
  4. cloud-1237162-276467-199844-2-deploy-7bdc7c98b6-26r2r       0/1     Evicted   0          18d 

Evicted 實例狀態: 

  1. status:  
  2.   message: 'Pod The node had condition: [DiskPressure]. '  
  3.   phase: Failed  
  4.   reason: Evicted  
  5.   startTime: "2021-09-14T10:42:32Z" 

實例被驅逐的原因

kubelet 默認會配置節點資源不足時驅逐實例的策略,當節點資源不足時 k8s 會停止該節點上實例并在其他節點啟動新實例,在某些情況下也可通過配置 --eviction-hard= 參數為空來禁用驅逐策略,在之前的生產環境中我們也確實這么做了。

節點資源不足導致實例被驅逐

k8s 中產生 Evicted 狀態實例主要是因為節點資源不足實例主動被驅逐導致的,kubelet eviction_manager 模塊會定期檢查節點內存使用率、inode 使用率、磁盤使用率、pid 等資源,根據 kubelet 的配置當使用率達到一定閾值后會先回收可以回收的資源,若回收后資源使用率依然超過閾值則進行驅逐實例操作。

Eviction Signal Description
memory.available memory.available := node.status.capacity[memory] - node.stats.memory.workingSet
nodefs.available nodefs.available := node.stats.fs.available
nodefs.inodesFree nodefs.inodesFree := node.stats.fs.inodesFree
imagefs.available imagefs.available := node.stats.runtime.imagefs.available
imagefs.inodesFree imagefs.inodesFree := node.stats.runtime.imagefs.inodesFree
pid.available pid.available := node.stats.rlimit.maxpid - node.stats.rlimit.curproc

kubelet 中 pod 的 stats 數據一部分是通過 cAdvisor 接口獲取到的,一部分是通過 CRI runtimes 的接口獲取到的。

  •  memory.available:當前節點可用內存,計算方式為 cgroup memory 子系統中 memory.usage_in_bytes 中的值減去 memory.stat 中 total_inactive_file 的值;
  •  nodefs.available:nodefs 包含 kubelet 配置中 --root-dir 指定的文件分區和 /var/lib/kubelet/ 所在的分區磁盤使用率;
  •  nodefs.inodesFree:nodefs.available 分區的 inode 使用率;
  •  imagefs.available:鏡像所在分區磁盤使用率;
  •  imagefs.inodesFree:鏡像所在分區磁盤 inode 使用率;
  •  pid.available:/proc/sys/kernel/pid_max 中的值為系統最大可用 pid 數;

kubelet 可以通過參數 --eviction-hard 來配置以上幾個參數的閾值,該參數默認值為 imagefs.available<15%,memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%,當達到閾值時會驅逐節點上的容器。

kubelet 驅逐實例時與資源處理相關的已知問題

1、kubelet 不會實時感知到節點內存數據的變化

kubelet 定期通過 cadvisor 接口采集節點內存使用數據,當節點短時間內內存使用率突增,此時 kubelet 無法感知到也不會有 MemoryPressure 相關事件,但依然會調用 OOMKiller 停止容器??梢酝ㄟ^為 kubelet 配置 --kernel-memcg-notification 參數啟用 memcg api,當觸發 memory 使用率閾值時 memcg 會主動進行通知;

memcg 主動通知的功能是 cgroup 中已有的,kubelet 會在 /sys/fs/cgroup/memory/cgroup.event_control 文件中寫入 memory.available 的閾值,而閾值與 inactive_file 文件的大小有關系,kubelet 也會定期更新閾值,當 memcg 使用率達到配置的閾值后會主動通知 kubelet,kubelet 通過 epoll 機制來接收通知。

2、kubelet memory.available 不會計算 active page

kubelet 通過內存使用率驅逐實例時,內存使用率數據包含了 page cache 中 active_file 的數據,在某些場景下會因 page cache 過高導致內存使用率超過閾值會造成實例被驅逐,

由于在內存緊張時 inactive_file 會被內核首先回收,但在內存不足時,active_file 也會被內核進行回收,社區對此機制也有一些疑問,針對內核回收內存的情況比較復雜,社區暫時還未進行回應,詳情可以參考 kubelet counts active page cache against memory.available (maybe it shouldn’t?)[1]。

kubelet 計算節點可用內存的方式如下: 

  1. #!/bin/bash  
  2. #!/usr/bin/env bash  
  3. # This script reproduces what the kubelet does  
  4. # to calculate memory.available relative to root cgroup.  
  5. # current memory usage  
  6. memory_capacity_in_kb=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}')  
  7. memory_capacity_in_bytes=$((memory_capacity_in_kb * 1024))  
  8. memory_usage_in_bytes=$(cat /sys/fs/cgroup/memory/memory.usage_in_bytes)  
  9. memory_total_inactive_file=$(cat /sys/fs/cgroup/memory/memory.stat | grep total_inactive_file | awk '{print $2}')  
  10. memory_working_set=${memory_usage_in_bytes}  
  11. if [ "$memory_working_set" -lt "$memory_total_inactive_file" ];  
  12. then  
  13.     memory_working_set=0  
  14. else  
  15.     memory_working_set=$((memory_usage_in_bytes - memory_total_inactive_file))  
  16. fi  
  17. memory_available_in_bytes=$((memory_capacity_in_bytes - memory_working_set))  
  18. memory_available_in_kb=$((memory_available_in_bytes / 1024))  
  19. memory_available_in_mb=$((memory_available_in_kb / 1024))  
  20. echo "memory.capacity_in_bytes $memory_capacity_in_bytes"  
  21. echo "memory.usage_in_bytes $memory_usage_in_bytes"  
  22. echo "memory.total_inactive_file $memory_total_inactive_file"  
  23. echo "memory.working_set $memory_working_set"  
  24. echo "memory.available_in_bytes $memory_available_in_bytes"  
  25. echo "memory.available_in_kb $memory_available_in_kb"  
  26. echo "memory.available_in_mb $memory_available_in_mb" 

驅逐實例未被刪除原因分析

源碼中對于 Statefulset 和 DaemonSet 會自動刪除 Evicted 實例,但是對于 Deployment 不會自動刪除。閱讀了部分官方文檔以及 issue,暫未找到官方對 Deployment Evicted 實例未刪除原因給出解釋。

statefulset:pkg/controller/statefulset/stateful_set_control.go 

  1. // Examine each replica with respect to its ordinal  
  2. for i :range replicas {  
  3.     // delete and recreate failed pods  
  4.     if isFailed(replicas[i]) {  
  5.         ssc.recorder.Eventf(set, v1.EventTypeWarning, "RecreatingFailedPod",  
  6.             "StatefulSet %s/%s is recreating failed Pod %s",  
  7.             set.Namespace,  
  8.             set.Name,  
  9.             replicas[i].Name)  
  10.         if err :ssc.podControl.DeleteStatefulPod(set, replicas[i]); err != nil {  
  11.             return &status, err  
  12.         }  
  13.         if getPodRevision(replicas[i]) == currentRevision.Name {  
  14.             status.CurrentReplicas--  
  15.         } 
  16.          if getPodRevision(replicas[i]) == updateRevision.Name {  
  17.             status.UpdatedReplicas--  
  18.         }  
  19.         ...... 

daemonset:pkg/controller/daemon/daemon_controller.go 

  1. func (dsc *DaemonSetsController) podsShouldBeOnNode(  
  2.   ......  
  3. ) (nodesNeedingDaemonPods, podsToDelete []string) {  
  4.   ......  
  5.     switch {  
  6.   ......  
  7.     case shouldContinueRunning:  
  8.     ......  
  9.         for _, pod :range daemonPods {  
  10.             if pod.DeletionTimestamp != nil {  
  11.                 continue  
  12.             }  
  13.             if pod.Status.Phase == v1.PodFailed {  
  14.                 // This is a critical place where DS is often fighting with kubelet that rejects pods.  
  15.                 // We need to avoid hot looping and backoff.  
  16.                 backoffKey :failedPodsBackoffKey(ds, node.Name)  
  17.                 ...... 

解決方案

1、團隊里面有了一套 k8s 集群事件采集的鏈路,我們通過消費 k8s 中 pod 的相關事件來進行處理,消費事件時過濾 pod 中與 Evicted 實例相關的事件然后處理即可。

Evicted 實例判斷邏輯: 

  1. const (  
  2.  podEvictedStatus = "Evicted"  
  3.  
  4. // 判斷如果為 Evicted 狀態的實例且 Pod 中容器數為 0 時直接刪除 pod  
  5. if strings.ToLower(status) == strings.ToLower(podEvictedStatus) && len(pod.Status.ContainerStatuses) == 0 {  

2、社區有人提供通過在 kube-controller-manager 中配置 podgc controller –terminated-pod-gc-threshold 參數來自動清理: 

  1. Podgc controller flags:  
  2.       --terminated-pod-gc-threshold int32  
  3.                 Number of terminated pods that can exist before the terminated pod garbage collector starts deleting terminated pods. If  
  4.                 <= 0, the terminated pod garbage collector is disabled. (default 12500) 

該參數配置的是保留的異常實例數,默認值為 12500,但 podgc controller 回收 pod 時使用強殺模式不支持實例的優雅退出,因此暫不考慮使用。

3、其他處理方式可以參考社區中提供的 Kubelet does not delete evicted pods[2]。

總結

由于在之前的公司中對于穩定性的高度重視,線上節點并未開啟驅逐實例的功能,因此也不會存在 Evicted 狀態的實例,當節點資源嚴重不足時會有告警人工介入處理,以及還會有二次調度、故障自愈等一些輔助處理措施。本次針對 Evicted 相關實例的分析,發現 k8s 與操作系統之間存在了很多聯系,如果要徹底搞清楚某些機制需要對操作系統的一些原理有一定的了解。 

 

責任編輯:龐桂玉 來源: 奇妙的Linux世界
相關推薦

2021-12-09 11:46:53

DockerIPLinux

2018-08-20 19:39:14

區塊鏈職業崗位

2022-02-06 00:16:53

加密貨幣比特幣以太坊

2020-09-29 12:15:13

生死鎖MySQL

2020-07-21 10:05:48

技術研發指標

2019-06-03 10:53:49

MySQL硬盤數據庫

2011-10-17 12:30:43

2022-09-05 09:02:01

服務器CPU服務

2022-05-19 08:01:49

PostgreSQL數據庫

2018-01-28 20:39:39

戴爾

2009-11-03 08:56:02

linux死機操作系統

2022-12-19 11:31:57

緩存失效數據庫

2022-07-05 11:48:47

MySQL死鎖表鎖

2022-04-22 10:30:07

框架JavaScript前端

2011-06-30 17:58:30

網站被K

2022-07-05 14:19:30

Spring接口CGLIB

2011-11-16 10:02:48

DNSDNS記錄DNS記錄消失

2011-11-18 10:52:00

2022-10-14 08:18:07

Guavaweb應用

2020-12-18 09:23:41

KubernetesDocker
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日日干夜夜操 | 91.色| 天堂久久天堂综合色 | 91污在线| 精品欧美一区免费观看α√ | 2019天天干天天操 | 91久久久久 | 91社区在线高清 | 亚洲国产精品视频一区 | 99精品一区| 日韩精品一区二区三区在线播放 | 久久国产综合 | 国产精品综合色区在线观看 | 美女午夜影院 | av中文字幕在线 | 久久综合国产精品 | 久久国产精品-国产精品 | 日韩精品在线观看一区二区三区 | 夜夜草天天草 | 超碰97免费观看 | 久久久久久国产精品久久 | 欧美成视频在线观看 | 日韩一区二区三区在线 | 国产精品日日做人人爱 | 欧洲一区二区三区 | 免费看一级毛片 | 成人免费视频网站在线看 | 久在线| www.婷婷亚洲基地 | 看av在线 | 欧美在线视频一区 | 四虎影院欧美 | yiren22综合网成人 | 日本高清视频网站 | 日韩欧美在线观看视频 | 一级a性色生活片久久毛片波多野 | 中文字幕亚洲精品 | 三级高清 | 欧美视频区| 精品免费国产一区二区三区 | 在线精品国产 |