Kubernetes排錯(七)-節點排錯

1、節點 Crash 與 Vmcore 分析

kdump 介紹?

目前大多 Linux 發新版都會默認開啟 kdump 服務,以方便在內核崩潰的時候, 可以通過 kdump 服務提供的 kexec 機制快速的啟用保留在內存中的第二個內核來收集并轉儲內核崩潰的日志信息(vmcore?等文件), 這種機制需要服務器硬件特性的支持, 不過現今常用的服務器系列均已支持.

如果沒有特別配置 kdump,當發生 crash 時,通常默認會將 vmcore 保存到?/var/crash?路徑下,也可以查看?/etc/kdump.conf?配置來確認:

$ grep ^path /etc/kdump.conf
path /var/crash

參考:kdump詳解-CSDN博客?

快速查看原因?

在需要快速了解崩潰原因的時候, 可以簡單查看崩潰主機(如果重啟成功)的?vmcore-dmesg.txt?文件, 該文件列出了內核崩潰時的堆棧信息, 有助于我們大致了解崩潰的原因, 方便處理措施的決斷. 如下所示為生成的日志文件通常的路徑:

/var/crash/127.0.0.1-2019-11-11-08:40:08/vmcore-dmesg.txt

2、節點高負載?

1)如何判斷節點高負載??

可以通過?top?或?uptime?命令行來確定 load 大小。load 負載判定規則:

  • load負載值 <= 0.7 * CPU 核數:低負載
  • 0.7 * CPU 核數 < load負載值 <=?CPU 核數:負載存在壓力
  • load負載值 >?CPU 核數: 高負載

2)排查思路?

觀察監控:通常不是因為內核 bug 導致的高負載,在系統卡死之前從操作系統監控一般能看出一些問題,可以觀察下系統各項監控指標與load監控指標的變化趨勢,觀察是否存在與load監控指標相同變化趨勢的指標。

排查現場:如果沒有相關監控或監控維度較少不足以查出問題,嘗試登錄節點分析現場。

注:有時負載過高通常使用 ssh 登錄不上,如果可以用 vnc,可以嘗試下使用 vnc 登錄。

3)排查現場思路?

load avg 可以認為是 R狀態線程數和D狀態線程數的總和 (R 代表需要 cpu,是 cpu 負載。 D 通常代表需要 IO,是 IO 負載),因此一般導致load負載高基本是CPU或者IO。

簡單判斷辦法:

ps -eL -o lwp,pid,ppid,state,comm | grep -E " R | D "

然后統計一下各種狀態多少個進程,看看是 D 多還是 R多。

如果是長時間 D多,可以進一步查看進程堆棧看看 D 多的原因是什么,如果是存在大量寫請求,可以考慮業務請求數據量調整批次大小,多批次小數據量寫入,同時優化磁盤落盤的頻率。

cat /proc/<PID>/stack

如果是大量進程/線程在 R 狀態,那就是同時需要 CPU 的進程/線程數過多,CPU 忙不過來了,可以利用 perf 分析程序在忙什么,但此時可以考慮業務擴容或者機器調大CPU核數。

perf -p <PID>

4)線程數量過多?

如果 load 高但 CPU 利用率不高,通常是同時 running 的進程/線程數過多,排隊等 CPU 切換的進程/線程較多。

通常在 load 高時執行任何命令都會非常卡,因為執行這些命令也都意味著要創建和執行新的進程,所以下面排查過程中執行命令時需要耐心等待。

看系統中可創建的進程數實際值:

cat /proc/sys/kernel/pid_max

修改方式: sysctl -w kernel.pid_max=65535

通過以下命令統計當前 PID 數量:

ps -eLf | wc -l

如果數量過多,可以大致掃下有哪些進程,如果有大量重復啟動命令的進程,就可能是這個進程對應程序的 bug 導致。

還可以通過以下命令統計線程數排名:

printf "NUM\tPID\tCOMMAND\n" && ps -eLf | awk '{$1=null;$3=null;$4=null;$5=null;$6=null;$7=null;$8=null;$9=null;print}' | sort |uniq -c |sort -rn | head -10

找出線程數量較多的進程,可能就是某個容器的線程泄漏,導致 PID 耗盡。

隨便取其中一個 PID,用 nsenter 進入進程 netns:

nsenter -n --target <PID>

然后執行?ip a?看下 IP 地址,如果不是節點 IP,通常就是 Pod IP,可以通過?kubectl get pod -o wide -A | grep <IP>?來反查進程來自哪個 Pod。

5)陷入內核態過久?

