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
中同時運行多個容器是一種比較高級的用法。只有當你的容器需要緊密配合協作的時候才考慮用這種模式。例如,你有一個容器作為web
服務器運行,需要用到共享的volume
,有另一個“sidecar”
容器來從遠端獲取資源更新這些文件,如下圖所示:
網絡:每個
pod
都會被分配一個唯一的IP
地址。Pod
中的所有容器共享網絡空間,包括IP
地址和端口。Pod
內部的容器可以使用localhost
互相通信。Pod
中的容器與外界通信時,必須分配共享網絡資源(例如使用宿主機的端口映射)。存儲:可以為一個
Pod
指定多個共享的Volume
。Pod
中的所有容器都可以訪問共享的volume
。Volume
也可以用來持久化Pod
中的存儲資源,以防容器重啟后文件丟失。
注意:重啟
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
上。
無論是手動創建還是通過
Deployment
等控制器創建,Pod
對象總是應該處於其生命進程中以下幾個相位(phase
)之一。
掛起(
Pending
):API Server
創建了pod
資源對象已存入etcd
中,但它尚未被調度完成,或者仍處於從倉庫下載鏡像的過程中。運行中(
Running
):Pod
已經被調度至某節點,並且所有容器都已經被kubelet
創建完成。成功(
Succeeded
):Pod
中的所有容器都已經成功終止並且不會被重啟失敗(
Failed
):Pod
中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。即容器以非0
狀態退出或者被系統禁止。未知(
Unknown
):Api Server
無法正常獲取到Pod
對象的狀態信息,通常是由於無法與所在工作節點的kubelet
通信所致。
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
,事件將通過它被接受。
1)初始化容器必須運行完成直至結束,若某初始化容器運行失敗,那么
kubernetes
需要重啟它直到成功完成。(注意:如果pod
的spec.restartPolicy
字段值為“Never
”,那么運行失敗的初始化容器不會被重啟。)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
添加至端點列表中。
如果希望容器在探測失敗時被殺死並重新啟動,那么請指定一個存活探針,並指定
restartPolicy
為Always
或OnFailure
。如果要僅在探測成功時才開始向
Pod
發送流量,請指定就緒探針。在這種情況下,就緒探針可能與存活探針相同,但是spec
中的就緒探針的存在意味着Pod
將在沒有接收到任何流量的情況下啟動,並且只有在探針探測成功才開始接收流量。如果希望容器能夠自行維護,可以指定一個就緒探針,該探針檢查與存活探針不同的端點。
注意:如果只想在
Pod
被刪除時能夠排除請求,則不一定需要使用就緒探針;在刪除Pod
時,Pod
會自動將自身置於未完成狀態,無論就緒探針是否存在。當等待Pod
中的容器停止時,Pod
仍處於未完成狀態。
Always:但凡
Pod
對象終止就將其重啟,默認值OnFailure:僅在
Pod
對象出現錯誤時方才將其重啟Never:從不重啟
[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
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 ......
[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 ......
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
[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 端口探測
與存活性探測機制類似,就緒性探測是用來判斷容器就緒與否的周期性(默認周期為10秒鍾)操作,它用於探測容器是否已經初始化完成並可服務於客戶端請求,探測操作返回
”success“
狀態時,即為傳遞容器已經”就緒“的信號。就緒性探測也支持
Exec
、HTTPGet
和TCPSocket
三種探測方式,且各自的定義機制也都相同。但與存活性探測觸發的操作不同的是,探測失敗時,就緒探測不會殺死或重啟容器以保證其健康性,而是通知其尚未就緒,並觸發依賴於其就緒狀態的操作(例如,從Service
對象中移除此Pod
對象)以確保不會有客戶端請求接入此Pod
對象。
設置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