一、工作負載狀態異常定位方法
工作負載狀態異常時,建議先查看Pod的事件以便于確定導致異常的初步原因,再參照下表中的內容針對性解決問題。
排查思路列表
| 事件信息 | 實例狀態 | 處理措施 |
|---|---|---|
| 實例調度失敗 | Pending | 請參考工作負載異常:實例調度失敗 |
| 拉取鏡像失敗 | ImagePullBackOff | 請參考工作負載異常:實例拉取鏡像失敗 |
| 啟動容器失敗 | CreateContainerErrorCrashLoopBackOff | 請參考工作負載異常:啟動容器失敗 |
| 實例狀態為“Evicted”,pod不斷被驅逐 | Evicted | 請參考工作負載異常:實例驅逐異常(Evicted) |
| 實例掛卷失敗 | Pending | 請參考工作負載異常:存儲卷無法掛載或掛載超時 |
| 實例狀態一直為“創建中” | Creating | 請參考工作負載異常:一直處于創建中 |
| 實例狀態一直為“結束中” | Terminating | 請參考工作負載異常:結束中,解決Terminating狀態的Pod刪不掉的問題 |
| 實例狀態為“已停止” | Stopped | 請參考工作負載異常:已停止 |
Pod事件查看方法
Pod的事件可以使用kubectl describe pod podname命令查看,或在CCE控制臺,工作負載詳情頁面中查看。
$ kubectl describe pod prepare-58bd7bdf9-fthrp...Events:Type Reason Age From MessageWarning FailedScheduling 49s default-scheduler 0/2 nodes are available: 2 Insufficient cpu.Warning FailedScheduling 49s default-scheduler 0/2 nodes are available: 2 Insufficient cpu.
查看Pod事件