有些時候某些 CPU 可能會執行耗時較長的內核態任務,比如大量創建/銷毀進程,回收內存,需要較長時間 reclaim memory,必須要執行完才能切回用戶態,雖然內核一般會有 migration 內核線程將這種負載較高的核上的任務遷移到其它核上,但也只能適當緩解,如果這種任務較多,整體的 CPU system 占用就會較高,影響到用戶態進程任務的執行,對于業務來說,就是 CPU 不夠用,處理就變慢,發生超時。

CPU 內核態占用的 Prometheus 查詢語句:

sum(irate(node_cpu_seconds_total{instance="10.10.1.14",mode="system"}[2m]

6)IO 高負載

系統如果出現 IO WAIT 高,說明 IO 設備的速度跟不上 CPU 的處理速度,CPU 需要在那里干等,這里的等待實際也占用了 CPU 時間,導致系統負載升高,可能就會影響業務進程的處理速度,導致業務超時。

如何判斷IO處于高負載?

使用?top?命令看下當前負載:

top - 19:42:06 up 23:59,  2 users,  load average: 34.64, 35.80, 35.76
Tasks: 679 total,   1 running, 678 sleeping,   0 stopped,   0 zombie
Cpu(s): 15.6%us,  1.7%sy,  0.0%ni, 74.7%id,  7.9%wa,  0.0%hi,  0.1%si,  0.0%st
Mem:  32865032k total, 30989168k used,  1875864k free,   370748k buffers
Swap:  8388604k total,     5440k used,  8383164k free,  7982424k cachedPID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND9783 mysql     20   0 17.3g  16g 8104 S 186.9 52.3   3752:33 mysqld5700 nginx     20   0 1330m  66m 9496 S  8.9  0.2   0:20.82 php-fpm6424 nginx     20   0 1330m  65m 8372 S  8.3  0.2   0:04.97 php-fpm

%wa?(wait) 表示 IO WAIT 的 cpu 占用,默認看到的是所有核的平均值,要看每個核的?%wa?值需要按下 "1":

top - 19:42:08 up 23:59,  2 users,  load average: 34.64, 35.80, 35.76
Tasks: 679 total,   1 running, 678 sleeping,   0 stopped,   0 zombie
Cpu0  : 29.5%us,  3.7%sy,  0.0%ni, 48.7%id, 17.9%wa,  0.0%hi,  0.1%si,  0.0%st
Cpu1  : 29.3%us,  3.7%sy,  0.0%ni, 48.9%id, 17.9%wa,  0.0%hi,  0.1%si,  0.0%st
Cpu2  : 26.1%us,  3.1%sy,  0.0%ni, 64.4%id,  6.0%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu3  : 25.9%us,  3.1%sy,  0.0%ni, 65.5%id,  5.4%wa,  0.0%hi,  0.1%si,  0.0%st
Cpu4  : 24.9%us,  3.0%sy,  0.0%ni, 66.8%id,  5.0%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu5  : 24.9%us,  2.9%sy,  0.0%ni, 67.0%id,  4.8%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu6  : 24.2%us,  2.7%sy,  0.0%ni, 68.3%id,  4.5%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu7  : 24.3%us,  2.6%sy,  0.0%ni, 68.5%id,  4.2%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu8  : 23.8%us,  2.6%sy,  0.0%ni, 69.2%id,  4.1%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu9  : 23.9%us,  2.5%sy,  0.0%ni, 69.3%id,  4.0%wa,  0.0%hi,  0.3%si,  0.0%st
Cpu10 : 23.3%us,  2.4%sy,  0.0%ni, 68.7%id,  5.6%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu11 : 23.3%us,  2.4%sy,  0.0%ni, 69.2%id,  5.1%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu12 : 21.8%us,  2.4%sy,  0.0%ni, 60.2%id, 15.5%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu13 : 21.9%us,  2.4%sy,  0.0%ni, 60.6%id, 15.2%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu14 : 21.4%us,  2.3%sy,  0.0%ni, 72.6%id,  3.7%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu15 : 21.5%us,  2.2%sy,  0.0%ni, 73.2%id,  3.1%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu16 : 21.2%us,  2.2%sy,  0.0%ni, 73.6%id,  3.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu17 : 21.2%us,  2.1%sy,  0.0%ni, 73.8%id,  2.8%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu18 : 20.9%us,  2.1%sy,  0.0%ni, 74.1%id,  2.9%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu19 : 21.0%us,  2.1%sy,  0.0%ni, 74.4%id,  2.5%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu20 : 20.7%us,  2.0%sy,  0.0%ni, 73.8%id,  3.4%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu21 : 20.8%us,  2.0%sy,  0.0%ni, 73.9%id,  3.2%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu22 : 20.8%us,  2.0%sy,  0.0%ni, 74.4%id,  2.8%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu23 : 20.8%us,  1.9%sy,  0.0%ni, 74.4%id,  2.8%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  32865032k total, 30209248k used,  2655784k free,   370748k buffers
Swap:  8388604k total,     5440k used,  8383164k free,  7986552k cached

wa?通常是 0%,如果經常在 1% 之上,說明存儲設備的速度已經太慢,無法跟上 cpu 的處理速度。

IO高負載如何排查??

使用 iostat 檢查設備是否 hang 住??

iostat -xhd 2

如果有 100% 的?%util?的設備,說明該設備基本 hang 住了

觀察高 IO 的磁盤讀寫情況?

# 捕獲 %util 超過 90 時 vdb 盤的讀寫指標,每秒檢查一次
while true; do iostat -xhd | grep -A1 vdb | grep -v vdb | awk '{if ($NF > 90){print $0}}'; sleep 1s; done

如果讀寫流量或 IOPS 不高,但?%util?不高,通常是磁盤本身有問題了,需要檢查下磁盤。 在云上托管的 k8s 集群通常就使用的云廠商的云盤(比如騰訊云CBS),可以拿到磁盤 ID 反饋下。

如果讀寫流量或 IOPS 高,繼續下面的步驟排查出哪些進程導致的 IO 高負載。

查看哪些進程占住磁盤?

fuser -v -m /dev/vdb

查找 D 狀態的進程?

D 狀態 (Disk Sleep) 表示進程正在等待 IO,不可中斷,正常情況下不會保持太久,如果進程長時間處于 D 狀態,通常是設備故障

ps -eo pid,ppid,stat,command## 捕獲 D 狀態的進程
while true; do ps -eo pid,ppid,stat,command | awk '{if ($3 ~ /D/) {print $0}}'; sleep 0.5s; done

觀察高 IO 進程?

iotop -oP
# 展示 I/O 統計,每秒更新一次
pidstat -d 1
# 只看某個進程
pidstat -d 1 -p 3394470

使用 pidstat 統計?

timeout 10 pidstat -dl 3 > io.txt
cat io.txt | awk '{if ($6>2000||$5>2000)print $0}'

使用 ebpf 抓高 IOPS 進程?

安裝 bcc-tools:

yum install -y bcc-tools

分析:

$ cd /usr/share/bcc/tools
$ ./biosnoop 5 > io.txt
$ cat io.txt | awk '{print $3,$2,$4,$5}' | sort | uniq -c | sort -rn | head -106850 3356537 containerd vdb R1294 3926934 containerd vdb R864 1670 xfsaild/vdb vdb W578 3953662 kworker/u180:1 vda W496 3540267 logsys_cfg_cli vdb R459 1670 xfsaild/vdb vdb R354 3285936 php-fpm vdb R340 3285934 php-fpm vdb R292 2952592 sap1001 vdb R273 324710 python vdb R
$ pstree -apnhs 3356537
systemd,1 --switched-root --system --deserialize 22└─containerd,3895└─{containerd},3356537    
$ timeout 10 strace -fp 3895 > strace.txt 2>&1
# vdb 的 IOPS 高,vdb 掛載到了 /data 目錄,這里過濾下 "/data"
$ grep "/data" strace.txt | tail -10
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2338.log", {st_mode=S_IFREG|0644, st_size=6509, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2339.log", {st_mode=S_IFREG|0644, st_size=6402, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2340.log", {st_mode=S_IFREG|0644, st_size=6509, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2341.log", {st_mode=S_IFREG|0644, st_size=6509, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2342.log", {st_mode=S_IFREG|0644, st_size=6970, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2343.log", {st_mode=S_IFREG|0644, st_size=6509, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2344.log", {st_mode=S_IFREG|0644, st_size=6402, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2345.log",  <unfinished ...>
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2346.log", {st_mode=S_IFREG|0644, st_size=7756, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 19562] newfstatat(AT_FDCWD, "/data/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6974/fs/data/log/monitor/snaps/20211010/ps-2347.log", Process 3895 detached
$ grep "/data" strace.txt > data.txt
# 合并且排序,自行用腳本分析下哪些文件操作多
$ cat data.txt | awk -F '"' '{print $2}' | sort | uniq -c | sort -n > data-sorted.txt

7)如果負載太高導致機器完全無法操作怎么辦??

此情況下建議直接重啟。

3、磁盤爆滿

1)什么情況下磁盤可能會爆滿 ??

kubelet 有 gc 和驅逐機制,通過以下參數:

  • --image-gc-high-threshold
  • --image-gc-low-threshold
  • --eviction-hard,?--eviction-soft
  • --eviction-minimum-reclaim

控制 kubelet 的 gc 和驅逐策略來釋放磁盤空間,如果配置正確的情況下,磁盤一般不會爆滿。

通常導致爆滿的原因可能是配置不正確或者節點上有其它非 K8S 管理的進程在不斷寫數據到磁盤占用大量空間導致磁盤爆滿。

2)磁盤爆滿會有什么影響 ??

影響 K8S 運行我們主要關注 kubelet 和容器運行時這兩個最關鍵的組件,它們所使用的目錄通常不一樣:

  • kubelet 一般不會單獨掛盤,直接使用系統磁盤,因為通常占用空間不會很大;
  • 容器運行時單獨掛盤的場景比較多,一般情況下會單獨掛盤。

當磁盤爆滿的時候我們也要看 kubelet 和 容器運行時使用的目錄是否在這個磁盤,通過?df?命令可以查看磁盤掛載點。

3)容器運行時使用的目錄所在磁盤爆滿?

