Pod概念
- Pod是kubernetes集群中最小的部署和管理的基本單元,協同尋址,協同調度。
- Pod是一個或多個容器的集合,是一個或一組服務(進程)的抽象集合。
- Pod中可以共享網絡和存儲(可以簡單理解為一個邏輯上的虛擬機,但並不是虛擬機)。
- Pod被創建后用一個UID來唯一標識,當Pod生命周期結束,被一個等價Pod替代時UID將重新生成。
Kubernetes Pod中最常用Docker容器運行,當然Pod也能支持其他的容器運行,比如rkt、podman等。
Kubernetes集群中的Pod可被用於以下兩個主要用途:
- 運行單個容器的Pod。“每個Pod 一個容器”模型是最常見的Kubernetes用例;在這種情況下,可以將Pod看作單個容器的包裝器,並且Kubernetes直接管理Pod,而不是容器。
- 運行多個協同工作的容器的Pod。Pod可能封裝由多個緊密耦合且需要共享資源的共處容器組成的應用程序。這些位於同一位置的容器可能形成單個內聚的服務單元,一個容器將文件從共享卷提供給公眾,而另一個單獨的“掛斗”容器則刷新或更新這些文件。Pod將這些容器和存儲資源打包為一個可管理的實體。
Pod控制器
控制器可以為您創建和管理多個Pod,管理副本和上線,並在集群范圍內提供自修復能力。例如,如果一個節點失敗,控制器可以在不同的節點上調度一樣的替身來自動替換Pod。
包含一個或多個Pod的控制器一些示例包括:
- Deployment kubernetes中最常見的控制器。用於運行無狀態應用
- Statefulset 用於運行有狀態應用
- DaemonSet 作用就像是計算機中的守護進程,它能夠運行集群存儲、日志收集和監控等【守護進程】
控制器通常使用您提供的Pod模塊來創建它負責的Pod。
Pod故障歸類
- Pod狀態 一直處於Pending
- Pod狀態 一直處於Waiting
- Pod狀態 一直處於ContainerCreating
- Pod狀態 處於ImagePullBackOff
- Pod狀態 處於CrashLoopBackOff
- Pod狀態 處於Error
- Pod狀態 一直處於Terminating
- Pod狀態 處於Unknown
Pod排查故障命令
- kubectl get pod <pod-name> -o yaml # 查看Pod配置是否正確
- kubectl describe pod <pod-name> # 查看Pod詳細事件信息
- kubectl logs <pod-name> [-c <container-name>] # 查看容器日志
Pod故障問題與排查方法
Pod 一直處於Pending狀態
Pending狀態意味着Pod的YAML文件已經提交給Kubernetes,API對象已經被創建並保存在Etcd當中。但是,這個Pod里有些容器因為某種原因而不能被順利創建。比如,調度不成功(可以通過kubectl describe pod 命令查看到當前Pod的事件,進而判斷為什么沒有調度)。可能原因:資源不足(集群內所有的Node都不滿足該Pod請求的CPU、內存、GPU等資源);HostPort已被占用(通常推薦使用Service對外開放服務端口)。
Pod 一直處於Waiting或ContainerCreating狀態
首先還是通過kubectl describe pod 命令查看當前Pod的事件。可能的原因有:
1、鏡像拉取失敗,比如鏡像地址配置錯誤、拉取不了國外鏡像源(gcr.io)、私有鏡像密鑰配置錯誤、鏡像太大導致拉取超時(可以適當調整kubelet的-image-pull-progress-deadline和-runtime-request-timeout選項)等。
2、CNI網絡錯誤,一般需要檢查CNI網絡插件的配置,比如:無法配置Pod網絡、無法分配IP地址。
3、容器無法啟動,需要檢查是否打包了正確的鏡像或者是否配置了正確的容器參數
4、Failed create pod sandbox,查看kubelet日志,原因可能是磁盤壞道(input/output error)。
Pod 一直處於ImagePullBackOff狀態
通常是鏡像名稱配置錯誤或者私有鏡像的密鑰配置錯誤導致。這種情況可以使用docker pull來驗證鏡像是否可以正常拉取。
如果私有鏡像密鑰配置錯誤或沒有配置,按下面檢查:
1、查詢docker-registry類型的Secret
# 查看 docker-registry Secret $ kubectl get secrets my-secret -o yaml | grep 'dockerconfigjson:' | awk '{print $NF}' | base64 -d
2、創建docker-registry類型的Secret
# 首先創建一個 docker-registry 類型的 Secret $ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL # 然后在 Deployment 中引用這個 Secret spec: containers: - name: private-reg-container image: <your-private-image> imagePullSecrets: - name: my-secret
Pod 一直處於CrashLoopBackOff狀態
此狀態說明容器曾經啟動了,但又異常退出。這時可以先查看一下容器的日志。
通過命令 kubectl logs 和 kubectl logs --previous 可以發下一些容器退出的原因,比如:容器進程退出、健康檢查失敗退出;此時如果還未發現線索,還而已到容器內執行命令(kubectl exec cassandra - cat /var.log/cassandra/system.log)來進一步查看退出原因;如果還是沒有線索,那就需要SSH登錄該Pod所在的Node上,查看Kubelet或者Docker的日志進一步排查。
Pod 處於 Error 狀態
通常處於Error狀態說明Pod啟動過程中發生了錯誤。常見的原因:依賴的ConfigMap、Secret或PV等不存在;請求的資源超過了管理員設置的限制,比如超過了LimitRange等;違反集群的安全策略,比如違反了PodSecurityPolicy等;容器無法操作集群內的資源,比如開啟RDAC后,需要為ServiceAccount配置角色綁定。
Pod 處於Terminating或Unknown狀態
從v1.5開始,Kubernetes不會因為Node失聯而刪除其上正在運行的Pod,而是將其標記為Terminating 或 Unknown 狀態。想要刪除這些狀態的Pod有三種方法:
1、從集群中刪除Node。使用公有雲時,kube-controller-manager會在VM刪除后自動刪除對應的Node。而在物理機部署的集群中,需要管理員手動刪除Node(kubectl delete node)。
2、Node恢復正常。kubelet會重新跟kube-apiserver通信確認這些Pod的期待狀態,進而再決定刪除或者繼續運行這些Pod。用戶強制刪除,用戶可以執行(kubectl delete pods pod-name --grace-period=0 --force)強制刪除Pod。除非明確知道Pod的確處於停止狀態(比如Node所在VM或物理機已經關機),否則不建議使用該方法。特別是StatefulSet 管理的Pod,強制刪除容易導致腦裂或數據丟失等問題。
3、Pod行為異常,這里所說的行為異常是指Pod沒有按預期的行為執行,比如沒有運行podSpec 里面設置的命令行參數。這一般是podSpec yaml文件內容有誤,可以嘗試使用 --validate 參數重建容器,比如(kubectl delete pod mypod 和 kubectl create --validate -f mypod.yaml);也可以查看創建后的podSpec是否是對的,比如(kubectl get pod mypod -o yaml);修改靜態Pod的Manifest后未自動重建,kubelet 使用inotify 機制檢測 /etc/kubernetes/manifests 目錄(可通過 kubelet 的 -pod-manifest-path 選項指定)中靜態Pod的變化,並在文件發生變化后重新創建相應的 Pod。但有時也會發現修改靜態Pod的 Manifest后未自動創建新 Pod的情景,此時已過簡單的修復方法是重啟 Kubelet。
Unknown 這個異常狀態意味着Pod的狀態不能持續地被 kubelet匯報給 kube-apiserver,這很有可能是主從節點(Master 和 Kubelet)間的通信出現了問題。