什么是Pod
Pod是kubernetes中你可以創建和部署的最小也是最簡的單位,Pod代表著集群中運行的行程,
Pod中封裝著應用的容器(有的情況下是好幾個容器),存盤、獨立的網路IP,管理容器如何運行的策略選項,Pod代表著部署的一個單位:kubernetes中應用的一個實體,可能由一個或者多個容器組合在一起共享資源,
Docker是kubernetes中最常用的容器運行時,但是Pod也支持其他容器運行時,在
Kubernetes集群中Pod有如下兩種方式:
一個Pod中運行一個容器,“每個
Pod中一個容器”的模式是最常見的用法;在這種使用方式中,你可以把Pod想象成單個容器的封裝,Kubernetes管理的是Pod而不是直接管理容器,在一個Pod中同時運行多個容器,一個
Pod也可以同時封裝幾個需要緊密耦合互相協作的容器,它們之間共享資源,這些在同一個Pod中的容器可以互相協作成為一個service單位——一個容器共享檔案,另一個“sidecar”容器來更新這些檔案,Pod將這些容器的存盤資源作為一個物體來管理,
Pod中共享的環境包括Linux的namespace、cgroup和其他可能的隔絕環境,這一點跟Docker容器一致,在Pod的環境中,每個容器可能還有更小的子隔離環境,
Pod中的容器共享IP地址和埠號,它們之間可以通過localhost互相發現,它們之間可以通過行程間通信,例如SystemV信號或者POSIX共享記憶體,不同Pod之間的容器具有不同的IP地址,不能直接通過IPC通信,
Pod中的容器也有訪問共享volume的權限,這些volume會被定義成pod的一部分并掛載到應用容器的檔案系統中,就像每個應用容器,
pod被認為是臨時(非持久的)物體,在Pod的生命周期中討論過,pod被創建后,被分配一個唯一的ID(UID),調度到節點上,并一致維持期望的狀態直到被終結(根據重啟策略)或者被洗掉,如果node死掉了,分配到了這個node上的pod,在經過一個超時時間后會被重新調度到其他node節點上,一個給定的pod(如UID定義的)不會被“重新調度”到新的節點上,而是被一個同樣的pod取代,如果期望的話甚至可以是相同的名字,但是會有一個新的UID,
Pod中如何管理多個容器
Pod中可以同時運行多個行程(作為容器運行)協同作業,同一個Pod中的容器會自動的分配到同一個node上,同一個Pod中的容器共享資源、網路環境和依賴,它們總是被同時調度,注意在一個
Pod中同時運行多個容器是一種比較高級的用法,只有當你的容器需要緊密配合協作的時候才考慮用這種模式,例如,你有一個容器作為web服務器運行,需要用到共享的volume,有另一個“sidecar”容器來從遠端獲取資源更新這些檔案,如下圖所示:

Pod中可以共享兩種資源:網路和存盤網路:每個
pod都會被分配一個唯一的IP地址,Pod中的所有容器共享網路空間,包括IP地址和埠,Pod內部的容器可以使用localhost互相通信,Pod中的容器與外界通信時,必須分配共享網路資源(例如使用宿主機的埠映射),存盤:可以為一個
Pod指定多個共享的Volume,Pod中的所有容器都可以訪問共享的volume,Volume也可以用來持久化Pod中的存盤資源,以防容器重啟后檔案丟失,
使用Pod
你很少會直接在
kubernetes中創建單個Pod,因為Pod的生命周期是短暫的,用后即焚的物體,當Pod被創建后(不論是由你直接創建還是被其它Controller),都會被Kubernetes調度到集群的Node上,直到Pod的行程終止、被刪掉、因為缺少資源而被驅逐、或者Node故障之前這個Pod都會一直保持在那個Node上,注意:重啟
Pod中的容器跟重啟Pod不是一回事,Pod只提供容器的運行環境并保持容器的運行狀態,重啟容器不會造成Pod重啟,
Pod不會自愈,如果Pod運行的Node故障,或者是調度器本身故障,這個Pod就會被洗掉,同樣的,如果Pod所在Node缺少資源或者Pod處于維護狀態,Pod也會被驅逐,Kubernetes使用更高級的稱為Controller的抽象層,來管理Pod實體,雖然可以直接使用Pod,但是在Kubernetes中通常是使用Controller來管理Pod的,
Controller可以創建和管理多個Pod,提供副本管理、滾動升級和集群級別的自愈能力,例如,如果一個Node故障,Controller就能自動將該節點上的Pod調度到其他健康的Node上,
Pod物件的生命周期
官方檔案
中文檔案
Pod物件自從其創建開始至其終止退出的時間范圍稱為其生命周期,在這段時間中,Pod會處于多種不同的狀態,并執行一些操作;其中,創建主容器(main container)為必需的操作,其他可選的操作還包括運行初始化容器(init container)、容器啟動后鉤子(post start hook)、容器的存活性探測(liveness probe)、就緒性探測(readiness probe)以及容器終止前鉤子(pre stop hook)等,這些操作是否執行則取決于Pod的定義,如下圖所示:

Pod phase
Pod的status欄位是一個PodStatus的物件,PodStatus中有一個phase欄位,無論是手動創建還是通過
Deployment等控制器創建,Pod物件總是應該處于其生命行程中以下幾個相位(phase)之一,
掛起(
Pending):API Server創建了pod資源物件已存入etcd中,但它尚未被調度完成,或者仍處于從倉庫下載鏡像的程序中,運行中(
Running):Pod已經被調度至某節點,并且所有容器都已經被kubelet創建完成,成功(
Succeeded):Pod中的所有容器都已經成功終止并且不會被重啟失敗(
Failed):Pod中的所有容器都已終止了,并且至少有一個容器是因為失敗終止,即容器以非0狀態退出或者被系統禁止,未知(
Unknown):Api Server無法正常獲取到Pod物件的狀態資訊,通常是由于無法與所在作業節點的kubelet通信所致,

Pod的創建程序
Pod是kubernetes的基礎單元,理解它的創建程序對于了解系統運作大有裨益,如下圖描述了一個Pod資源物件的典型創建程序,

用戶通過
kubectl或其他API客戶端提交了Pod Spec給API Server,
API Server嘗試著將Pod物件的相關資訊存入etcd中,待寫入操作執行完成,API Server即會回傳確認資訊至客戶端,
API Server開始反映etcd中的狀態變化,所有的
kubernetes組件均使用“watch”機制來跟蹤檢查API Server上的相關的變動,
kube-scheduler(調度器)通過其“watcher”覺察到API Server創建了新的Pod物件但尚未系結至任何作業節點,
kube-scheduler為Pod物件挑選一個作業節點并將結果資訊更新至API Server,調度結果資訊由
API Server更新至etcd存盤系統,而且API Server也開始反映此Pod物件的調度結果,
Pod被調度到的目標作業節點上的kubelet嘗試在當前節點上呼叫Docker啟動容器,并將容器的結果狀態回傳送至API Server,
API Server將Pod狀態資訊存入etcd系統中,在
etcd確認寫入操作成功完成后,API Server將確認資訊發送至相關的kubelet,事件將通過它被接受,
Pod生命周期中的重要行為
1)初始化容器
初始化容器(
init container)即應用程式的主容器啟動之前要運行的容器,常用于為主容器執行一些預置操作,它們具有兩種典型特征,1)初始化容器必須運行完成直至結束,若某初始化容器運行失敗,那么
kubernetes需要重啟它直到成功完成,(注意:如果pod的spec.restartPolicy欄位值為“Never”,那么運行失敗的初始化容器不會被重啟,)2)每個初始化容器都必須按定義的順序串行運行,
2)容器探測
容器探測(
container probe)是Pod物件生命周期中的一項重要的日常任務,它是kubelet對容器周期性執行的健康狀態診斷,診斷操作由容器的處理器(handler)進行定義,Kubernetes支持三種處理器用于Pod探測:
ExecAction:在容器內執行指定命令,并根據其回傳的狀態碼進行診斷的操作稱為Exec探測,狀態碼為0表示成功,否則即為不健康狀態,
TCPSocketAction:通過與容器的某TCP埠嘗試建立連接進行診斷,埠能夠成功打開即為正常,否則為不健康狀態,
HTTPGetAction:通過向容器IP地址的某指定埠的指定path發起HTTP GET請求進行診斷,回應碼為2xx或3xx時即為成功,否則為失敗,任何一種探測方式都可能存在三種結果:
“Success”(成功)、“Failure”(失敗)、“Unknown”(未知),只有success表示成功通過檢測,
容器探測分為兩種型別:
存活性探測(livenessProbe):用于判定容器是否處于“運行”(
Running)狀態;一旦此類檢測未通過,kubelet將殺死容器并根據重啟策略(restartPolicy)決定是否將其重啟;未定義存活檢測的容器的默認狀態為“Success”,就緒性探測(readinessProbe):用于判斷容器是否準備就緒并可對外提供服務;未通過檢測的容器意味著其尚未準備就緒,端點控制器(如
Service物件)會將其IP從所有匹配到此Pod物件的Service物件的端點串列中移除;檢測通過之后,會再將其IP添加至端點串列中,
什么時候使用存活(liveness)和就緒(readiness)探針?
如果容器中的行程能夠在遇到問題或不健康的情況下自行崩潰,則不一定需要存活探針,
kubelet將根據Pod的restartPolicy自動執行正確的操作,如果希望容器在探測失敗時被殺死并重新啟動,那么請指定一個存活探針,并指定
restartPolicy為Always或OnFailure,如果要僅在探測成功時才開始向
Pod發送流量,請指定就緒探針,在這種情況下,就緒探針可能與存活探針相同,但是spec中的就緒探針的存在意味著Pod將在沒有接收到任何流量的情況下啟動,并且只有在探針探測成功才開始接收流量,如果希望容器能夠自行維護,可以指定一個就緒探針,該探針檢查與存活探針不同的端點,
注意:如果只想在
Pod被洗掉時能夠排除請求,則不一定需要使用就緒探針;在洗掉Pod時,Pod會自動將自身置于未完成狀態,無論就緒探針是否存在,當等待Pod中的容器停止時,Pod仍處于未完成狀態,
容器的重啟策略
PodSpec中有一個restartPolicy欄位,可能的值為Always、OnFailure和Never,默認為Always,restartPolicy適用于Pod中的所有容器,而且它僅用于控制在同一節點上重新啟動Pod物件的相關容器,首次需要重啟的容器,將在其需要時立即進行重啟,隨后再次需要重啟的操作將由kubelet延遲一段時間后進行,且反復的重啟操作的延遲時長依次為10秒、20秒、40秒... 300秒是最大延遲時長,事實上,一旦系結到一個節點,Pod物件將永遠不會被重新系結到另一個節點,它要么被重啟,要么終止,直到節點發生故障或被洗掉,
Always:但凡
Pod物件終止就將其重啟,默認值OnFailure:僅在
Pod物件出現錯誤時方才將其重啟Never:從不重啟
Pod存活性探測示例
設定exec探針示例
[root@k8s-master ~]# vim manfests/liveness-exec.yaml apiVersion: v1 kind: Pod metadata: name: liveness-exec-pod namespace: default labels: test: liveness-exec spec: containers: - name: liveness-exec-container image: busybox:latest imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600"] livenessProbe: exec: command: ["test","-e","/tmp/healthy"] initialDelaySeconds: 1 periodSeconds: 3 [root@k8s-master ~]# kubectl create -f manfests/liveness-exec.yaml #創建pod pod/liveness-exec-pod created [root@k8s-master ~]# kubectl get pods #查看pod NAME READY STATUS RESTARTS AGE liveness-exec-pod 1/1 Running 0 6s #等待一段時間后再次查看其狀態 [root@k8s-master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE liveness-exec-pod 1/1 Running 2 2m46s
上面的資源清單中定義了一個pod物件,基于busybox鏡像啟動一個運行“touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 3600"命令的容器,此命令在容器啟動時創建了/tmp/healthy檔案,并于60秒之后將其洗掉,存活性探針運行”test -e /tmp/healthy"命令檢查/tmp/healthy檔案的存在性,若檔案存在則回傳狀態碼0,表示成功通過測驗,在60秒內使用“kubectl describe pods/liveness-exec-pod”查看其詳細資訊,其存活性探測不會出現錯誤,而超過60秒之后,再執行該命令查看詳細資訊,可以發現存活性探測出現了故障,并且還可通過“kubectl get pods"查看該pod的重啟的相關資訊,
設定HTTP探針示例
基于
HTTP的探測(HTTPGetAction)向目標容器發起一個HTTP請求,根據其回應碼進行結果判定,回應碼如2xx或3xx時表示測驗通過,通過該命令”# kubectl explain pod.spec.containers.livenessProbe.httpGet“查看httpGet定義的欄位host <string>:請求的主機地址,默認為Pod IP,也可以在httpHeaders中使用“Host:”來定義, httpHeaders <[]Object>:自定義的請求報文首部, port <string>:請求的埠,必選欄位, path <string>:請求的HTTP資源路徑,即URL path, scheme <string>:建立連接使用的協議,僅可為HTTP或HTTPS,默認為HTTP,
[root@k8s-master ~]# vim manfests/liveness-httpget.yaml apiVersion: v1 kind: Pod metadata: name: liveness-http namespace: default labels: test: liveness spec: containers: - name: liveness-http-demo image: nginx:1.12 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Healthz > /usr/share/nginx/html/healthz"] livenessProbe: httpGet: path: /healthz port: http scheme: HTTP [root@k8s-master ~]# kubectl create -f manfests/liveness-httpget.yaml #創建pod pod/liveness-http created [root@k8s-master ~]# kubectl get pods #查看pod NAME READY STATUS RESTARTS AGE liveness-http 1/1 Running 0 7s [root@k8s-master ~]# kubectl describe pods/liveness-http #查看liveness-http詳細資訊 ...... Containers: liveness-http-demo: ...... Port: 80/TCP Host Port: 0/TCP State: Running Started: Mon, 09 Sep 2019 15:43:29 +0800 Ready: True Restart Count: 0 ......
上面清單中定義的httpGet測驗中,通過lifecycle中的postStart hook創建了一個專用于httpGet測驗的頁面檔案healthz,請求的資源路徑為"/healthz",地址默認為Pod IP,埠使用了容器中頂一個埠名稱http,這也是明確了為容器指明要暴露的埠的用途之一,并查看健康狀態檢測相關的資訊,健康狀態檢測正常時,容器也將正常運行,下面通過“kubectl exec”命令進入容器洗掉由postStart hook創建的測驗頁面healthz,再次查看容器狀態
[root@k8s-master ~]# kubectl exec pods/liveness-http -it -- /bin/sh #進入到上面創建的pod中 # rm -rf /usr/share/nginx/html/healthz #洗掉healthz測驗頁面 # [root@k8s-master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE liveness-http 1/1 Running 1 10m [root@k8s-master ~]# kubectl describe pods/liveness-http ...... Containers: liveness-http-demo: ...... Port: 80/TCP Host Port: 0/TCP State: Running Started: Mon, 09 Sep 2019 15:53:04 +0800 Last State: Terminated Reason: Completed Exit Code: 0 Started: Mon, 09 Sep 2019 15:43:29 +0800 Finished: Mon, 09 Sep 2019 15:53:03 +0800 Ready: True Restart Count: 1 ......
通過上面測驗可以看出,當發起http請求失敗后,容器將被殺掉后進行了重新構建,
設定TCP探針
基于
TCP的存活性探測(TCPSocketAction)用于向容器的特定埠發起TCP請求并建立連接進行結果判定,連接建立成功即為通過檢測,相比較來說,它比基于HTTP的探測要更高效、更節約資源,但精確度略低,畢竟連接建立成功未必意味著頁面資源可用,通過該命令”# kubectl explain pod.spec.containers.livenessProbe.tcpSocket“查看tcpSocket定義的欄位host <string>:請求連接的目標IP地址,默認為Pod IP port <string>:請求連接的目標埠,必選欄位
[root@k8s-master ~]# vim manfests/liveness-tcp.yaml apiVersion: v1 kind: Pod metadata: name: liveness-tcp-pod namespace: default labels: test: liveness-tcp spec: containers: - name: liveness-tcp-demo image: nginx:1.12 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 livenessProbe: tcpSocket: port: http
上面清單中定義的tcpSocket測驗中,通過向容器的80埠發起請求,如果埠正常,則表明正常運行,
livenessProbe行為屬性
[root@k8s-master ~]# kubectl explain pods.spec.containers.livenessProbe KIND: Pod VERSION: v1 RESOURCE: livenessProbe <Object> exec command 的方式探測,例如 ps 一個行程是否存在 failureThreshold 探測幾次失敗 才算失敗, 默認是連續三次 initialDelaySeconds 初始化延遲探測,即容器啟動多久之后再開始探測,默認為0秒 periodSeconds 每隔多久探測一次,默認是10秒 successThreshold 處于失敗狀態時,探測操作至少連續多少次的成功才算通過檢測,默認為1秒 timeoutSeconds 存活性探測的超時時長,默認為1秒 httpGet http請求探測 tcpSocket 埠探測
Pod就緒性探測示例
Pod物件啟動后,容器應用通常需要一段時間才能完成其初始化程序,例如加載配置或資料,甚至有些程式需要運行某類的預熱程序,若在這個階段完成之前即接入客戶端的請求,勢必會等待太久,因此,這時候就用到了就緒性探測(readinessProbe),與存活性探測機制類似,就緒性探測是用來判斷容器就緒與否的周期性(默認周期為10秒鐘)操作,它用于探測容器是否已經初始化完成并可服務于客戶端請求,探測操作回傳
”success“狀態時,即為傳遞容器已經”就緒“的信號,就緒性探測也支持
Exec、HTTPGet和TCPSocket三種探測方式,且各自的定義機制也都相同,但與存活性探測觸發的操作不同的是,探測失敗時,就緒探測不會殺死或重啟容器以保證其健康性,而是通知其尚未就緒,并觸發依賴于其就緒狀態的操作(例如,從Service物件中移除此Pod物件)以確保不會有客戶端請求接入此Pod物件,
這里只是示例http探針示例,不論是httpGet還是exec還是tcpSocket和存活性探針類似,
設定HTTP探針示例
#終端1: [root@k8s-master ~]# vim manfests/readiness-httpget.yaml #編輯readiness-httpget測驗pod的yaml檔案 apiVersion: v1 kind: Pod metadata: name: readiness-http namespace: default labels: test: readiness-http spec: containers: - name: readiness-http-demo image: nginx:1.12 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 readinessProbe: httpGet: path: /index.html port: http scheme: HTTP [root@k8s-master ~]# kubectl create -f manfests/readiness-httpget.yaml #創建pod pod/readiness-http created [root@k8s-master ~]# kubectl get pods 查看pod狀態 NAME READY STATUS RESTARTS AGE liveness-tcp-pod 1/1 Running 1 7d18h readiness-http 1/1 Running 0 7s #新打開一個終端2進入到容器里面 [root@k8s-master ~]# kubectl exec pods/readiness-http -it -- /bin/sh #進入上面創建的pod # rm -f /usr/share/nginx/html/index.html #洗掉nginx的主頁面檔案 # ls /usr/share/nginx/html 50x.html # #回到終端1上面查看pod狀態 [root@k8s-master ~]# kubectl get pods #查看pod狀態 NAME READY STATUS RESTARTS AGE liveness-tcp-pod 1/1 Running 1 7d18h readiness-http 0/1 Running 0 2m44s
通過上面測驗可以看出,當我們洗掉了nginx主頁檔案后,readinessProbe發起的測驗就會失敗,此時我們再查看pod的狀態會發現并不會將pod洗掉重新啟動,只是在READY欄位可以看出,當前的Pod處于未就緒狀態,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/57251.html
標籤:其他