如果容器運行時使用的目錄所在磁盤空間爆滿,可能會造成容器運行時無響應,比如 docker,執行 docker 相關的命令一直 hang 住, kubelet 日志也可以看到 PLEG unhealthy,因為 CRI 調用 timeout,當然也就無法創建或銷毀容器,通常表現是 Pod 一直 ContainerCreating 或 一直 Terminating。

docker 默認使用的目錄主要有:

  • /var/run/docker: 用于存儲容器運行狀態,通過 dockerd 的?--exec-root?參數指定。
  • /var/lib/docker: 用于持久化容器相關的數據,比如容器鏡像、容器可寫層數據、容器標準日志輸出、通過 docker 創建的 volume 等

Pod 啟動可能報類似下面的事件:

  Warning  FailedCreatePodSandBox    53m                 kubelet, 172.22.0.44  Failed create pod sandbox: rpc error: code = DeadlineExceeded desc = context deadline exceeded
  Warning  FailedCreatePodSandBox  2m (x4307 over 16h)  kubelet, 10.179.80.31  (combined from similar events): Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "apigateway-6dc48bf8b6-l8xrw": Error response from daemon: mkdir /var/lib/docker/aufs/mnt/1f09d6c1c9f24e8daaea5bf33a4230de7dbc758e3b22785e8ee21e3e3d921214-init: no space left on device
  Warning  Failed   5m1s (x3397 over 17h)  kubelet, ip-10-0-151-35.us-west-2.compute.internal  (combined from similar events): Error: container create failed: container_linux.go:336: starting container process caused "process_linux.go:399: container init caused \"rootfs_linux.go:58: mounting \\\"/sys\\\" to rootfs \\\"/var/lib/dockerd/storage/overlay/051e985771cc69f3f699895a1dada9ef6483e912b46a99e004af7bb4852183eb/merged\\\" at \\\"/var/lib/dockerd/storage/overlay/051e985771cc69f3f699895a1dada9ef6483e912b46a99e004af7bb4852183eb/merged/sys\\\" caused \\\"no space left on device\\\"\""