二、工作負載異常:實例調度失敗
問題定位
當Pod狀態為“Pending”,事件中出現“實例調度失敗”的信息時,可根據具體事件信息確定具體問題原因。事件查看方法請參見工作負載狀態異常定位方法。
排查思路
根據具體事件信息確定具體問題原因,如下表所示。
實例調度失敗
| 事件信息 | 問題原因與解決方案 |
|---|---|
| no nodes available to schedule pods. | 集群中沒有可用的節點。排查項一:集群內是否無可用節點 |
| 0/2 nodes are available: 2 Insufficient cpu.0/2 nodes are available: 2 Insufficient memory. | 節點資源(CPU、內存)不足。排查項二:節點資源(CPU、內存等)是否充足 |
| 0/2 nodes are available: 1 node(s) didn't match node selector, 1 node(s) didn't match pod affinity rules, 1 node(s) didn't match pod affinity/anti-affinity. | 節點與Pod親和性配置互斥,沒有滿足Pod要求的節點。排查項三:檢查工作負載的親和性配置 |
| 0/2 nodes are available: 2 node(s) had volume node affinity conflict. | Pod掛載云硬盤存儲卷與節點不在同一個可用區。排查項四:掛載的存儲卷與節點是否處于同一可用區 |
| 0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate. | 節點存在污點Tanits,而Pod不能容忍這些污點,所以不可調度。排查項五:檢查Pod污點容忍情況 |
| 0/7 nodes are available: 7 Insufficient ephemeral-storage. | 節點臨時存儲不足。排查項六:檢查臨時卷使用量 |
| 0/1 nodes are available: 1 everest driver not found at node | 節點上everest-csi-driver不在running狀態。排查項七:檢查everest插件是否工作正常。 |
| Failed to create pod sandbox: ...Create more free space in thin pool or use dm.min_free_space option to change behavior | 節點thinpool空間不足。排查項八:檢查節點thinpool空間是否充足。 |
排查項一:集群內是否無可用節點
登錄CCE控制臺,檢查節點狀態是否為可用。或使用如下命令查看節點狀態是否為Ready。
$ kubectl get nodeNAME STATUS ROLES AGE VERSION192.168.0.37 Ready 21d v1.19.10-r1.0.0-source-121-gb9675686c54267192.168.0.71 Ready 21d v1.19.10-r1.0.0-source-121-gb9675686c54267
如果狀態都為不可用(Not Ready),則說明集群中無可用節點。
解決方案:
- 新增節點,若工作負載未設置親和策略,pod將自動遷移至新增的可用節點,確保業務正常。
- 排查不可用節點問題并修復,排查修復方法請參見集群可用,但節點狀態為“不可用”?。
- 重置不可用的節點。
排查項二:節點資源(CPU、內存等)是否充足
0/2 nodes are available: 2 Insufficient cpu. CPU不足。
0/2 nodes are available: 2 Insufficient memory. 內存不足。
當“實例資源的申請量”超過了“實例所在節點的可分配資源總量”時,節點無法滿足實例所需資源要求導致調度失敗。
如果節點可分配資源小于Pod的申請量,則節點無法滿足實例所需資源要求導致調度失敗。
解決方案:
資源不足的情況主要解決辦法是擴容,建議在集群中增加節點數量。
排查項三:檢查工作負載的親和性配置
當親和性配置出現如下互斥情況時,也會導致實例調度失敗:
例如:
workload1、workload2設置了工作負載間的反親和,如workload1部署在Node1,workload2部署在Node2。
workload3部署上線時,既希望與workload2親和,又希望可以部署在不同節點如Node1上,這就造成了工作負載親和與節點親和間的互斥,導致最終工作負載部署失敗。
0/2 nodes are available: 1 node(s) didn't match node selector , 1 node(s) didn't match pod affinity rules , 1 node(s) didn't match pod affinity/anti-affinity .
- node selector 表示節點親和不滿足。
- pod affinity rules 表示Pod親和沒不滿足。
- pod affinity/anti-affinity 表示Pod親和/反親和沒不滿足。
解決方案:
- 在設置“工作負載間的親和性”和“工作負載和節點的親和性”時,需確保不要出現互斥情況,否則工作負載會部署失敗。
- 若工作負載配置了節點親和性,需確保親和的節點標簽中supportContainer設置為true,否則會導致pod無法調動到節點上,查看事件提示如下錯誤信息:
- No nodes are available that match all of the following predicates: MatchNode Selector, NodeNotSupportsContainer
節點標簽為false時將會調度失敗
排查項四:掛載的存儲卷與節點是否處于同一可用區
0/2 nodes are available: 2 node(s) had volume node affinity conflict. 存儲卷與節點之間存在親和性沖突,導致無法調度。
這是因為云硬盤不能跨可用區掛載到節點。例如云硬盤存儲卷在可用區1,節點在可用區2,則會導致無法調度。
CCE中創建云硬盤存儲卷,默認帶有親和性設置,如下所示。
kind: PersistentVolumeapiVersion: v1metadata:name: pvc-c29bfac7-efa3-40e6-b8d6-229d8a5372ac
spec:...
nodeAffinity:required:nodeSelectorTerms:matchExpressions:key: failure-domain.beta.kubernetes.io/zoneoperator: Invalues:cn-gz1a
解決方案:
重新創建存儲卷,可用區選擇與節點同一分區,或重新創建工作負載,存儲卷選擇自動分配。
排查項五:檢查Pod污點容忍情況
0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate. 是因為節點打上了污點,不允許Pod調度到節點上。
查看節點的上污點的情況。如下則說明節點上存在污點。
$ kubectl describe node 192.168.0.37Name: 192.168.0.37...Taints: key1=value1:NoSchedule...
在某些情況下,系統會自動給節點添加一個污點。當前內置的污點包括:
- node.kubernetes.io/not-ready:節點未準備好。
- node.kubernetes.io/unreachable:節點控制器訪問不到節點。
- node.kubernetes.io/memory-pressure:節點存在內存壓力。
- node.kubernetes.io/disk-pressure:節點存在磁盤壓力,此情況表明節點上用于存儲鏡像的磁盤空間已滿,需要清理鏡像,或擴容磁盤。
- node.kubernetes.io/pid-pressure:節點的 PID 壓力,此情況下您可通過修改節點進程 ID數量上限kernel.pid_max進行解決。
- node.kubernetes.io/network-unavailable:節點網絡不可用。
- node.kubernetes.io/unschedulable:節點不可調度。
- node.cloudprovider.kubernetes.io/uninitialized:如果kubelet啟動時指定了一個“外部”云平臺驅動, 它將給當前節點添加一個污點將其標志為不可用。在cloud-controller-manager初始化這個節點后,kubelet將刪除這個污點。
解決方案:
要想把Pod調度到這個節點上,有兩種方法:
- 若該污點為用戶自行添加,可考慮刪除節點上的污點。若該污點為系統自動添加,解決相應問題后污點會自動刪除。
- Pod的定義中容忍這個污點,如下所示。
apiVersion: v1kind: Podmetadata:name: nginxspec:containers:name: nginximage: nginx:alpinetolerations:key: "key1"operator: "Equal"value: "value1"effect: "NoSchedule
排查項六:檢查臨時卷使用量
0/7 nodes are available: 7 Insufficient ephemeral-storage. 節點臨時存儲不足。
檢查Pod是否限制了臨時卷的大小,如下所示,當應用程序需要使用的量超過節點已有容量時會導致無法調度,修改臨時卷限制或擴容節點磁盤可解決此問題。
apiVersion: v1kind: Podmetadata:name: frontendspec:containers:name: app
image: images.my-company.example/app:v4
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
volumeMounts:name: ephemeral
mountPath: "/tmp"
volumes:name: ephemeral
emptyDir: {}
排查項七:檢查everest插件是否工作正常。
0/1 nodes are available: 1 everest driver not found at node 。集群everest插件的everest-csi-driver 在節點上未正常啟動。
檢查kube-system命名空間下名為everest-csi-driver的守護進程,查看對應Pod是否正常啟動,若未正常啟動,刪除該Pod,守護進程會重新拉起該Pod。
排查項八:檢查節點thinpool空間是否充足。
節點在創建時會綁定一個100G的docker專用數據盤。若數據盤空間不足,將導致實例無法正常創建。
方案一
您可以執行以下命令清理未使用的Docker鏡像:
docker system prune -a
說明
該命令會把暫時沒有用到的Docker鏡像都刪除,執行命令前請確認。
方案二
或者您也可以選擇擴容磁盤,具體步驟如下:
步驟 1 在EVS界面擴容數據盤。
步驟 2 登錄CCE控制臺,進入集群,在左側選擇“節點管理”,單擊節點后的“同步云服務器”。
步驟 3 登錄目標節點。
步驟 4 使用lsblk命令查看節點塊設備信息。
這里存在兩種情況,根據容器存儲Rootfs而不同。
Overlayfs,沒有單獨劃分thinpool,在dockersys空間下統一存儲鏡像相關數據。
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk└─sda1 8:1 0 50G 0 part /sdb 8:16 0 200G 0 disk├─vgpaas-dockersys 253:0 0 90G 0 lvm /var/lib/docker # docker使用的空間└─vgpaas-kubernetes 253:1 0 10G 0 lvm /mnt/paas/kubernetes/kubelet # kubernetes使用的空間
在節點上執行如下命令,將新增的磁盤容量加到dockersys盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/dockersysresize2fs /dev/vgpaas/dockersys
Devicemapper,單獨劃分了thinpool存儲鏡像相關數據。
#lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk└─sda1 8:1 0 50G 0 part /sdb 8:16 0 200G 0 disk├─vgpaas-dockersys 253:0 0 18G 0 lvm /var/lib/docker├─vgpaas-thinpool_tmeta 253:1 0 3G 0 lvm│ └─vgpaas-thinpool 253:3 0 67G 0 lvm # thinpool空間│ ...├─vgpaas-thinpool_tdata 253:2 0 67G 0 lvm│ └─vgpaas-thinpool 253:3 0 67G 0 lvm│ ...└─vgpaas-kubernetes 253:4 0 10G 0 lvm /mnt/paas/kubernetes/kubelet
在節點上執行如下命令,將新增的磁盤容量加到thinpool盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/thinpool
在節點上執行如下命令,將新增的磁盤容量加到dockersys盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/dockersysresize2fs /dev/vgpaas/dockersys
三、工作負載異常:實例拉取鏡像失敗
問題定位
當Pod狀態為“ImagePullBackOff”,說明實例拉取鏡像失敗。
排查思路
根據具體事件信息確定具體問題原因,如下表所示。
實例拉取鏡像失敗
| 事件信息 | 問題原因與解決方案 |
|---|---|
| Failed to pull image "xxx": rpc error: code = Unknown desc = Error response from daemon: Get xxx: denied: You may not login yet | 沒有登錄鏡像倉庫,無法拉取鏡像。排查項一:kubectl創建工作負載時未指定imagePullSecret |
| Failed to pull image "nginx:v1.1": rpc error: code = Unknown desc = Error response from daemon: Get //registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host | 鏡像地址配置有誤找不到鏡像導致失敗。排查項二:填寫的鏡像地址錯誤(使用第三方鏡像時)排查項三:使用錯誤的密鑰(使用第三方鏡像時) |
| Failed to pull image "docker.io/bitnami/nginx:1.22.0-debian-11-r3": rpc error: code = Unknown desc = Error response from daemon: Get //registry-1.docker.io/v2/: net/ http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) |
無法連接鏡像倉庫,網絡不通。排查項七:無法連接鏡像倉庫 |
| Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "nginx-6dc48bf8b6-l8xrw": Error response from daemon: mkdir xxxxx: no space left on device | 磁盤空間不足。排查項四:節點磁盤空間不足 |
| Failed to pull image "xxx": rpc error: code = Unknown desc = error pulling image configuration: xxx x509: certificate signed by unknown authority | 從第三方倉庫下載鏡像時,第三方倉庫使用了非知名或者不安全的證書.排查項五:遠程鏡像倉庫使用非知名或不安全的證書 |
| Failed to pull image "XXX": rpc error: code = Unknown desc = context canceled | 鏡像體積過大。排查項六:鏡像過大導致失敗 |
| Failed to pull image "docker.io/bitnami/nginx:1.22.0-debian-11-r3": rpc error: code = Unknown desc = Error response from daemon: Get //registry-1.docker.io/v2/: net/ http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) |
排查項七:無法連接鏡像倉庫 |
| ERROR: toomanyrequests: Too Many Requests.或you have reached your pull rate limit, you may increase the limit by authenticating an upgrading | 由于拉取鏡像次數達到上限而被限速。排查項八:拉取公共鏡像達上限 |
排查思路


