一文弄懂pod Evicted的狀態(tài)究竟是何人所為
背景
今天發(fā)現(xiàn)好多pod的狀態(tài)都是Evicted,然后我沒有監(jiān)控的權(quán)限,本來想看看grafana上監(jiān)控圖是否出現(xiàn)了特殊情況,無奈沒權(quán)限看。
因?yàn)槲野l(fā)現(xiàn)pod出現(xiàn)大量的Evicted狀態(tài)的時(shí)候,查看pod所在的node節(jié)點(diǎn),距離當(dāng)時(shí)發(fā)生Evicted的時(shí)間已經(jīng)是7小時(shí)之久了。因此可能會(huì)存在一種原因:發(fā)生了Evicted的時(shí)候的確磁盤已經(jīng)超過默認(rèn)的kubelet的資源預(yù)留參數(shù)了。但是問題發(fā)生后,觸發(fā)了閾值,已經(jīng)回收了磁盤空間,導(dǎo)致我看的時(shí)候磁盤空間已經(jīng)恢復(fù)。
在每個(gè) Kubernetes Node節(jié)點(diǎn) 上,kubelet 默認(rèn)根目錄是 /var/lib/kubelet 和 日志目錄 /var/log 保存在節(jié)點(diǎn)的系統(tǒng)分區(qū)上,這個(gè)分區(qū)同時(shí)也會(huì)被Pod的 EmptyDir 類型的 volume、容器日志、鏡像層、容器的可寫層所占用。ephemeral-storage 便是對(duì)系統(tǒng)分區(qū)進(jìn)行管理。
大量的Evicted狀態(tài)的pod
- $ kubectl get po -A -o wide | grep -v "Running"
- NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nsop account-service-pre-master-6db67f5cc-5nrgf 0/1 Evicted 0 103m <none> node2.pre.ayunw.cn <none> <none>
- nsop account-service-pre-master-6db67f5cc-7zbrf 0/1 Evicted 0 103m <none> node2.pre.ayunw.cn <none> <none>
- nsop account-service-pre-master-6db67f5cc-h78hv 0/1 Evicted 0 103m <none> node2.pre.ayunw.cn <none> <none>
- nsop account-service-pre-master-6db67f5cc-jj4xx 0/1 Evicted 0 103m <none> node2.pre.ayunw.cn <none> <none>
- nsop account-service-pre-master-6db67f5cc-jz4cs 0/1 Evicted 0 103m <none> node2.pre.ayunw.cn <none> <none>
- nsop account-service-pre-master-6db67f5cc-km2cz 0/1 Evicted 0 103m <none> node2.pre.ayunw.cn <none> <none>
當(dāng)我們的集群中有太多被驅(qū)逐的 pod 時(shí),這會(huì)導(dǎo)致網(wǎng)絡(luò)負(fù)載。因?yàn)槊總€(gè) pod 即使被驅(qū)逐是連接到網(wǎng)絡(luò)的,并且在云 Kubernetes 集群的情況下,也會(huì)阻塞一個(gè) IP 地址,這可能導(dǎo)致如果您的集群有固定的 IP 地址池,也會(huì)耗盡 IP 地址。此外,當(dāng)我們有太多處于 Evicted 狀態(tài)的 Pod 時(shí),通過運(yùn)行kubectl get pod命令來監(jiān)控 Pod 會(huì)變得很困難,因?yàn)闀?huì)存在非常多的 Evicted Pod。當(dāng)然你可以通過grep等手段過濾掉Evicted狀態(tài)的pod。
查看Evicted的pod的任意一個(gè)node
describe任意一個(gè)pod查看,發(fā)現(xiàn)Warning提示DiskPressure,表示磁盤存在壓力了。
- $ kubectl describe po account-service-pre-master-6db67f5cc-5nrgf -n nsop
- ...
- QoS Class: Burstable
- Node-Selectors: <none>
- Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
- node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
- topology.kubernetes.io/env=pre:NoSchedule
- topology.kubernetes.io/region=bce-gz:NoSchedule
- topology.kubernetes.io/type=appserver:NoSchedule
- topology.kubernetes.io/zone:NoSchedule op=Exists
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 100m default-scheduler Successfully assigned nsop/account-service-pre-master-6db67f5cc-5nrgf to node2.pre.ayunw.cn
- Warning Evicted 100m kubelet, node2.pre.ayunw.cn The node had condition: [DiskPressure].
登錄node2.pre.ayunw.cn查看
- [root@node2-pre-ayunw.cn ~]# df -Th | egrep -v "overlay2|kubernetes|docker"
- Filesystem Type Size Used Avail Use% Mounted on
- devtmpfs devtmpfs 32G 0 32G 0% /dev
- tmpfs tmpfs 32G 0 32G 0% /dev/shm
- tmpfs tmpfs 32G 5.9M 32G 1% /run
- tmpfs tmpfs 32G 0 32G 0% /sys/fs/cgroup
- /dev/vda1 ext4 50G 7.9G 39G 17% /
- /dev/vdb1 xfs 200G 138G 63G 69% /data
- tmpfs tmpfs 6.3G 0 6.3G 0% /run/user/0
發(fā)現(xiàn)還有69%的磁盤空間,似乎也沒有什么問題啊,應(yīng)該磁盤空間也還很充足的。
iostat命令查看磁盤IO
- [root@node2-pre-ayunw.cn ~]# iostat -xk 1 3
- Linux 5.10.8-1.el8.elrepo.x86_64 (node2-pre-ayunw.cn) 08/31/2021 _x86_64_ (32 CPU)
- avg-cpu: %user %nice %system %iowait %steal %idle
- 1.86 0.00 1.77 0.03 0.00 96.34
- Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
- vda 0.02 2.77 0.40 22.43 0.00 2.14 4.57 43.58 1.51 0.75 0.00 24.11 8.09 0.38 0.11
- vdb 0.08 126.81 3.31 519.35 0.00 0.54 0.31 0.43 3.20 0.56 0.07 40.29 4.10 0.47 6.01
- avg-cpu: %user %nice %system %iowait %steal %idle
- 3.09 0.00 3.34 0.03 0.00 93.54
- Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
- vda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- vdb 0.00 51.00 0.00 168.50 0.00 0.00 0.00 0.00 0.00 0.45 0.02 0.00 3.30 0.55 2.80
- avg-cpu: %user %nice %system %iowait %steal %idle
- 2.74 0.00 2.81 0.00 0.00 94.45
- Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
- vda 0.00 3.00 0.00 40.00 0.00 7.00 0.00 70.00 0.00 0.67 0.00 0.00 13.33 1.00 0.30
- vdb 0.00 62.00 0.00 619.50 0.00 7.00 0.00 10.14 0.00 0.58 0.04 0.00 9.99 0.50 3.10
目前似乎也看不到有什么IO壓力 。但是由于我手上沒有監(jiān)控權(quán)限,估計(jì)也是直接就沒有對(duì)pod做監(jiān)控。然后describe的時(shí)候看到問題發(fā)生也是7個(gè)小時(shí)之前的事情了,所以的話這邊猜測(cè)可能是當(dāng)時(shí)已經(jīng)觸發(fā)了kubelet的eviction-hard,然后磁盤已經(jīng)有部分空間被回收了,而且壓力可能也已經(jīng)下去了。
查看node上的日志
查看節(jié)點(diǎn)上kubelet日志和message日志,并沒有任何Evicted的日志被發(fā)現(xiàn)。
- $ tail -500 kubelet.log | grep "Evicted"
- $ tail -500 /var/log/messages | grep "Evicted"
那當(dāng)前情況下就只能臨時(shí)先處理掉這個(gè)Evicted狀態(tài)的pod了
- $ kubectl get po -n nsop --field-selector 'status.phase!=Running' -o json| kubectl delete -f -
因?yàn)槭谴疟P空間的問題,所以想到去檢查一下是否有持續(xù)增長(zhǎng)的目錄。最后排查發(fā)現(xiàn),所有出現(xiàn)Evicted狀態(tài)的pod所處的節(jié)點(diǎn)似乎都有一個(gè)共性:那就是都啟用了skywalking,并且以emptyDir的形式寫日志到本地臨時(shí)存儲(chǔ)中。
目前公司將默認(rèn)的docker目錄和kubelet目錄都改到了/data目錄下,上pod所在的node,到/data/目錄下通過du -sh ./* | grep G命令去查看了一下有好多/data/kubernetes/kubelet/pods/xxx/volumes/kubernetes.io~empty-dir/vol-apm-empty/logs的目錄下存在skywalking-api.log的日志,而且都是輪轉(zhuǎn)的日志,默認(rèn)沒有設(shè)置日志保留時(shí)間。
skywalking-agent的配置文件中默認(rèn)開啟了以下幾個(gè)參數(shù):
- $ egrep -v "^$|^#" agent.config
- agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
- collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
- logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log}
- logging.level=${SW_LOGGING_LEVEL:INFO}
- plugin.mount=${SW_MOUNT_FOLDERS:plugins,activations}
skywalking-agent在emptyDir下的日志
- [root@node2-pre-ayunw.cn vol-apm-empty]# cd logs/
- [root@node2-pre-ayunw.cn logs]# ll
- total 4327672
- -rw-r--r-- 1 root root 260328481 Aug 31 09:43 skywalking-api.log
- -rw-r--r-- 1 root root 314573222 Aug 12 02:56 skywalking-api.log.2021_08_12_02_56_35
- -rw-r--r-- 1 root root 314573394 Aug 13 15:01 skywalking-api.log.2021_08_13_15_01_56
- -rw-r--r-- 1 root root 314574277 Aug 15 03:12 skywalking-api.log.2021_08_15_03_12_26
- -rw-r--r-- 1 root root 314574161 Aug 16 15:21 skywalking-api.log.2021_08_16_15_21_13
- -rw-r--r-- 1 root root 314574334 Aug 18 03:31 skywalking-api.log.2021_08_18_03_31_18
- -rw-r--r-- 1 root root 314572887 Aug 19 15:40 skywalking-api.log.2021_08_19_15_40_22
- -rw-r--r-- 1 root root 314574238 Aug 21 03:44 skywalking-api.log.2021_08_21_03_44_28
- -rw-r--r-- 1 root root 314574144 Aug 22 15:49 skywalking-api.log.2021_08_22_15_49_08
- -rw-r--r-- 1 root root 314573963 Aug 24 03:51 skywalking-api.log.2021_08_24_03_51_28
- -rw-r--r-- 1 root root 314572991 Aug 25 15:54 skywalking-api.log.2021_08_25_15_54_21
- -rw-r--r-- 1 root root 314573321 Aug 27 03:57 skywalking-api.log.2021_08_27_03_57_11
- -rw-r--r-- 1 root root 314572890 Aug 28 16:01 skywalking-api.log.2021_08_28_16_01_26
- -rw-r--r-- 1 root root 314573311 Aug 30 04:05 skywalking-api.log.2021_08_30_04_05_34
我的docker根目錄被更改過,不是默認(rèn)的/var/lib/docker,而是/data/docker。我的k8s的kubelet目錄也是被更改過的,在/data/kubernetes/kubelet。
臨時(shí)解決日志爆滿的兩種方法
- 在K8s-master節(jié)點(diǎn)查看Evicted的pod調(diào)度在哪個(gè)節(jié)點(diǎn),然后到/data/kubernetes/kubelet/pods目錄下去通過du -sh 命令找到目錄占用量大的pod,然后將截圖指出的輪轉(zhuǎn)后(就是帶上時(shí)間2021_08_17這一類)的日志文件刪除
- 直接重新刪除pod,其實(shí)只要是pod重啟后,EmptyDir目錄就會(huì)被刪除掉。
操作步驟
- $ cd /data/kubernetes/kubelet/pods
- $ du -sh ./* | grep G
- 1.3G ./02c9511d-0787-49f1-8c59-0db239baee79
- 1.3G ./079f3ca0-810d-468d-9136-75f3d3235b2d
- 4.8G ./07fc67f7-d46d-4d0c-8f6c-401e14705ae1
- 3.0G ./091594a0-b5ac-45c2-8ad9-7dcfc91c9e55
- 1.8G ./130a1b35-b447-43e1-8802-eb74aefa566c
- 1.2G ./1b257c27-cbaf-49f8-bca3-ceadc467aad6
- 2.8G ./2ec50216-f81e-4e83-922d-14316762dee2
- 7.0G ./321baae6-1efe-4535-8a20-0fdfa6cc3117
- 8.0G ./46680114-11f7-47af-9ee2-347f56592924
- ...
我這里找到了占用7.0G大小的pod,根據(jù)目錄名稱找到pod名字,然后觸發(fā)了這個(gè)pod的cicd,也就相當(dāng)于更新了這個(gè)pod的deployment.yaml,然后apply -f重新生成了一遍這個(gè)pod
- $ docker ps -a | grep "321baae6-1efe-4535-8a20-0fdfa6cc3117"
- a69b2635ba98 registry.ayunw.cn/tsp/msmessagecenter "/startApp.sh" 5 weeks ago Up 5 weeks k8s_msmessagecenter-perf-dev-v1-0-0_msmessagecenter-perf-dev-v1-0-0-7f746b84bf-wb4g5_tsp_321baae6-1efe-4535-8a20-0fdfa6cc3117_0
- c8f2cc0a2737 874552b27b34 "sh -c 'set -ex;mkdi…" 5 weeks ago Exited (0) 5 weeks ago k8s_init-skywalking-agent_msmessagecenter-perf-dev-v1-0-0-7f746b84bf-wb4g5_tsp_321baae6-1efe-4535-8a20-0fdfa6cc3117_0
- c415f52e7489 registry.ayunw.cn/library/k8s.gcr.io/pause:3.2 "/pause" 5 weeks ago Up 5 weeks k8s_POD_msmessagecenter-perf-dev-v1-0-0-7f746b84bf-wb4g5_tsp_321baae6-1efe-4535-8a20-0fdfa6cc3117_0
等pod被完全刪除后查看這個(gè)目錄已經(jīng)消失
- $ du -sh ./* | grep G
- 1.3G ./02c9511d-0787-49f1-8c59-0db239baee79
- 1.3G ./079f3ca0-810d-468d-9136-75f3d3235b2d
- 4.8G ./07fc67f7-d46d-4d0c-8f6c-401e14705ae1
- 3.0G ./091594a0-b5ac-45c2-8ad9-7dcfc91c9e55
- 1.8G ./130a1b35-b447-43e1-8802-eb74aefa566c
- 1.2G ./1b257c27-cbaf-49f8-bca3-ceadc467aad6
- 2.8G ./2ec50216-f81e-4e83-922d-14316762dee2
- 8.0G ./46680114-11f7-47af-9ee2-347f56592924
- ...
永久解決日志保留個(gè)數(shù)方法
- 直接在Dockerfile打鏡像的時(shí)候更改參數(shù)或者提前寫好配置文件然后構(gòu)建鏡像的時(shí)候COPY進(jìn)去
我這里直接改好agent.config參數(shù)然后Dockerfile中COPY進(jìn)去了
- $ cat Dockerfile
- FROM registry.ayunw.cn/library/alpine:3.12.0
- ENV LANG=C.UTF-8 \
- SKYWLKING_AGENT_VERSION=8.6.0
- RUN set -eux && mkdir -p /opt/skywalking/agent \
- && apk add wget \
- && wget https://downloads.apache.org/skywalking/${SKYWLKING_AGENT_VERSION}/apache-skywalking-apm-es7-${SKYWLKING_AGENT_VERSION}.tar.gz -P /tmp/ \
- && cd /tmp && tar zxf apache-skywalking-apm-es7-${SKYWLKING_AGENT_VERSION}.tar.gz \
- && mv /tmp/apache-skywalking-apm-bin-es7/agent/* /opt/skywalking/agent \
- && rm -f /opt/skywalking/agent/optional-plugins/apm-spring-annotation-plugin-8.6.0.jar /opt/skywalking/agent/plugins/thrift-plugin-8.6.0.jar \
- && mv /opt/skywalking/agent/plugins/thrift-plugin-8.6.0.jar /tmp/thrift-plugin-8.6.0.jar \
- && cp -r /opt/skywalking/agent/optional-plugins/* /opt/skywalking/agent/plugins/ \
- && unset export \
- && rm -rf /tmp/* /opt/skywalking/agent/config/agent.config
- COPY agent.config /opt/skywalking/agent/config/
- WORKDIR /
- $ egrep -v "^$|^#" agent.config
- agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
- collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
- logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log}
- logging.level=${SW_LOGGING_LEVEL:INFO}
- plugin.mount=${SW_MOUNT_FOLDERS:plugins,activations}
- # 以下參數(shù)是我更改后的,表示日志保留個(gè)數(shù)為3個(gè)
- logging.max_history_files=${SW_LOGGING_MAX_HISTORY_FILES:3}
其實(shí)agent.config文件中是有l(wèi)ogging.max_history_files=${SW_LOGGING_MAX_HISTORY_FILES:-1}這一行的,但是默認(rèn)被注釋掉了。我這里將它打開,然后將-1改成了3。這行配置是JAVA中的寫法,意思是默認(rèn)是-1表示"最大歷史日志文件保留個(gè)數(shù)",而-1則表示不設(shè)置最大歷史日志文件保留,也就是一直輪轉(zhuǎn),不會(huì)做日志清理。參數(shù)意思可以參考skywalking官網(wǎng)。
然后重新構(gòu)建這個(gè)skywalking-agent鏡像,在deployment中引用即可。
- $ cat deployment.yaml
- apiVersion: apps/v1
- kind: Deployment
- ...
- dnsPolicy: ClusterFirst
- terminationGracePeriodSeconds: 10
- serviceAccountName: default
- imagePullSecrets:
- - name: registry-auth-ayunw-cn
- initContainers:
- - name: init-skywalking-agent
- image: "registry.ayunw.cn/library/skywalking-agent:33-ac402d20"
- command:
- - 'sh'
- - '-c'
- - 'set -ex;mkdir -p /skywalking/agent;cp -r /opt/skywalking/agent/* /skywalking/agent;'
- volumeMounts:
- - name: vol-apm-empty
- mountPath: /skywalking/agent
- containers:
- - name: demo-hello-pre-master
- image: "registry.ayunw.cn/paas/demo-hello:537-c87b6177"
- ...
- volumeMounts:
- - name: vol-apm-empty
- mountPath: /skywalking/agent
- volumes:
- - name: vol-apm-empty
- emptyDir: {}
其實(shí)這里的磁盤DiskPressure目前只能大概排查到skywalking導(dǎo)致,但沒有監(jiān)控的情況下并不能百分百確認(rèn)就是skywalking引起,因此如果需要更精準(zhǔn)的定位這個(gè)問題,還需要通過監(jiān)控等手段去排查。如果各位有更好的解決Evicted狀態(tài)的pod這種問題的方法,也歡迎后臺(tái)回復(fù),一起交流。
本文轉(zhuǎn)載自微信公眾號(hào)「運(yùn)維開發(fā)故事」
【編輯推薦】