Pod 刪除可能報類似下面的事件:

Normal  Killing  39s (x735 over 15h)  kubelet, 10.179.80.31  Killing container with id docker://apigateway:Need to kill Pod

4)kubelet 使用的目錄所在磁盤爆滿?

如果 kubelet 使用的目錄所在磁盤空間爆滿(通常是系統盤),新建 Pod 時連 Sandbox 都無法創建成功,因為 mkdir 將會失敗,通常會有類似這樣的 Pod 事件:

  Warning  UnexpectedAdmissionError  44m                 kubelet, 172.22.0.44  Update plugin resources failed due to failed to write checkpoint file "kubelet_internal_checkpoint": write /var/lib/kubelet/device-plugins/.728425055: no space left on device, which is unexpected.

kubelet 默認使用的目錄是?/var/lib/kubelet, 用于存儲插件信息、Pod 相關的狀態以及掛載的 volume (比如?emptyDir,?ConfigMap,?Secret),通過 kubelet 的?--root-dir?參數指定。

5)如何分析磁盤占用 ??

如果運行時使用的是 Docker,請參考:分析 Docker 磁盤占用-CSDN博客

6)如何恢復 ??

如果容器運行時使用的 Docker,我們無法直接重啟 dockerd 來釋放一些空間,因為磁盤爆滿后 dockerd 無法正常響應,停止的時候也會卡住。我們需要先手動清理一點文件騰出空間好讓 dockerd 能夠停止并重啟。

可以手動刪除一些 docker 的 log 文件或可寫層文件,通常刪除 log:

$ cd /var/lib/docker/containers
$ du -sh * # 找到比較大的目錄
$ cd dda02c9a7491fa797ab730c1568ba06cba74cecd4e4a82e9d90d00fa11de743c
$ cat /dev/null > dda02c9a7491fa797ab730c1568ba06cba74cecd4e4a82e9d90d00fa11de743c-json.log.9 # 刪除log文件