排查項一:kubectl創建工作負載時未指定imagePullSecret
當工作負載狀態異常并顯示“實例拉取鏡像失敗”的K8s事件時,請排查yaml文件中是否存在imagePullSecrets字段。
排查事項:
- 當Pull SWR容器鏡像倉庫的鏡像時,name參數值需固定為default-secret。
apiVersion: extensions/v1beta1kind: Deploymentmetadata:name: nginxspec:replicas: 1selector:matchLabels:app: nginxstrategy:type: RollingUpdatetemplate:metadata:labels:app: nginxspec:containers:image: nginx
imagePullPolicy: Always
name: nginx
imagePullSecrets:name: default-secret
- Pull第三方鏡像倉庫的鏡像時,需設置為創建的secret名稱。
kubectl創建工作負載拉取第三方鏡像時,需指定的imagePullSecret字段,name表示pull鏡像時的secret名稱。
排查項二:填寫的鏡像地址錯誤(使用第三方鏡像時)
CCE支持拉取第三方鏡像倉庫中的鏡像來創建工作負載。
在填寫第三方鏡像的地址時,請參照要求的格式來填寫。鏡像地址格式為:ip:port/path/name:version或name:version,若沒標注版本號則默認版本號為latest。
- 若是私有倉庫,請填寫ip:port/path/name:version。
- 若是docker開源倉庫,請填寫name:version,例如nginx:latest。
第三方鏡像


鏡像地址配置有誤找不到鏡像導致失敗,Kubernetes Event中提示如下信息:
Failed to pull image "nginx:v1.1": rpc error: code = Unknown desc = Error response from daemon: Get //registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host
解決方案:
可編輯yaml修改鏡像地址,也可在工作負載詳情頁面更新升級頁簽單擊更換鏡像。
排查項三:使用錯誤的密鑰(使用第三方鏡像時)
通常第三方鏡像倉庫都必須經過認證(帳號密碼)才可以訪問,而CCE中容器拉取鏡像是使用密鑰認證方式,這就要求在拉取鏡像前必須先創建鏡像倉庫的密鑰。
解決方案:
若您的密鑰錯誤將會導致鏡像拉取失敗,請重新獲取密鑰。
排查項四:節點磁盤空間不足
新建節點會給節點綁定一個100G的docker專用數據盤。若數據盤空間不足,會導致重新拉取鏡像失敗。
數據盤


當k8s事件中包含以下信息,表明節點上用于存儲鏡像的磁盤空間已滿,需要清理鏡像,或擴容磁盤。
Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "nginx-6dc48bf8b6-l8xrw": Error response from daemon: mkdir xxxxx: no space left on device
確認節點上存儲鏡像的磁盤空間的命令為:lvs


