Pod中如何管理多個容器
Pod中可以同時運行多個進程(作為容器運行)協同工作。同一個Pod中的容器會自動的分配到同一個 node 上。同一個Pod中的容器共享資源、網絡環境和依賴,它們總是被同時調度。
注意在一個Pod中同時運行多個容器是一種比較高級的用法。只有當你的容器需要緊密配合協作的時候才考慮用這種模式。例如,你有一個容器作為web服務器運行,需要用到共享的volume,有另一個“sidecar”容器來從遠端獲取資源更新這些文件,如下圖所示:

Pod中可以共享兩種資源:網絡和存儲。
- 網絡:每個Pod都會被分配一個唯一的IP地址。Pod中的所有容器共享網絡空間,包括IP地址和端口。Pod內部的容器可以使用
localhost互相通信。Pod中的容器與外界通信時,必須分配共享網絡資源(例如使用宿主機的端口映射)。
- 存儲:可以Pod指定多個共享的Volume。Pod中的所有容器都可以訪問共享的volume。Volume也可以用來持久化Pod中的存儲資源,以防容器重啟后文件丟失。
Pod容器分類
•Infrastructure Container:基礎容器,維護整個Pod網絡空間
•InitContainers:初始化容器,先於業務容器開始執行
•Containers:業務容器,並行啟動
kubernetes中pod創建流程
Pod是Kubernetes中最基本的部署調度單元,可以包含container,邏輯上表示某種應用的一個實例。例如一個web站點應用由前端、后端及數據庫構建而成,這三個組件將運行在各自的容器中,那么我們可以創建包含三個container的pod。