注意:?使用?cat /dev/null >?方式刪除而不用?rm,因為用 rm 刪除的文件,docker 進程可能不會釋放文件,空間也就不會釋放;log 的后綴數字越大表示越久遠,先刪除舊日志。

然后將該 node 標記不可調度,并將其已有的 pod 驅逐到其它節點,這樣重啟 dockerd 就會讓該節點的 pod 對應的容器刪掉,容器相關的日志(標準輸出)與容器內產生的數據文件(沒有掛載 volume, 可寫層)也會被清理:

kubectl drain <node-name>

重啟 dockerd:

systemctl restart dockerd
# or systemctl restart docker

等重啟恢復,pod 調度到其它節點,排查磁盤爆滿原因并清理和規避,然后取消節點不可調度標記:

kubectl uncordon <node-name>

7)如何規避 ??

正確配置 kubelet gc 和 驅逐相關的參數,即便到達爆滿地步,此時節點上的 pod 也都早就自動驅逐到其它節點了,不會存在 Pod 一直 ContainerCreating 或 Terminating 的問題。

4、PID 爆滿

1)如何判斷 PID 耗盡?

首先要確認當前的 PID 限制,檢查全局 PID 最大限制:

cat /proc/sys/kernel/pid_max

也檢查下線程數限制:

cat /proc/sys/kernel/threads-max

再檢查下當前用戶是否還有?ulimit?限制最大進程數。

確認當前實際 PID 數量,檢查當前用戶的 PID 數量:

ps -eLf | wc -l

如果發現實際 PID 數量接近最大限制說明 PID 就可能會爆滿導致經常有進程無法啟動,低版本內核可能報錯:?Cannot allocate memory,這個報錯信息不準確,在內核 4.1 以后改進了:?fork: report pid reservation failure properly · torvalds/linux@35f71bc · GitHub

2)如何解決?

臨時調大 PID 和線程數限制:

echo 65535 > /proc/sys/kernel/pid_max
echo 65535 > /proc/sys/kernel/threads-max

永久調大 PID 和線程數限制:

echo "kernel.pid_max=65535 " >> /etc/sysctl.conf && sysctl -p
echo "kernel.threads-max=65535 " >> /etc/sysctl.conf && sysctl -p

k8s 1.14 支持了限制 Pod 的進程數量:?Process ID Limiting for Stability Improvements in Kubernetes 1.14 | Kubernetes

參考:如何限制pod 進程/線程數量?-CSDN博客

5、判斷 arp_cache 是否溢出?

node 內核日志會有有下面的報錯:

arp_cache: neighbor table overflow!

查看當前 arp 記錄數:

$ arp -an | wc -l
1335

查看 arp gc 閥值:

$ sysctl -a | grep gc_thresh
net.ipv4.neigh.default.gc_thresh1 = 128
net.ipv4.neigh.default.gc_thresh2 = 512
net.ipv4.neigh.default.gc_thresh3 = 1024
net.ipv6.neigh.default.gc_thresh1 = 128
net.ipv6.neigh.default.gc_thresh2 = 512
net.ipv6.neigh.default.gc_thresh3 = 1024

當前 arp 記錄數接近?gc_thresh3?比較容易 overflow,因為當 arp 記錄達到?gc_thresh3?時會強制觸發 gc 清理,當這時又有數據包要發送,并且根據目的 IP 在 arp cache 中沒找到 mac 地址,這時會判斷當前 arp cache 記錄數加 1 是否大于?gc_thresh3,如果沒有大于就會 時就會報錯:?arp_cache: neighbor table overflow!

解決方案?

調整節點內核參數,將 arp cache 的 gc 閥值調高 (/etc/sysctl.conf):

net.ipv4.neigh.default.gc_thresh1 = 80000
net.ipv4.neigh.default.gc_thresh2 = 90000
net.ipv4.neigh.default.gc_thresh3 = 100000

分析是否只是部分業務的 Pod 的使用場景需要節點有比較大的 arp 緩存空間。

如果不是,就需要調整所有節點內核參數。

如果是,可以將部分 Node 打上標簽,比如:

kubectl label node host1 arp_cache=large

然后用 nodeSelector 或 nodeAffnity 讓這部分需要內核有大 arp_cache 容量的 Pod 只調度到這部分節點,推薦使用 nodeAffnity,yaml 示例:

  template:spec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: arp_cacheoperator: Invalues:- large

參考:K8S node ARP 表爆滿 如何優化-CSDN博客

6、inotify 資源耗盡

inotify詳解參考:linux inotify 資源詳解-CSDN博客

1)inotify 耗盡的危害?

如果 inotify 資源耗盡,kubelet 創建容器將會失敗:

Failed to watch directory "/sys/fs/cgroup/blkio/system.slice": inotify_add_watch /sys/fs/cgroup/blkio/system.slice/var-lib-kubelet-pods-d111600d\x2dcdf2\x2d11e7\x2d8e6b\x2dfa163ebb68b9-volumes-kubernetes.io\x7esecret-etcd\x2dcerts.mount: no space left on device

2)查看 inotify watch 的限制?

每個 linux 進程可以持有多個 fd,每個 inotify 類型的 fd 可以 watch 多個目錄,每個用戶下所有進程 inotify 類型的 fd 可以 watch 的總目錄數有個最大限制,這個限制可以通過內核參數配置:?fs.inotify.max_user_watches

查看最大 inotify watch 數:

$ cat /proc/sys/fs/inotify/max_user_watches
8192

3)查看進程的 inotify watch 情況?

使用下面的腳本查看當前有 inotify watch 類型 fd 的進程以及每個 fd watch 的目錄數量,降序輸出,帶總數統計:

#!/usr/bin/env bash
#
# Copyright 2019 (c) roc
#
# This script shows processes holding the inotify fd, alone with HOW MANY directories each inotify fd watches(0 will be ignored).
total=0
result="EXE PID FD-INFO INOTIFY-WATCHES\n"
while read pid fd; do \exe="$(readlink -f /proc/$pid/exe || echo n/a)"; \fdinfo="/proc/$pid/fdinfo/$fd" ; \count="$(grep -c inotify "$fdinfo" || true)"; \if [ $((count)) != 0 ]; thentotal=$((total+count)); \result+="$exe $pid $fdinfo $count\n"; \fi
done <<< "$(lsof +c 0 -n -P -u root|awk '/inotify$/ { gsub(/[urw]$/,"",$4); print $2" "$4 }')" && echo "total $total inotify watches" && result="$(echo -e $result|column -t)\n" && echo -e "$result" | head -1 && echo -e "$result" | sed "1d" | sort -k 4rn;

示例輸出:

total 7882 inotify watches
EXE                                         PID    FD-INFO                INOTIFY-WATCHES
/usr/local/qcloud/YunJing/YDEyes/YDService  25813  /proc/25813/fdinfo/8   7077
/usr/bin/kubelet                            1173   /proc/1173/fdinfo/22   665
/usr/bin/ruby2.3                            13381  /proc/13381/fdinfo/14  54
/usr/lib/policykit-1/polkitd                1458   /proc/1458/fdinfo/9    14
/lib/systemd/systemd-udevd                  450    /proc/450/fdinfo/9     13
/usr/sbin/nscd                              7935   /proc/7935/fdinfo/3    6
/usr/bin/kubelet                            1173   /proc/1173/fdinfo/28   5
/lib/systemd/systemd                        1      /proc/1/fdinfo/17      4
/lib/systemd/systemd                        1      /proc/1/fdinfo/18      4
/lib/systemd/systemd                        1      /proc/1/fdinfo/26      4
/lib/systemd/systemd                        1      /proc/1/fdinfo/28      4
/usr/lib/policykit-1/polkitd                1458   /proc/1458/fdinfo/8    4
/usr/local/bin/sidecar-injector             4751   /proc/4751/fdinfo/3    3
/usr/lib/accountsservice/accounts-daemon    1178   /proc/1178/fdinfo/7    2
/usr/local/bin/galley                       8228   /proc/8228/fdinfo/10   2
/usr/local/bin/galley                       8228   /proc/8228/fdinfo/9    2
/lib/systemd/systemd                        1      /proc/1/fdinfo/11      1
/sbin/agetty                                1437   /proc/1437/fdinfo/4    1
/sbin/agetty                                1440   /proc/1440/fdinfo/4    1
/usr/bin/kubelet                            1173   /proc/1173/fdinfo/10   1
/usr/local/bin/envoy                        4859   /proc/4859/fdinfo/5    1
/usr/local/bin/envoy                        5427   /proc/5427/fdinfo/5    1
/usr/local/bin/envoy                        6058   /proc/6058/fdinfo/3    1
/usr/local/bin/envoy                        6893   /proc/6893/fdinfo/3    1
/usr/local/bin/envoy                        6950   /proc/6950/fdinfo/3    1
/usr/local/bin/galley                       8228   /proc/8228/fdinfo/3    1
/usr/local/bin/pilot-agent                  3819   /proc/3819/fdinfo/5    1
/usr/local/bin/pilot-agent                  4244   /proc/4244/fdinfo/5    1
/usr/local/bin/pilot-agent                  5901   /proc/5901/fdinfo/3    1
/usr/local/bin/pilot-agent                  6789   /proc/6789/fdinfo/3    1
/usr/local/bin/pilot-agent                  6808   /proc/6808/fdinfo/3    1
/usr/local/bin/pilot-discovery              6231   /proc/6231/fdinfo/3    1
/usr/local/bin/sidecar-injector             4751   /proc/4751/fdinfo/5    1
/usr/sbin/acpid                             1166   /proc/1166/fdinfo/6    1
/usr/sbin/dnsmasq                           7572   /proc/7572/fdinfo/8    1