清理鏡像的命令為:
docker rmi –f {鏡像ID}
擴容磁盤的操作步驟如下:
步驟 1 在EVS界面擴容數據盤。
步驟 2 登錄CCE控制臺,進入集群,在左側選擇“節點管理”,單擊節點后的“同步云服務器”。
步驟 3 登錄目標節點。
步驟 4 使用lsblk命令查看節點塊設備信息。
這里存在兩種情況,根據容器存儲Rootfs而不同。
- Overlayfs,沒有單獨劃分thinpool,在dockersys空間下統一存儲鏡像相關數據。
#lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk└─sda1 8:1 0 50G 0 part /sdb 8:16 0 200G 0 disk├─vgpaas-dockersys 253:0 0 90G 0 lvm /var/lib/docker # docker使用的空間└─vgpaas-kubernetes 253:1 0 10G 0 lvm /mnt/paas/kubernetes/kubelet # kubernetes使用的空間
在節點上執行如下命令,將新增的磁盤容量加到dockersys盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/dockersysresize2fs /dev/vgpaas/dockersy
- Devicemapper,單獨劃分了thinpool存儲鏡像相關數據。
#lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk└─sda1 8:1 0 50G 0 part /sdb 8:16 0 200G 0 disk├─vgpaas-dockersys 253:0 0 18G 0 lvm /var/lib/docker├─vgpaas-thinpool_tmeta 253:1 0 3G 0 lvm│ └─vgpaas-thinpool 253:3 0 67G 0 lvm # thinpool空間│ ...├─vgpaas-thinpool_tdata 253:2 0 67G 0 lvm│ └─vgpaas-thinpool 253:3 0 67G 0 lvm│ ...└─vgpaas-kubernetes 253:4 0 10G 0 lvm /mnt/paas/kubernetes/kubelet
在節點上執行如下命令,將新增的磁盤容量加到thinpool盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/thinpool
在節點上執行如下命令,將新增的磁盤容量加到dockersys盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/dockersysresize2fs /dev/vgpaas/dockersys
排查項五:遠程鏡像倉庫使用非知名或不安全的證書
從第三方倉庫下載鏡像時,若第三方倉庫使用了非知名或者不安全的證書,節點上會拉取鏡像失敗,Pod事件列表中有“實例拉取鏡像失敗”事件,報錯原因為"x509: certificate signed by unknown authority"。
操作步驟:
步驟 1 確認報錯unknown authority的第三方鏡像服務器地址和端口。
從"實例拉取鏡像失敗"事件信息中能夠直接看到報錯的第三方鏡像服務器地址和端口,如上圖中錯誤信息為:
Failed to pull image "bitnami/redis-cluster:latest": rpc error: code = Unknown desc = error pulling image configuration: Get //production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/e8/e83853f03a2e792614e7c1e6de75d63e2d6d633b4e7c39b9d700792ee50f7b56/data?verify=1636972064-AQbl5RActnudDZV%2F3EShZwnqOe8%3D: x509: certificate signed by unknown authority
對應的第三方鏡像服務器地址為 production.cloudflare.docker.com ,端口為https默認端口 443 。
步驟 2 在需要下載第三方鏡像的節點上加載第三方鏡像服務器的根證書。
CentOS節點執行如下命令,{server_url}:{server_port}需替換成步驟1中地址和端口,如 production.cloudflare.docker.com:443。
若節點的容器引擎為containerd,最后一步“systemctl restart docker”命令替換為"systemctl restart containerd"。
openssl s_client -showcerts -connect {server_url}:{server_port} < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /etc/pki/ca-trust/source/anchors/tmp_ca.crtupdate-ca-trustsystemctl restart docker
ubuntu節點執行如下命令。
openssl s_client -showcerts -connect {server_url}:{server_port } < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /usr/local/share/ca-certificates/tmp_ca.crtupdate-ca-trustsystemctl restart docker
排查項六:鏡像過大導致失敗
Pod事件列表中有“實例拉取鏡像失敗”事件,報錯原因如下。這可能是鏡像較大導致的情況。
Failed to pull image "XXX": rpc error: code = Unknown desc = context canceled
登錄節點使用docker pull命令手動下拉鏡像,鏡像下拉成功。
問題根因:
kubernetes默認的image-pull-progress-deadline是1分鐘, 如果1分鐘內鏡像下載沒有任何進度更新, 下載動作就會取消。在節點性能較差或鏡像較大時,可能出現鏡像無法成功下載,負載啟動失敗的現象。
解決方案:
- (推薦)方法一:登錄節點使用docker pull命令手動下拉鏡像,確認負載的鏡像拉取策略imagePullPolicy為IfNotPresent(默認策略配置)。此時創建負載會使用已拉取到本地的鏡像。
- 方法二:修改kubelet配置參數。
1.15及以上集群使用如下命令:
vi /opt/cloud/cce/kubernetes/kubelet/kubelet
1.15以下集群使用如下命令:
vi /var/paas/kubernetes/kubelet/kubelet
在DAEMON_ARGS參數末尾追加配置 --image-pull-progress-deadline=30m ,30m為30分鐘,可根據需求修改為合適時間。追加配置和前項配置之間由空格分開。


重啟kubelet:
systemctl restart kubelet
等待片刻,確定kubelet狀態為running
systemctl status kubelet


負載正常啟動,鏡像下拉成功。
排查項七:無法連接鏡像倉庫
問題現象
創建工作負載時報如下錯誤。
Failed to pull image "docker.io/bitnami/nginx:1.22.0-debian-11-r3": rpc error: code = Unknown desc = Error response from daemon: Get //registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
問題原因
無法連接鏡像倉庫,網絡不通。SWR僅支持直接拉Docker官方的鏡像,其他倉庫的鏡像需要連接。
解決方案:
- 給需要下載鏡像的節點綁定公網IP。
- 先將鏡像上傳到SWR,然后從SWR拉取鏡像。
排查項八:拉取公共鏡像達上限
問題現象
創建工作負載時報如下錯誤。
ERROR: toomanyrequests: Too Many Requests.
或
you have reached your pull rate limit, you may increase the limit by authenticating an upgrading: //www.docker.com/increase-rate-limits.
問題原因
DockerHub對用戶拉取容器鏡像請求設定了上限,詳情請參見。
解決方案:
將常用的鏡像上傳到SWR,然后從SWR拉取鏡像。
四、工作負載異常:啟動容器失敗
問題定位
工作負載詳情中,若事件中提示“啟動容器失敗”,請按照如下方式來初步排查原因:
步驟 1 登錄異常工作負載所在的節點。
步驟 2 查看工作負載實例非正常退出的容器ID。
docker ps -a | grep $podName
步驟 3 查看退出容器的錯誤日志。
docker logs $containerID
根據日志提示修復工作負載本身的問題。
步驟 4 查看操作系統的錯誤日志。
cat /var/log/messages | grep
根據日志判斷是否觸發了系統OOM。
排查思路
根據具體事件信息確定具體問題原因,如下表所示。
容器啟動失敗
| 日志或事件信息 | 問題原因與解決方案 |
|---|---|
| 日志中存在exit(0) | 容器中無進程。請調試容器是否能正常運行。排查項一:(退出碼:0)容器中無持續運行的進程 |
| 事件信息:Liveness probe failed: Get http…日志中存在exit(137) | 健康檢查執行失敗。排查項二:(退出碼:137)健康檢查執行失敗 |
| 事件信息:Thin Pool has 15991 free data blocks which is less than minimum required 16383 free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior |
磁盤空間不足,需要清理磁盤空間。排查項三:容器所在磁盤空間不足 |
| 日志中存在OOM字眼 | 內存不足。排查項四:達到容器資源上限排查項五:工作負載的容器規格設置較小導致 |
| Address already in use | Pod中容器端口沖突排查項六:同一pod中container端口沖突導致 |
出上述可能原因外,還可能存在如下原因,請根據順序排查。
- 排查項七:容器啟動命令配置有誤導致
- 排查項九:用戶自身業務BUG
- 在ARM架構的節點上創建工作負載時未使用正確的鏡像版本,使用正確的鏡像版本即可解決該問題。
排查思路