具體的創建步驟包括:
(1)客戶端提交創建請求,可以通過API Server的Restful API,也可以使用kubectl命令行工具。支持的數據類型包括JSON和YAML。 (2)API Server處理用戶請求,存儲Pod數據到etcd。 (3)調度器通過API Server查看未綁定的Pod。嘗試為Pod分配主機。 (4)過濾主機 (調度預選):調度器用一組規則過濾掉不符合要求的主機。比如Pod指定了所需要的資源量,那么可用資源比Pod需要的資源量少的主機會被過濾掉。 (5)主機打分(調度優選):對第一步篩選出的符合要求的主機進行打分,在主機打分階段,調度器會考慮一些整體優化策略,比如把容一個Replication Controller的副本分布到不同的主機上,使用最低負載的主機等。 (6)選擇主機:選擇打分最高的主機,進行binding操作,結果存儲到etcd中。 (7)kubelet根據調度結果執行Pod創建操作: 綁定成功后,scheduler會調用APIServer的API在etcd中創建一個boundpod對象,描述在一個工作節點上綁定運行的所有pod信息。運行在每個工作節點上的kubelet也會定期與etcd同步boundpod信息,一旦發現應該在該工作節點上運行的boundpod對象沒有更新,則調用Docker API創建並啟動pod內的容器。
調度約束
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
scheduler組件
k8s調度器會將pod調度到資源滿足要求並且評分最高的node上。
我們可以使用多種規則比如:
1.設置cpu、內存的使用要求
2.增加node的label,並通過pod.Spec.NodeSelector進行強匹配;
3.直接設置pod的nodeName,跳過調度直接下發。
k8s 1.2加入了一個實驗性的功能:affinity。意為親和性。這個特性的設計初衷是為了替代nodeSelector,並擴展更強大的調度策略。
調度器的工作機制是這樣的
一、預備工作 1、緩存所有的node節點,記錄他們的規格:cpu、內存、磁盤空間、gpu顯卡數等; 2、緩存所有運行中的pod,按照pod所在的node進行區分,統計每個node上的pod request了多少資源。request是pod的QoS配置。 3、list & watch pod資源,當檢查到有新的Pending狀態的pod出現,就將它加入到調度隊列中。 4、調度器的worker組件從隊列中取出pod進行調度。 二、調度過程 1、先將當前所有的node放入隊列; 2、執行predicates算法,對隊列中的node進行篩選。這里算法檢查了一些pod運行的必要條件,包括port不沖突、cpu和內存資源QoS(如果有的話)必須滿足、掛載volume(如果有的話)類型必須匹配、nodeSelector規則必須匹配、硬性的affinity規則(下文會提到)必須匹配、node的狀態(condition)必須正常,taint_toleration硬規則(下文會提到)等等。 3、執行priorities算法,對隊列中剩余的node進行評分,這里有許多評分項,各個項目有各自的權重:整體cpu,內存資源的平衡性、node上是否有存在要求的鏡像、同rs的pod是否有調度、node affinity的軟規則、taint_toleration軟規則(下文會提到)等等。 4、最終評分最高的node會被選出。即代碼中suggestedHost, err := sched.schedule(pod)一句(plugin/pkg/scheduler/scheduler.go)的返回值。 5、調度器執行assume方法,該方法在pod調度到node之前,就以“該pod運行在目標node上” 為場景更新調度器緩存中的node 信息,也即預備工作中的1、2兩點。這么做是為了讓pod在真正調度到node上時,調度器也可以同時做后續其他pod的調度工作。 6、調度器執行bind方法,該方法創建一個Binding資源,apiserver檢查到創建該資源時,會主動更新pod的nodeName字段。完成調度
nodeSelector用於將Pod調度到匹配Label的Node上
將標簽附加到node
[root@k8s-master1 ~]# kubectl label nodes 192.168.0.126 env_role=dev node/192.168.0.126 labeled [root@k8s-master1 ~]# kubectl label nodes 192.168.0.125 env_role=test node/192.168.0.125 labeled [root@k8s-master1 ~]# kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS 192.168.0.125 Ready <none> 2d4h v1.13.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=test,kubernetes.io/hostname=192.168.0.125 192.168.0.126 Ready <none> 2d4h v1.13.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/hostname=192.168.0.126
將nodeSelector字段添加到pod配置中
[root@k8s-master1 ~]# vim pod2.yaml apiVersion: v1 kind: Pod metadata: name: nginx
labels:
app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: env_role: dev [root@k8s-master1 ~]# kubectl create -f pod2.yaml pod/nginx created
查看pod
[root@k8s-master1 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 115s [root@k8s-master1 ~]# kubectl describe pod nginx Name: nginx Namespace: default Priority: 0 PriorityClassName: <none> Node: 192.168.0.126/192.168.0.126 Start Time: Fri, 21 Dec 2018 14:07:49 +0800 Labels: <none> Annotations: <none> Status: Running IP: 172.17.92.2 Containers: nginx: Container ID: docker://8c7e442cc83b6532b3bda707f389fa371861d173e9395149bbede9e166bf559c Image: nginx Image ID: docker-pullable://nginx@sha256:1a0043cfb1987774c6981c41e49f758c58ace64c30e1c4ecff5cedff0b5c88da Port: <none> Host Port: <none> State: Running Started: Fri, 21 Dec 2018 14:07:50 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-7vs6s (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-7vs6s: Type: Secret (a volume populated by a Secret) SecretName: default-token-7vs6s Optional: false QoS Class: BestEffort Node-Selectors: env_role=dev Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m11s default-scheduler Successfully assigned default/nginx to 192.168.0.126 Normal Pulled 2m11s kubelet, 192.168.0.126 Container image "nginx" already present on machine Normal Created 2m10s kubelet, 192.168.0.126 Created container Normal Started 2m10s kubelet, 192.168.0.126 Started container
nodeName用於將Pod調度到指定的Node名稱上
spec.nodeName用於強制約束將Pod調度到指定的Node節點上,這里說是“調度”,但其實指定了nodeName的Pod會直接跳過Scheduler的調度邏輯,直接寫入PodList列表,該匹配規則是強制匹配。
[root@k8s-master1 ~]# vim pod3.yaml apiVersion: v1 kind: Pod metadata: name: pod-example labels: app: nginx spec: nodeName: 192.168.0.125 containers: - name: nginx image: nginx:1.15 [root@k8s-master1 ~]# kubectl create -f pod3.yaml pod/pod-example created
查看pod
[root@k8s-master1 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 10m pod-example 1/1 Running 0 22s [root@k8s-master1 ~]# kubectl describe pod pod-example Name: pod-example Namespace: default Priority: 0 PriorityClassName: <none> Node: 192.168.0.125/192.168.0.125 Start Time: Fri, 21 Dec 2018 14:17:47 +0800 Labels: app=nginx Annotations: <none> Status: Running IP: 172.17.19.2 Containers: nginx: Container ID: docker://5e33eacb41e9b4ffd072141af63209229543105feb804d23b72a09be9e414409 Image: nginx:1.15 Image ID: docker-pullable://nginx@sha256:5d32f60db294b5deb55d078cd4feb410ad88e6fe77500c87d3970eca97f54dba Port: <none> Host Port: <none> State: Running Started: Fri, 21 Dec 2018 14:17:48 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-7vs6s (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-7vs6s: Type: Secret (a volume populated by a Secret) SecretName: default-token-7vs6s Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Pulled 31s kubelet, 192.168.0.125 Container image "nginx:1.15" already present on machine Normal Created 31s kubelet, 192.168.0.125 Created container Normal Started 30s kubelet, 192.168.0.125 Started container
從私有鏡像倉庫拉取鏡像
參考:https://kubernetes.io/docs/concepts/containers/images/
查看docker登陸私有倉庫的憑據
[root@k8s-node01 ~]# cat .docker/config.json |base64 -w 0
ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjAuMTIyIjogewoJCQkiYXV0aCI6ICJiM0J6T2xCQWMzTjNNSEprIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wOS4wIChsaW51eCkiCgl9Cn0=
創建Secret
[root@k8s-master1 tomcat]# vim registry-pull-secret.yaml apiVersion: v1 kind: Secret metadata: name: registry-pull-secret data: .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjAuMTIyIjogewoJCQkiYXV0aCI6ICJiM0J6T2xCQWMzTjNNSEprIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wOS4wIChsaW51eCkiCgl9Cn0= type: kubernetes.io/dockerconfigjson [root@k8s-master1 tomcat]# kubectl create -f registry-pull-secret.yaml secret/registry-pull-secret created [root@k8s-master1 tomcat]# kubectl get secret NAME TYPE DATA AGE default-token-7vs6s kubernetes.io/service-account-token 3 44h registry-pull-secret kubernetes.io/dockerconfigjson 1 23s
創建pod時,設置從私有倉庫拉取鏡像
[root@k8s-master1 tomcat]# vim tomcat.yaml apiVersion: apps/v1beta2 kind: Deployment metadata: name: tomcat-deployment namespace: default spec: replicas: 3 selector: matchLabels: app: tomcat template: metadata: labels: app: tomcat spec: imagePullSecrets: - name: registry-pull-secret #secret 登陸倉庫的憑據 containers: - name: tomcat image: 192.168.0.122/ceba/tomcat #鏡像地址 imagePullPolicy: Always #設置每次創建pod都重新拉取鏡像 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: tomcat-service labels: app: tomcat spec: type: NodePort ports: - port: 80 targetPort: 8080 selector: app: tomcat
鏡像拉取策略
•IfNotPresent:默認值,鏡像在宿主機上不存在時才拉取
•Always:每次創建Pod 都會重新拉取一次鏡像
•Never:Pod 永遠不會主動拉取這個鏡像
查看拉取的鏡像正常啟動
[root@k8s-master1 tomcat]# kubectl get pod,svc,deploy NAME READY STATUS RESTARTS AGE pod/tomcat-deployment-6bb6864d4f-4xj82 1/1 Running 0 65s pod/tomcat-deployment-6bb6864d4f-drcjc 1/1 Running 0 47s pod/tomcat-deployment-6bb6864d4f-wmkxx 1/1 Running 0 45s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 44h service/tomcat-service NodePort 10.0.0.3 <none> 80:49014/TCP 8m20s NAME READY UP-TO-DATE AVAILABLE AGE deployment.extensions/tomcat-deployment 3/3 3 3 8m20s
資源限制
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
創建Pod的時候,可以指定計算資源(目前支持的資源類型有CPU和內存),即指定每個容器的資源請求(Request)和資源限制(Limit),資源請求是容器所需的最小資源需求,資源限制則是容器不能超過的資源上限。它們的大小關系是:0<=request<=limit<=infinity
Pod的資源請求就是Pod中容器資源請求之和。Kubernetes在調度Pod時,會根據Node中的資源總量(通過cAdvisor接口獲得),以及該Node上已使用的計算資源,來判斷該Node是否滿足需求。
資源請求能夠保證Pod有足夠的資源來運行,而資源限制則是防止某個Pod無限制地使用資源,導致其他Pod崩潰。特別是在公有雲場景,往往會有惡意軟件通過搶占內存來攻擊平台。
原理:Docker 通過使用Linux Cgroup來實現對容器資源的控制,具體到啟動參數上是--memory和--cpu-shares。Kubernetes中是通過控制這兩個參數來實現對容器資源的控制。
Pod和Container的資源請求和限制:
•spec.containers[].resources.limits.cpu
•spec.containers[].resources.limits.memory
•spec.containers[].resources.requests.cpu
•spec.containers[].resources.requests.memory
示例
以下Pod有兩個容器。每個Container都有0.25 cpu和64MiB內存的請求。每個Container的內存限制為0.5 cpu和128MiB。你可以說Pod有0.5 cpu和128 MiB內存的請求,並且限制為1 cpu和256MiB的內存。
[root@k8s-master1 ~]# vim pod1.yaml apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: wp image: wordpress resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
查看node節點資源使用情況
[root@k8s-master1 ~]# kubectl describe pod frontend | grep -A 3 Events Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 19m default-scheduler Successfully assigned default/frontend to 192.168.0.125 [root@k8s-master1 ~]# kubectl describe nodes 192.168.0.125 Name: 192.168.0.125 Roles: <none> Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/hostname=192.168.0.125 Annotations: node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Wed, 19 Dec 2018 09:54:14 +0800 Taints: <none> Unschedulable: false Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- MemoryPressure False Thu, 20 Dec 2018 17:26:03 +0800 Thu, 20 Dec 2018 10:29:48 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure False Thu, 20 Dec 2018 17:26:03 +0800 Thu, 20 Dec 2018 10:29:48 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure PIDPressure False Thu, 20 Dec 2018 17:26:03 +0800 Thu, 20 Dec 2018 10:29:48 +0800 KubeletHasSufficientPID kubelet has sufficient PID available Ready True Thu, 20 Dec 2018 17:26:03 +0800 Thu, 20 Dec 2018 10:29:48 +0800 KubeletReady kubelet is posting ready status OutOfDisk Unknown Wed, 19 Dec 2018 09:54:14 +0800 Wed, 19 Dec 2018 13:23:20 +0800 NodeStatusNeverUpdated Kubelet never posted node status. Addresses: InternalIP: 192.168.0.125 Hostname: 192.168.0.125 Capacity: cpu: 2 ephemeral-storage: 80699908Ki hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 3861520Ki pods: 110 Allocatable: cpu: 2 ephemeral-storage: 74373035090 hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 3759120Ki pods: 110 System Info: Machine ID: def36d2abcbe49839534858f6f1e13c5 System UUID: 86B24D56-709A-3467-6DDB-966B3B807949 Boot ID: 949f73c9-b14b-4e94-9137-78b2ac83d046 Kernel Version: 3.10.0-957.1.3.el7.x86_64 OS Image: CentOS Linux 7 (Core) Operating System: linux Architecture: amd64 Container Runtime Version: docker://18.9.0 Kubelet Version: v1.13.0 Kube-Proxy Version: v1.13.0 Non-terminated Pods: (3 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- default frontend 500m (25%) 1 (50%) 128Mi (3%) 256Mi (6%) 20m default tomcat-deployment-6bb6864d4f-drcjc 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3h25m default tomcat-deployment-6bb6864d4f-wmkxx 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3h25m Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 500m (25%) 1 (50%) memory 128Mi (3%) 256Mi (6%) ephemeral-storage 0 (0%) 0 (0%) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Starting 9m29s kube-proxy, 192.168.0.125 Starting kube-proxy. Normal Starting 8m42s kubelet, 192.168.0.125 Starting kubelet. Normal NodeHasSufficientMemory 8m42s kubelet, 192.168.0.125 Node 192.168.0.125 status is now: NodeHasSufficientMemory Normal NodeHasNoDiskPressure 8m42s kubelet, 192.168.0.125 Node 192.168.0.125 status is now: NodeHasNoDiskPressure Normal NodeHasSufficientPID 8m42s kubelet, 192.168.0.125 Node 192.168.0.125 status is now: NodeHasSufficientPID Normal NodeAllocatableEnforced 8m42s kubelet, 192.168.0.125 Updated Node Allocatable limit across pods Warning Rebooted 8m42s kubelet, 192.168.0.125 Node 192.168.0.125 has been rebooted, boot id: 949f73c9-b14b-4e94-9137-78b2ac83d046
健康檢查(Probe)
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
在實際生產環境中,想要使得開發的應用程序完全沒有bug,在任何時候都運行正常,幾乎 是不可能的任務。因此,我們需要一套管理系統,來對用戶的應用程序執行周期性的健康檢查和修復操作。這套管理系統必須運行在應用程序之外,這一點非常重要一一如果它是應用程序的一部分,極有可能會和應用程序一起崩潰。因此,在Kubernetes中,系統和應用程序的健康檢查是由Kubelet來完成的。
1、進程級健康檢查
最簡單的健康檢查是進程級的健康檢查,即檢驗容器進程是否存活。這類健康檢查的監控粒 度是在Kubernetes集群中運行的單一容器。Kubelet會定期通過Docker Daemon獲取所有Docker進程的運行情況,如果發現某個Docker容器未正常運行,則重新啟動該容器進程。目前,進程級的健康檢查都是默認啟用的。
2.業務級健康檢查
在很多實際場景下,僅僅使用進程級健康檢查還遠遠不夠。有時,從Docker的角度來看,容器進程依舊在運行;但是如果從應用程序的角度來看,代碼處於死鎖狀態,即容器永遠都無法正常響應用戶的業務為了解決以上問題,Kubernetes引人了一個在容器內執行的活性探針的概念,以支持用戶自己實現應用業務級的健康檢查。
Probe有以下兩種類型:
livenessProbe:如果檢查失敗,將殺死容器,根據Pod的restartPolicy來操作。
readinessProbe:如果檢查失敗,Kubernetes會把Pod從service endpoints中剔除。

Probe支持以下三種檢查方法:
- ExecAction:在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。
- TCPSocketAction:對指定端口上的容器的 IP 地址進行 TCP 檢查。如果端口打開,則診斷被認為是成功的。
- HTTPGetAction:對指定的端口和路徑上的容器的 IP 地址執行 HTTP Get 請求。如果響應的狀態碼大於等於200 且小於 400,則診斷被認為是成功的。
livenessProbe解析
[root@k8s-master1 ~]# kubectl explain pod.spec.containers.livenessProbe KIND: Pod VERSION: v1 RESOURCE: livenessProbe <Object> exec command 的方式探測 例如 ps 一個進程 failureThreshold 探測幾次失敗 才算失敗 默認是連續三次 periodSeconds 每次的多長時間探測一次 默認10s timeoutSeconds 探測超市的秒數 默認1s initialDelaySeconds 初始化延遲探測,第一次探測的時候,因為主程序未必啟動完成 tcpSocket 檢測端口的探測 httpGet http請求探測
exec探針的示例:
[root@k8s-master1 ~]# vim exec-liveness.yaml apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5 [root@k8s-master1 ~]# kubectl create -f exec-liveness.yaml pod/liveness-exec created [root@k8s-master1 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE frontend 2/2 Running 106 16h liveness-exec 1/1 Running 0 16s
在配置文件中,您可以看到Pod具有單個Container。該periodSeconds字段指定kubelet應每5秒執行一次活躍度探測。該initialDelaySeconds字段告訴kubelet它應該在執行第一次探測之前等待5秒。要執行探測,kubelet將cat /tmp/healthy在Container中執行命令。如果命令成功,則返回0,並且kubelet認為Container是活動且健康的。如果該命令返回非零值,則kubelet會終止Container並重新啟動它。
再等30秒,確認Container已重新啟動,RESTARTS已增加
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 57s default-scheduler Successfully assigned default/liveness-exec to 192.168.0.126 Normal Pulling 55s kubelet, 192.168.0.126 pulling image "busybox" Normal Pulled 47s kubelet, 192.168.0.126 Successfully pulled image "busybox" Normal Created 47s kubelet, 192.168.0.126 Created container Normal Started 47s kubelet, 192.168.0.126 Started container Warning Unhealthy 5s (x3 over 15s) kubelet, 192.168.0.126 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory [root@k8s-master1 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE frontend 2/2 Running 106 16h liveness-exec 1/1 Running 1 107s
pod生命周期
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
Pod 的 status 在信息保存在 PodStatus 中定義,其中有一個 phase 字段。
Pod 的相位(phase)是 Pod 在其生命周期中的簡單宏觀概述。該階段並不是對容器或 Pod 的綜合匯總,也不是為了做為綜合狀態機。
Pod 相位的數量和含義是嚴格指定的。除了本文檔中列舉的狀態外,不應該再假定 Pod 有其他的 phase值。
下面是 phase 可能的值:
- 掛起(Pending):Pod 已被 Kubernetes 系統接受,但有一個或者多個容器鏡像尚未創建。等待時間包括調度 Pod 的時間和通過網絡下載鏡像的時間,這可能需要花點時間。
- 運行中(Running):該 Pod 已經綁定到了一個節點上,Pod 中所有的容器都已被創建。至少有一個容器正在運行,或者正處於啟動或重啟狀態。
- 成功(Succeeded):Pod 中的所有容器都被成功終止,並且不會再重啟。
- 失敗(Failed):Pod 中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態退出或者被系統終止。
- 未知(Unknown):因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通信失敗。
下圖是Pod的生命周期示意圖,從圖中可以看到Pod狀態的變化。

故障排查
kubectl describe TYPE/NAME kubectl logs TYPE/NAME [-c CONTAINER] kubectl exec POD [-c CONTAINER] --COMMAND [args...]