4)調整 inotify watch 限制?

如果看到總 watch 數比較大,接近最大限制,可以修改內核參數調高下這個限制。

臨時調整:

sudo sysctl fs.inotify.max_user_watches=524288

永久生效:

echo "fs.inotify.max_user_watches=524288" >> /etc/sysctl.conf && sysctl -p

打開 inotify_add_watch 跟蹤,進一步 debug inotify watch 耗盡的原因:

echo 1 >> /sys/kernel/debug/tracing/events/syscalls/sys_exit_inotify_add_watch/enable

7、soft lockup (內核軟死鎖)

1)內核報錯?

Oct 14 15:13:05 VM_1_6_centos kernel: NMI watchdog: BUG: soft lockup - CPU#5 stuck for 22s! [runc:[1:CHILD]:2274]

2)原因?

發生這個報錯通常是內核繁忙 (掃描、釋放或分配大量對象),分不出時間片給用戶態進程導致的,也伴隨著高負載,如果負載降低報錯則會消失。

3)什么情況下會導致內核繁忙?

短時間內創建大量進程 (可能是業務需要,也可能是業務bug或用法不正確導致創建大量進程)

4)如何優化?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79529.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79529.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79529.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【QT】QT中的軟鍵盤設計

QT的軟鍵盤設計 1.軟鍵盤制作步驟2.介紹有關函數的使用3.出現的編譯錯誤及解決辦法示例代碼1&#xff1a;按鍵事件實現軟鍵盤現象&#xff1a;示例代碼2&#xff1a;按鍵事件實現軟鍵盤&#xff08;加特殊按鍵&#xff09;現象&#xff1a; 軟鍵盤移植到新的工程的步驟&#xf…

【LaTeX+VSCode本地Win11編譯教程】

LaTeXVSCode本地編譯教程參考視頻&#xff1a; LaTeXVSCode本地編譯教程 下面提供一種Win11的Latex環境配置和設置方案&#xff0c;首先vscode安裝參考博客&#xff1a;【VscodeGit教程】&#xff0c;然后準備安裝Latex相關組件 在 https://miktex.org/download 下載 miktex 并…

2025五一杯數學建模ABC題賽題已出

2025五一杯數學建模ABC題賽題已出 A: B: C:

Springclound常用五大組件及其使用原理

注冊中心Eureka Eureka-Server&#xff1a;就是服務注冊中心&#xff08;可以是一個集群&#xff09;&#xff0c;對外暴露自己的地址。 提供者&#xff1a;啟動后向Eureka注冊自己信息&#xff08;地址&#xff0c;服務名稱等&#xff09;&#xff0c;并且定期進行服務續約 …

Docker —— 隔離的基本操作(2)

Docker —— 隔離的基本操作&#xff08;2&#xff09; unshareunshare 命令詳解基本語法常用選項常用示例實際應用場景注意事項與 Docker 的關系1. 執行命令2. 修改主機名3. 退出命名空間4. 驗證宿主機主機名關鍵原理類比 Docker 容器總結 實戰操作一&#xff08;PID 隔離&…

Java List分頁工具