排查項一:(退出碼:0)容器中無持續運行的進程
步驟 1 登錄異常工作負載所在的節點。
步驟 2 查看容器狀態。
docker ps -a | grep $podName
如下圖所示:


當容器中無持續運行的進程時,會出現exit(0)的狀態碼,此時說明容器中無進程。
排查項二:(退出碼:137)健康檢查執行失敗
工作負載配置的健康檢查會定時檢查業務,異常情況下pod會報實例不健康的事件且pod一直重啟失敗。
工作負載若配置liveness型(工作負載存活探針)健康檢查,當健康檢查失敗次數超過閾值時,會重啟實例中的容器。在工作負載詳情頁面查看事件,若K8s事件中出現“Liveness probe failed: Get http…”時,表示健康檢查失敗。
解決方案:
請核查“工作負載詳情>更新升級>高級配置>健康檢查”中的信息,排查健康檢查策略是否合理或業務是否已異常。
排查項三:容器所在磁盤空間不足
如下磁盤為創建節點時選擇的docker專用盤分出來的thinpool盤,以root用戶執行lvs命令可以查看當前磁盤的使用量。
Thin Pool has 15991 free data blocks which is less than minimum required 16383 free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior
解決方案:
方案一
您可以執行以下命令清理未使用的垃圾鏡像:
docker system prune -a

說明
該命令會把暫時沒有用到的Docker鏡像都刪除,執行命令前請確認。
方案二
或者您也可以選擇擴容磁盤,具體步驟如下:
步驟 1 在EVS界面擴容數據盤。
步驟 2 登錄CCE控制臺,進入集群,在左側選擇“節點管理”,單擊節點后的“同步云服務器”。
步驟 3 登錄目標節點。
步驟 4 使用lsblk命令查看節點塊設備信息。
這里存在兩種情況,根據容器存儲Rootfs而不同。
- Overlayfs,沒有單獨劃分thinpool,在dockersys空間下統一存儲鏡像相關數據。
#lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk└─sda1 8:1 0 50G 0 part /sdb 8:16 0 200G 0 disk├─vgpaas-dockersys 253:0 0 90G 0 lvm /var/lib/docker # docker使用的空間└─vgpaas-kubernetes 253:1 0 10G 0 lvm /mnt/paas/kubernetes/kubelet # kubernetes使用的空間
在節點上執行如下命令,將新增的磁盤容量加到dockersys盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/dockersysresize2fs /dev/vgpaas/dockersys
- Devicemapper,單獨劃分了thinpool存儲鏡像相關數據。
#lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk└─sda1 8:1 0 50G 0 part /sdb 8:16 0 200G 0 disk├─vgpaas-dockersys 253:0 0 18G 0 lvm /var/lib/docker├─vgpaas-thinpool_tmeta 253:1 0 3G 0 lvm│ └─vgpaas-thinpool 253:3 0 67G 0 lvm # thinpool空間│ ...├─vgpaas-thinpool_tdata 253:2 0 67G 0 lvm│ └─vgpaas-thinpool 253:3 0 67G 0 lvm│ ...└─vgpaas-kubernetes 253:4 0 10G 0 lvm /mnt/paas/kubernetes/kubelet
在節點上執行如下命令,將新增的磁盤容量加到thinpool盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/thinpool
在節點上執行如下命令,將新增的磁盤容量加到dockersys盤上。
pvresize /dev/sdblvextend -l+100%FREE -n vgpaas/dockersysresize2fs /dev/vgpaas/dockersys
排查項四:達到容器資源上限
事件詳情中有OOM字樣。并且,在日志中也會有記錄:
cat /var/log/messages | grep 96feb0a425d6 | grep oom


創建工作負載時,設置的限制資源若小于實際所需資源,會觸發系統OOM,并導致容器異常退出。
排查項五:工作負載的容器規格設置較小導致
工作負載的容器規格設置較小導致,若創建工作負載時,設置的限制資源少于實際所需資源,會導致啟動容器失敗。
排查項六:同一pod中container端口沖突導致
步驟 1 登錄異常工作負載所在的節點。
步驟 2 查看工作負載實例非正常退出的容器ID。
docker ps -a | grep $podName
步驟 3 查看退出容器的錯誤日志。
docker logs $containerID
根據日志提示修復工作負載本身的問題。如下圖所示,即同一Pod中的container端口沖突導致容器啟動失敗。
container沖突導致容器啟動失敗

解決方案:
重新創建工作負載,并配置正確的端口,確保端口不沖突。
排查項七:容器啟動命令配置有誤導致
錯誤信息如下圖所示:


解決方案:
核查“工作負載詳情>更新升級頁簽>高級配置>啟動命令”中的信息,確保啟動命令配置正確。
排查項九:用戶自身業務BUG
請檢查工作負載啟動命令是否正確執行,或工作負載本身bug導致容器不斷重啟。
步驟 1 登錄異常工作負載所在的節點。
步驟 2 查看工作負載實例非正常退出的容器ID。
docker ps -a | grep $podName
步驟 3 查看退出容器的錯誤日志。
docker logs $containerID
注意
這里的containerID為已退出的容器的ID
容器啟動命令配置不正確


如上圖所示,容器配置的啟動命令不正確導致容器啟動失敗。其他錯誤請根據日志提示修復工作負載本身的BUG問題。
解決方案:
重新創建工作負載,并配置正確的啟動命令。
五、工作負載異常:實例驅逐異常(Evicted)
Eviction介紹
Eviction,即驅逐的意思,意思是當節點出現異常時,為了保證工作負載的可用性,kubernetes將有相應的機制驅逐該節點上的Pod。
目前kubernetes中存在兩種eviction機制,分別由kube-controller-manager和kubelet實現。
- kube-controller-manager實現的eviction
kube-controller-manager主要由多個控制器構成,而eviction的功能主要由node controller這個控制器實現。該Eviction會周期性檢查所有節點狀態,當節點處于NotReady狀態超過一段時間后,驅逐該節點上所有pod。
kube-controller-manager提供了以下啟動參數控制eviction:
pod-eviction-timeout: 即當節點宕機該時間間隔后,開始eviction機制,驅趕宕機節點上的Pod,默認為5min。
node-eviction-rate: 驅趕速率,即驅趕Node的速率,由令牌桶流控算法實現,默認為0.1,即每秒驅趕0.1個節點,注意這里不是驅趕Pod的速率,而是驅趕節點的速率。相當于每隔10s,清空一個節點。
secondary-node-eviction-rate: 二級驅趕速率,當集群中宕機節點過多時,相應的驅趕速率也降低,默認為0.01。
unhealthy-zone-threshold: 不健康zone閾值,會影響什么時候開啟二級驅趕速率,默認為0.55,即當該zone中節點宕機數目超過55%,而認為該zone不健康。
large-cluster-size-threshold: 大集群閾值,當該zone的節點多于該閾值時,則認為該zone是一個大集群。大集群節點宕機數目超過55%時,則將驅趕速率降為0.01,假如是小集群,則將速率直接降為0。
- kubelet的eviction機制
如果節點處于資源壓力,那么kubelet就會執行驅逐策略。驅逐會考慮Pod的優先級,資源使用和資源申請。當優先級相同時,資源使用/資源申請最大的Pod會被首先驅逐。
kube-controller-manager的eviction機制是粗粒度的,即驅趕一個節點上的所有pod,而kubelet則是細粒度的,它驅趕的是節點上的某些Pod,驅趕哪些Pod與Pod的Qos機制有關。該Eviction會周期性檢查本節點內存、磁盤等資源,當資源不足時,按照優先級驅逐部分pod。
驅逐閾值分為軟驅逐閾值(Soft Eviction Thresholds)和強制驅逐(Hard Eviction Thresholds)兩種機制,如下:
軟驅逐閾值: 當node的內存/磁盤空間達到一定的閾值后,kubelet不會馬上回收資源,如果改善到低于閾值就不進行驅逐,若這段時間一直高于閾值就進行驅逐。
強制驅逐: 強制驅逐機制則簡單的多,一旦達到閾值,直接把pod從本地驅逐。
kubelet提供了以下參數控制eviction:
eviction-soft: 軟驅逐閾值設置,具有一系列閾值,比如memory.available<1.5Gi時,它不會立即執行pod eviction,而會等待eviction-soft-grace-period時間,假如該時間過后,依然還是達到了eviction-soft,則觸發一次pod eviction。
eviction-soft-grace-period: 默認為90秒,當eviction-soft時,終止Pod的grace的時間,即軟驅逐寬限期,軟驅逐信號與驅逐處理之間的時間差。
eviction-max-pod-grace-period: 最大驅逐pod寬限期,停止信號與kill之間的時間差。
eviction-pressure-transition-period: 默認為5分鐘,驅逐壓力過渡時間,超過閾值時,節點會被設置為memory pressure或者disk pressure,然后開啟pod eviction。
eviction-minimum-reclaim: 表示每一次eviction必須至少回收多少資源。
eviction-hard : 強制驅逐設置,也具有一系列的閾值,比如memory.available<1Gi,即當節點可用內存低于1Gi時,會立即觸發一次pod eviction。
問題定位
若節點故障時,實例未被驅逐,請先按照如下方法進行問題定位。
使用如下命令發現很多pod的狀態為Evicted:
kubectl get pods
在節點的kubelet日志中會記錄Evicted相關內容,搜索方法可參考如下命令:
cat /var/paas/sys/log/kubernetes/kubelet.log | grep -i Evicted -C3
排查思路
以下排查思路根據原因的出現概率進行排序,建議您從高頻率原因往低頻率原因排查,從而幫助您快速找到問題的原因。
如果解決完某個可能原因仍未解決問題,請繼續排查其他可能原因。
- 排查項一:是否在實例上設置了tolerations
- 排查項二:是否滿足停止驅逐實例的條件
- 排查項三:容器與節點上的“資源分配量”是否一致
- 排查項四:工作負載實例不斷失敗并重新部署
排查思路