PageUtil.java import com.google.common.collect.Lists; import com.jd.platform.hotkey.dashboard.common.domain.Page; import org.springframework.util.CollectionUtils;import java.util.ArrayList; import java.util.List;public class PageUtil {/*** 通用分頁工具類*…

中陽策略:如何從K線行為中提取交易邏輯信號?

中陽策略&#xff1a;如何從K線行為中提取交易邏輯信號&#xff1f; 在量化趨勢研究中&#xff0c;中陽形態常被視作市場動能變化的重要標志。它不僅代表價格的強勢上行&#xff0c;更隱含著主力資金換手與情緒轉換的信號。將“中陽”這一結構元素抽象為模型中的“強動能突破”…

Java SE(8)——繼承

1.繼承的概念&作用 在Java中&#xff0c;繼承是面向對象編程的三大基本特性之一&#xff08;還有封裝和多態&#xff09;&#xff0c;允許一個類&#xff08;子類/繼承類&#xff09;繼承另一個類&#xff08;父類/基類&#xff09;的屬性和方法 繼承的核心目的是&#xf…

Python爬蟲(18)反爬攻防戰:動態IP池構建與代理IP實戰指南(突破95%反爬封禁率)

目錄 引言一、背景&#xff1a;為什么代理IP是爬蟲的“第二生命”&#xff1f;1.1 反爬系統的IP檢測三把刀1.2 代理IP的核心價值 二、基礎實戰&#xff1a;快速搭建代理IP系統2.1 免費代理IP的獲取與篩選2.2 代理IP的智能容錯機制 三、高階攻防&#xff1a;突破企業級反爬封鎖3…

LFU算法解析

文章目錄 LFU緩存中關鍵變量的訪問與更新機制1. min_freq - 最小頻率訪問時機更新時機更新示例 2. capacity - 緩存容量訪問時機更新時機訪問示例 3. key_to_node - 鍵到節點的映射訪問時機更新時機更新示例 4. freq_to_dummy - 頻率到鏈表啞節點的映射訪問時機更新時機更新示例…

ByteArrayInputStream 類詳解

ByteArrayInputStream 類詳解 ByteArrayInputStream 是 Java 中用于從字節數組讀取數據的輸入流&#xff0c;位于 java.io 包。它允許將內存中的字節數組當作輸入流來讀取&#xff0c;是處理內存數據的常用工具。 1. 核心特性 內存數據源&#xff1a;從字節數組&#xff08;b…

rvalue引用()

一、先確定基礎:左值(Lvalue)和右值(Rvalue) 理解Rvalue引用,首先得搞清楚左值和右值的概念。 左值(Lvalue):有明確內存地址的表達式,可以取地址。比如變量名、引用等。 復制代碼 int a = 10; // a是左值 int& ref = a; // ref也是左值右值(Rval…

吳恩達深度學習作業 RNN模型——字母級語言模型

一. 簡單復習一下RNN RNN RNN適用于處理序列數據&#xff0c;令是序列的第i個元素&#xff0c;那么就是一個長度為的序列&#xff0c;NLP中最常見的元素是單詞&#xff0c;對應的序列是句子。 RNN使用同一個神經網絡處理序列中的每一個元素。同時&#xff0c;為了表示序列的…

基于python的哈希查表搜索特定文件

Python有hashlib庫&#xff0c;支持多種哈希算法&#xff0c;比如MD5、SHA1、SHA256等。通常SHA256比較安全&#xff0c;但MD5更快&#xff0c;但可能存在碰撞風險&#xff0c;得根據自己需求決定。下面以SHA256做例。 import hashlib import os from typing import Dict, Lis…

idea創建springboot項目無法創建jdk8原因及多種解決方案

idea創建springboot項目無法創建jdk8原因及多種解決方案 提示&#xff1a;幫幫志會陸續更新非常多的IT技術知識&#xff0c;希望分享的內容對您有用。本章分享的是springboot的使用。前后每一小節的內容是存在的有&#xff1a;學習and理解的關聯性。【幫幫志系列文章】&#x…

【C++進階十】多態深度剖析

【C進階十】多態深度剖析 1.多態的概念及條件2.虛函數的重寫3.重寫、重定義、重載區別4.C11新增的override 和final5.抽象類6.虛表指針和虛表6.1什么是虛表指針6.2指向誰調用誰&#xff0c;傳父類調用父類&#xff0c;傳子類調用子類 7.多態的原理8.單繼承的虛表狀態9.多繼承的…

面向網絡安全的開源 大模型-Foundation-Sec-8B

1. Foundation-Sec-8B 整體介紹 Foundation-Sec-8B 是一個專注于網絡安全領域的大型語言模型 (LLM),由思科的基礎人工智能團隊 (Foundation AI) 開發 。它基于 Llama 3.1-8B 架構構建,并通過在一個精心策劃和整理的網絡安全專業語料庫上進行持續預訓練而得到增強 。該模型旨在…

Python爬蟲的基礎用法

Python爬蟲的基礎用法 python爬蟲一般通過第三方庫進行完成 導入第三方庫&#xff08;如import requests &#xff09; requests用于處理http協議請求的第三方庫,用python解釋器中查看是否有這個庫&#xff0c;沒有點擊安裝獲取網站url&#xff08;url一定要解析正確&#xf…

WHAT - Tailwind CSS + Antd = MetisUI組件庫

文章目錄 Tailwind 和 Antd 組件庫MetisUI 組件庫 Tailwind 和 Antd 組件庫 在 WHAT - Tailwind 樣式方案&#xff08;不寫任何自定義樣式&#xff09; 中我們介紹了 Tailwind&#xff0c;至于 Antd 組件庫&#xff0c;我們應該都耳熟能詳&#xff0c;官網地址&#xff1a;htt…

Day 4:牛客周賽Round 91

好久沒寫了&#xff0c;問題還蠻多的。聽說這次是苯環哥哥出題 F題 小苯的因子查詢 思路 考慮求因子個數&#xff0c;用質因數分解&#xff1b;奇數因子只需要去掉質數為2的情況&#xff0c;用除法。 這里有個比較妙的細節是&#xff0c;提前處理出數字x的最小質因數&#xff0…