排查項一:是否在實例上設置了tolerations
通過kubectl工具或單擊對應工作負載后的“更多 > 編輯YAML”,檢查工作負載上是不是打上了tolerations,具體請參見。
排查項二:是否滿足停止驅逐實例的條件
若屬于小規格的集群(集群節點數小于50個節點),如果故障的節點大于總節點數的55%,實例的驅逐將會被暫停。此情況下k8s將部署嘗試驅逐故障節點的工作負載,具體請參見。
排查項三:容器與節點上的“資源分配量”是否一致
容器被驅逐后還會頻繁調度到原節點。
問題原因:
節點驅逐容器是根據節點的“資源使用率”進行判斷;容器的調度規則是根據節點上的“資源分配量”進行判斷。由于判斷標準不同,所以可能會出現被驅逐后又再次被調度到原節點的情況。
解決方案:
遇到此類問題時,請合理分配各容器的資源分配量即可解決。
排查項四:工作負載實例不斷失敗并重新部署
工作負載實例出現不斷失敗,不斷重新部署的情況。
問題分析:
pod驅逐后,如果新調度到的節點也有驅逐情況,就會再次被驅逐;甚至出現pod不斷被驅逐的情況。
如果是由kube-controller-manager觸發的驅逐,會留下一個狀態為Terminating的pod;直到容器所在節點狀態恢復后,pod才會自動刪除。如果節點已經刪除或者其他原因導致的無法恢復,可以使用“強制刪除”刪除pod。
如果是由kubelet觸發的驅逐,會留下一個狀態為Evicted的pod,此pod只是方便后期定位的記錄,可以直接刪除。
解決方案:
使用如下命令刪除舊驅趕的遺留:
kubectl get pods | grep Evicted | awk '{print $1}' | xargs kubectl delete pod
為命名空間名稱,請根據需要指定。
參考
六、工作負載異常:存儲卷無法掛載或掛載超時
排查思路
以下排查思路根據原因的出現概率進行排序,建議您從高頻率原因往低頻率原因排查,從而幫助您快速找到問題的原因。
如果解決完某個可能原因仍未解決問題,請繼續排查其他可能原因。
- 排查項一:EVS存儲卷是否跨AZ掛載
- 排查項二:存儲中是否同時存在多條權限相關的配置
- 排查項三:帶云硬盤卷的Deployment的副本數大于1
- 排查項四:EVS磁盤文件系統損壞
排查思路


排查項一:EVS存儲卷是否跨AZ掛載
問題描述:
客戶在有狀態工作負載上掛載EVS存儲卷,但無法掛載卷并超時。
問題定位:
經查詢確認,該節點在 可用區1 ,而要掛載的磁盤在 可用區2 ,導致無法掛載而超時。
解決方案:
在同一可用區內創建磁盤再掛載后即可正常。
排查項二:存儲中是否同時存在多條權限相關的配置
如果您掛載的存儲中內容太多,同時又配置了以下幾條配置,最終會由于逐個修改文件權限,而導致掛載時間過長。
問題定位:
- Securitycontext字段中是否包含runAsuser/fsGroup。securityContext是kubernetes中的字段,即安全上下文,它用于定義Pod或Container的權限和訪問控制設置。
- 啟動命令中是否包含ls、chmod、chown等查詢或修改文件權限的操作。
解決建議 :
請根據您的業務需求,判斷是否需要修改。
排查項三:帶云硬盤卷的Deployment的副本數大于1
問題描述:
創建Pod失敗,并報“添加存儲失敗”的事件,事件信息如下。
Multi-Attach error for volume "pvc-62a7a7d9-9dc8-42a2-8366-0f5ef9db5b60" Volume is already used by pod(s) testttt-7b774658cb-lc98h
問題定位:
查看Deployment的副本數是否大于1。
Deployment中使用EVS存儲卷時,副本數只能為1。若用戶在后臺指定Deployment的實例數為2以上,此時CCE并不會限制Deployment的創建。但若這些實例Pod被調度到不同的節點,則會有部分Pod因為其要使用的EVS無法被掛載到節點,導致Pod無法啟動成功。
解決方案:
使用EVS的Deployment的副本數指定為1,或使用其他類型存儲卷。
排查項四:EVS磁盤文件系統損壞
問題描述:
創建Pod失敗,出現類似信息,磁盤文件系統損壞。
MountVolume.MountDevice failed for volume "pvc-08178474-c58c-4820-a828-14437d46ba6f" : rpc error: code = Internal desc = [09060def-afd0-11ec-9664-fa163eef47d0] /dev/sda has file system, but it is detected to be damaged
解決方案:
在EVS中對磁盤進行備份,然后執行如下命令修復文件系統。
fsck -y {盤符}
七、工作負載異常:一直處于創建中
問題描述
節點變更之后,節點上的工作負載一直處于創建中。
解決方法
步驟 1 登錄CCE節點(彈性云服務器)并刪除cpu_manager_state文件。
刪除命令示例如下:
rm -rf /mnt/paas/kubernetes/kubelet/cpu_manager_state
步驟 2 重啟節點或重啟kubelet,重啟kubelet的方法如下:
systemctl restart kubelet
此時重新拉起或創建工作負載,已可成功執行。
解決方式鏈接:CCE節點變更規格后,為什么無法重新拉起或創建工作負載?
八、工作負載異常:結束中,解決Terminating狀態的Pod刪不掉的問題
問題描述
在節點處于“不可用”狀態時,CCE會遷移節點上的容器實例,并將節點上運行的pod置為“Terminating”狀態。
待節點恢復后,處于“Terminating”狀態的pod會自動刪除。
偶現部分pod(實例)一直處于“Terminating ”狀態:
#kubectl get pod -n aosNAME READY STATUS RESTARTS AGEaos-apiserver-5f8f5b5585-s9l92 1/1 Terminating 0 3d1haos-cmdbserver-789bf5b497-6rwrg 1/1 Running 0 3d1haos-controller-545d78bs8d-vm6j9 1/1 Running 3 3d1h
通過kubectl delete pods -n 命令始終無法將其刪除:
kubectl delete pods aos-apiserver-5f8f5b5585-s9l92 -n aos
解決方法
無論各種方式生成的pod,均可以使用如下命令強制刪除:
kubectl delete pods --grace-period=0 --force
因此對于上面的pod,我們只要執行如下命令即可刪除:
kubectl delete pods aos-apiserver-5f8f5b5585-s9l92 --grace-period=0 --force
九、工作負載異常:已停止
問題現象
工作負載的狀態為“已停止”。
問題原因:
工作負載的yaml的中metadata.enable字段為false,導致工作負載被停止,Pod被刪除導致工作負載處于已停止狀態,如下圖所示:


解決方案
將enable字段刪除或者將false修改為true。
十、在什么場景下設置工作負載生命周期中的“停止前處理”?
服務的業務處理時間較長,在升級時,需要先等Pod中的業務處理完,才能kill該Pod,以保證業務不中斷的場景。
十一、在同一個命名空間內訪問指定容器的FQDN是什么?
問題背景
客戶詢問在創建負載時指定部署的容器名稱、pod名稱、namespace名稱,在同一個命名空間內訪問該容器的FQDN是什么?
全限定域名:FQDN,即Fully Qualified Domain Name,同時帶有主機名和域名的名稱。(通過符號“.”)
例如:主機名是bigserver,域名是mycompany.com,那么FQDN就是:bigserver.mycompany.com。
問題建議
方案一: 發布服務使用域名發現,需要提前預制好主機名和命名空間,服務發現使用域名的方式,注冊的服務的域名為:服務名.命名空間.svc.cluster.local 。這種使用有限制,注冊中心部署必須容器化部署。
方案二: 容器部署使用主機網絡部署,然后親和到集群的某一個節點,這樣可以明確知道容器的服務地址(就是節點的地址),注冊的地址為:服務所在節點IP,這種方案可以滿足注冊中心利用VM部署,缺陷是使用主機網絡效率沒有容器網絡高。
十二、健康檢查探針(Liveness、Readiness)偶現檢查失敗?
健康檢查探針偶現檢測失敗,是由于容器內的業務故障所導致,您需要優先定位自身業務問題。
常見情況有:
- 業務處理時間長,導致返回超時。
- tomcat建鏈和等到耗費時間太長(連接數、線程數等),導致返回超時。
- 容器所在節點,磁盤IO等性能達到瓶頸,導致業務處理超時。
十三、 如何設置容器umask值?
問題描述
tailf /dev/null的方式啟動容器,然后手動執行啟動腳本的方式得到的目錄的權限是700,而不加tailf由Kubernetes自行啟動的方式得到的目錄權限卻是751。
操作步驟
這個問題是因為兩種方式設置的umask值不一樣,所以創建出來的目錄權限不相同。
umask值用于為用戶新創建的文件和目錄設置缺省權限。如果umask的值設置過小,會使群組用戶或其他用戶的權限過大,給系統帶來安全威脅。因此設置所有用戶默認的umask值為0077,即用戶創建的目錄默認權限為700,文件的默認權限為600。
可以在啟動腳本里面增加如下內容實現創建出來的目錄權限為700:
- 分別在**/etc/bashrc**文件和 /etc/profile.d/ 目錄下的所有文件中加入“umask 0077”。
- 執行如下命令:
echo "umask 0077" >> $FILE
說明
FILE為具體的文件名,例如:echo “umask 0077” >> /etc/bashrc
- 設置**/etc/bashrc**文件和 /etc/profile.d/ 目錄下所有文件的屬主為:root,群組為:root。
- 執行如下命令:
chown root.root $FILE
十四、 Dockerfile中ENTRYPOINT指定JVM啟動堆內存參數后部署容器啟動報錯?
問題描述
Dockerfile中ENTRYPOINT指定JVM啟動堆內存參數后部署容器啟動報錯,報錯信息為:invalid initial heap size,如下圖:


操作步驟
請檢查ENTRYPOINT設置,下方的設置是錯誤的:
ENTRYPOINT ["java","-Xms2g -Xmx2g","-jar","xxx.jar"]
如下兩種辦法可以解決該問題:
- (推薦) 將容器啟動命令寫在“工作負載 > 更新升級 > 容器設置 > 生命周期 > 啟動命令”這里,容器能正常啟動。
- 將ENTRYPOINT啟動命令修改為如下格式:
ENTRYPOINT exec java -Xmx2g -Xms2g -jar xxxx.jar
十五、 CCE啟動實例失敗時的重試機制是怎樣的?
CCE是基于原生Kubernetes的云容器引擎服務,完全兼容Kubernetes社區原生版本,與社區最新版本保持緊密同步,完全兼容Kubernetes API和Kubectl。
在Kubernetes中,Pod的spec中包含一個restartPolicy字段,其取值包括:Always、OnFailure和Never,默認值為:Always。
- Always:當容器失效時,由kubelet自動重啟該容器。
- OnFailure:當容器終止運行且退出不為0時(正常退出),由kubelet自動重啟該容器。
- Never:不論容器運行狀態如何,kubelet都不會重啟該容器。
restartPolicy適用于Pod中的所有容器。
restartPolicy僅針對同一節點上kubelet的容器重啟動作。當Pod中的容器退出時,kubelet 會按指數回退方式計算重啟的延遲(10s、20s、40s...),其最長延遲為5分鐘。 一旦某容器執行了10分鐘并且沒有出現問題,kubelet對該容器的重啟回退計時器執行重置操作。
每種控制器對Pod的重啟策略要求如下:
- Replication Controller(RC)和DaemonSet:必須設置為Always,需要保證該容器的持續運行。
- Job:OnFailure或Never,確保容器執行完成后不再重啟。
十六、 CCE集群中工作負載鏡像的拉取策略?
容器在啟動運行前,需要鏡像。鏡像的存儲位置可能會在本地,也可能會在遠程鏡像倉庫中。
Kubernetes配置文件中的imagePullPolicy屬性是用于描述鏡像的拉取策略的,如下:
- Always:總是拉取鏡像。
imagePullPolicy: Always
- IfNotPresent:本地有則使用本地鏡像,不拉取。
imagePullPolicy: IfNotPresent
- Never:只使用本地鏡像,從不拉取,即使本地沒有。
imagePullPolicy: Never
說明
1. 如果設置為Always ,則每次容器啟動或者重啟時,都會從遠程倉庫拉取鏡像。
如果省略imagePullPolicy,策略默認為Always。
2. 如果設置為IfNotPreset,有下面兩種情況:
當本地不存在所需的鏡像時,會從遠程倉庫中拉取。
如果我們需要的鏡像和本地鏡像內容相同,只不過重新打了tag。此tag鏡像本地不存在,而遠程倉庫存在此tag鏡像。這種情況下,Kubernetes并不會拉取新的鏡像。