1. 程式人生 > 實用技巧 >Kubernetes中資源清單與Pod的生命週期(二)

Kubernetes中資源清單與Pod的生命週期(二)

一、資源清單

1,定義:

  在k8s中一般使用yaml格式的檔案來建立符合我們預期的資源,這樣的yaml被稱為資源清單。

  使用資源清單建立Pod:

kubectl apply -f nginx.yaml

  定義nginx.yaml內容為:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod #自定義的名稱只能用小寫字母使用 - 連線,駝峰 或者 _ 連線會報錯
  labels:
    app: nginx-app
    version: v1
spec:
  containers:
  - name: test-nginx
    image: nginx

2,資源清單常用欄位

欄位型別說明
apiVersion String k8s api 的版本,目前基本上是 v1。可以用 kubectl api-versions 命令檢視
kind String 定義的資源型別。比如定義為一個 Pod 或者 Deployment等等。
metadata Object 宣告元資料物件,固定值:metadata。
metadata.name String 元資料物件的名字。我們自己定義,比如該資源被kind定義為一個 Pod,那麼 Pod 的名稱就是在這裡定義。
metadata.namespace String 元資料物件的名稱空間。我們自己定義,不寫預設為 default。這裡定義的名稱空間必須是已存在的。
metadata.labels Object 標籤。
metadata.labels.app String 標籤名稱。
metadata.labels.version String 標籤版本號。
Spec Object 詳細定義物件。固定值:Spec。
spec.containers[] List 這裡是Spec物件的容器列表。即這個資源可以宣告多個容器。
spec.containers[].name String 容器的名字。建議不寫,會自動建立。如果此處寫了容器的名字,那麼 k8s 對該容器進行擴容時會報錯,因為不能存在相同名稱的容器。
spec.containers[].image String 容器使用的映象。
spec.containers[].imagePullPolicy String 映象拉取策略。如果不設定,預設為 Always。Always:每次都拉取新的映象;Never:僅使用本地映象,如果本地映象不存在則不使用該映象;IfNotPresent:如果本地沒有,就拉取新映象。
spec.containers[].command[] List 指定容器啟動命令,可以指定多個。不指定則預設為容器打包時使用的啟動命令,若指定了則會覆蓋原命令。
spec.containers[].args[] List 指定容器啟動命令引數,可傳入多個。
spec.containers[].workingDir String 指定容器的工作目錄。
spec.containers[] List 指定容器北部的儲存卷配置。
spec.containers[].volumeMounts[].name String 指定可以被容器掛載的儲存卷的名稱。
spec.containers[].volumeMounts[].mountPath String 指定可以被容器掛載的儲存卷的路徑。
spec.containers[].volumeMounts[].readOnly String 設定儲存卷路徑的讀寫模式,ture 或 false,預設為讀寫模式。
spec.containers[].ports[] List 指定容器需要用到的埠列表。
spec.containers[].ports[].name String 指定埠名稱。
spec.containers[].ports[].containerPort String 指定容器需要監聽的埠號。
spec.containers[].ports[].hostPort String 指定容器所在主機需要監聽的埠號,預設跟 containerPort 相同。設定了 hostPort ,那麼同一臺主機就無法啟動該容器的相同副本(同一主機埠號衝突)。
spec.containers[].ports[].protocol String 指定埠協議,支援 TCP 和 UDP,預設為 TCP。
spec.containers[].env[] List 指定容器執行前需要設定的環境變數列表。
spec.containers[].env[].name String 指定環境變數名稱。
spec.containers[].env[].value String 指定環境變數的值。
spec.containers[].resources Object 指定資源限制和資源請求的值。
spec.containers[].resources.limits Object 設定容器執行時的資源執行上限。
spec.containers[].resources.limits.cpu String 指定 CPU 的限制,單位為 core 數,將用於 docker run -- cpu-shares 引數。
spec.containers[].resources.limits.memory String 指定 MEM 記憶體的限制,單位為 MIB、GIB。
spec.restartPolicy String Pod 重啟策略。Always:Pod 一旦終止執行,不論是以什麼方式終止的,kubelet 都會重啟它;OnFailure:如果 Pod 的退出碼是0,kubelet 不會重啟,其它任何非0退出碼終止的,都會重啟;Never:Pod 終止後,kubelet 將退出碼報告給 master 並不會重啟該 Pod。
spec.nodeSelector Object 定義 Node 的 Label 過濾標籤,言外之意就是選擇在哪些 Node 上執行。以 key:value 格式指定。
spec.imagePullSecrets Object 定義 pull 映象時使用的 secret 名稱,格式為 name:secretkey 。
spec.hostNetwork Boolean 是否使用主機網路模式,預設值為 false。ture 表示使用宿主機網路,不使用 docker 網橋,並且將無法在同一臺宿主機上啟動第二個副本,否則端埠衝突。

3,排錯思路

  如果我們使用資源清單進行資源的建立時發生錯誤(某個容器啟動失敗),可以通過以下思路排查(以 Pod 為例):

# 檢視 Pod,-n 指定名稱空間名稱
kubectl get pod -n myspace -o wide

# 檢視 Pod 的詳細資訊(假設 Pod 名稱為 my-pod),查詢結果包括 Pod 中所有容器的執行情況,如果某個容器正常執行,其 State 屬性會是 Running
kubectl describe pod my-pod -n myspace

# 檢視 Pod 中容器的執行日誌,找出容器執行失敗的原因。-c 表示要檢視的容器,若 Pod 裡只有一個容器,不加也可以。
kubectl log my-pod -c my-nginx -n myspace

二、Pod定義

  每個Pod都會存在一個Pause根容器,是每一個Pod都會去執行的,container即為應用程式,所以Pod就是根容器Pause和應用程式container所組成,在Pod當中可以執行多個小的容器的。

1,Pod組成的意義

  •   使用Pause根容器可以防止由於將多個容器組成一個單元,當其中某個容器掛掉就會導致整個單元無法使用的情況發生。
  •   Pod可以執行過個container,這些container是共享Pause根容器的IP地址,也共享Pause的volume掛債卷,這樣既簡化了關聯業務容器之間的通訊問題,也很好的解決了容器之間共享的問題
  •   在Kubernetes中的Pod之間是可以進行相互通訊的,因為他們之間是一個二層交換的網路,所以不同主機之間Pod是可以進行相互訪問的

2,Pod型別劃分

  靜態Pod:不會將狀態存放到Etcd儲存資料庫中,而是放到了某個Node上的具體檔案當中,並且只有在這個Node上才能啟動執行

  普通Pod:普通Pod一旦被建立成功,那麼Pod狀態資訊就會放到Etcd儲存資料庫當中,狀態就會實時進行更新,就會被Master節點繫結到某個Node節點上進行排程和資源分配,隨後Pod就放到了指定的Node上面,相當於把一個應用例項化成了一組相關Docker容器並啟動去執行

3,Pod、容器與Node之間的關係

  •   在Node當中執行著Pod,而在Pod當中是包含著容器。
  •   在K8s當中都是以Docker映象釋出的,每個Pod可以理解為上面執行著多個映象,在預設情況下,比如在Pod當中某個容器停止了,K8s會自動檢查這個問題並重啟這個Pod(即將Pod當中的所有容器全部重啟)
  •   如果Pod所在的Node宕機了,K8s會把Pod排程到其他的Node節點上
  •   Pod當中是可以執行多個應用的,即支援多容器執行,每一個Pod相當於一個資源池,Pod當中的容器可以共享IP和檔案系統

三、Pod的生命週期

1,生命週期描述

初始化 Pod 環境:每一個 Pod 在建立時都會先初始化 Pod 執行所必須的條件。然後才繼續執行後面的容器初始化操作。比如會先建立 pause 這樣的容器。
Init C:Init Containers,初始化容器。
  我們在 Pod 裡面執行的容器,可能會依賴某些檔案或者環境才能夠正常啟動或執行。Init C 就是來完成這些檔案或者環境的建立的。
  Init C 可以有多個,也可以沒有。按順序執行,必須要等到前一個執行完成(必須是正常退出,否則會根據重啟策略判斷是否重新執行該 Init C),才會執行後一個。
  Init C 只存在容器初始化階段,Init C 執行完成之後會消亡,不參與 Pod 的後續流程。
  所有的 Init C 都正常結束後,Main C 主容器才開始建立並啟動。
Main C:主容器。即執行在 Pod 裡提供服務的容器。主容器一旦停止執行,那麼 Pod 也就停止了。需要注意的是一個 Pod 裡面可以有很多個 Main C,且每個 Main C 都有自己的 Init C 等。
start:Main C 建立之前執行的操作,可以是一條命令或一個指令碼。
stop:Main C 結束之後執行的操作,可以是一條命令或一個指令碼。
readiness:容器就緒檢測,可以指定在容器啟動之後的某個時間點執行,比如 10 秒後。只有當 readiness 正常執行完成,該 Pod 才會顯示為就緒狀態。
liveness:容器是否正在執行。

2,InitC

  Init容器與普通的容器非常像,但是:1,Init容器總是執行到成功為止;2,每個Init容器必須都在下一個Init容器啟動之前成功完成。

InitC簡單例項init.yaml:(kubectlcreate -f init.yaml)

apiVersion: v1
kind: Pod #Pod型別
metadata:
  name: myapp-pod #Pod名稱
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container #主容器
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers: #InitC
  - name: init-myservice #率先啟動的Init容器
    image: busybox
    command: [ 'sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']  #監控myservice
  - name: init-mydb #在主容器之前啟動,在init-myservice正常退出之後啟動。
    image: busybox
    command: [ 'sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;'] #監控mydb

myservice.yaml :(kubectlcreate -f myservice.yaml)

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

mydb.yaml :(kubectlcreate -f myservice.yaml)

apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

InitC特點:

  • 在 Pod 啟動過程中,Init 容器會按順序在網路和資料卷初始化之後啟動(即在 pause 容器之後啟動)。每個容器必須在下一個 容器啟動之前成功退出。
  • 如果由於執行時或失敗退出,將導致容器啟動失敗,它會根據 Pod 的 restartPolicy 指定的策略進行重試。
  • 在所有的 Init 容器沒有成功之前,Pod 將不會變成 Ready 狀態。Init 容器的埠將不會在 Service 中進行聚集。正在初始化中的 Pod 處於 Pending 狀態,但應該會將 Initializing 狀態設定為true。
  • 如果 Pod 重啟,所有 Init 容器必須重新執行。
  • 對 Init 容器 spec 的修改被限制在容器 image 欄位,修改其他欄位都不會生效。更改 Init 容器的 image 欄位,等價於重啟該Pod。
  • Init 容器具有應用容器的所有欄位。除了 readinessProbe,因為 Init 容器無法定義不同於完成 (conpletion)的就緒(readiness)之外的其他狀態。
  • 在 Pod 中的每個 app 和 Init 容器的名稱必須唯一;與任何其它容器共享同一個名稱,會在驗證時丟擲錯誤。

3,探針

  探針是由 kubelet 對容器執行的定期診斷。要執行診斷,kubelet 呼叫由容器實現的 Handler。有三種類型的處理程式:

    •   ExecAction:在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。
    •   TCPSocketAction:對指定埠上的容器的 IP 地址進行 TCP 檢查。如果埠開啟,則診斷被認為是成功的。
    •   HTTPGetAction:對指定的埠和路徑上的容器的 IP 地址執行 HTTPGet 請求。如果響應的狀態碼大於等於 200 且小於 400,則診斷被認為是成功的。

  每次探測都將獲得以下三種結果之一:

    •   成功:容器通過了診斷。
    •   失敗:容器未通過診斷。
    •   未知:診斷失敗,因此不會採取任何行動。

  探針有兩種型別:

  • readinessProbe:探測容器是否準備好服務請求(即是否就緒 [READY])。如果就緒探測失敗,端點控制器將從與 Pod 匹配的所有Service 的端點中刪除該 Pod 的 IP 地址。初始延遲之前的就緒狀態預設為 Failure 。如果容器不提供就緒探針,則預設狀態為Success。
  • livenessProbe:探測容器是否正常執行。如果存活探測失敗,則 kubelet 會殺死容器,並且容器將受到其重啟策略的影響。如果容器不提供存活探針,則預設狀態為 Success。

readinessProbe例項:採用HTTPGetAction(readness-httpget.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: readness-httpget-pod
spec:
  containers:
  - name: readness-httpget-container
    image: hub.xcc.com/library/mynginx:v1
    imagePullPolicy: IfNotPresent #映象拉取策略
    readinessProbe:
      httpGet: #探測方式
        port: 80
        path: /index1.html #檢測路徑
      initialDelaySeconds: 1 #容器啟動後1s開始探測
      periodSeconds: 3 #如果檢測失敗,每3s繼續探測,直到檢測成功或者達到最大檢測值

livenessProbe例項:採用ExecAction(liveness-exec.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: lineness-exec-container
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'touch /tmp/live; sleep 50; rm -rf /tmp/live; sleep 3600']
    livenessProbe:
      exec:
        command: ['test', '-e', '/tmp/live']
      initialDelaySeconds: 1
      periodSeconds: 3

4,Podhook

  Pod hook(鉤子)是由 Kubernetes 管理的 kubelet 發起的,當容器中的程序啟動前或者容器中的程序終止之前執行,這是包含在容器的生命週期之中,也就是上面Pod 生命週期中提到的 start 和 stop。可以同時為 Pod 中的所有容器都配置 hook。

  Hook的型別包括兩種:

    •   exec:執行一段命令。
    •   HTTP:傳送HTTP請求。
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: hub.xcc.com/library/mynginx:v1
    lifecycle:
      postStart:
        exec:
          command: [......]
      preStop:
        exec:
          command: [......]

5,Pod相位(phase)

  Pod 的 status 欄位是一個 PodStatus 物件,PodStatus 中有一個 phase 欄位。

  Pod 的相位(phase)是 Pod 在其生命週期中的簡單巨集觀概述。該階段並不是對容器或 Pod 的綜合彙總,也不是為了做為綜合狀態機。

  Pod 相位的數量和含義是嚴格指定的,以下是當前 Pod 相位的所有值:

    •   掛起(Pending):Pod 已被 Kubernetes 系統接受,但有一個或者多個容器映象尚未建立。等待時間包括排程 Pod 的時間和通過網路下載映象的時間。
    •   執行中(Running):該 Pod 己經繫結到了一個節點上,Pod 中所有的容器都己被建立。至少有一個容器正在執行,或者正處於啟動或重啟狀態。
    •   成功(Succeeded):Pod 中的所有容器都被成功終止,並且不會再重啟。
    •   失畋(Failed):Pod 中的所有容器都己終止了,並且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態退出或者被系統終止。
    •   未知(Unknown):因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通訊失敗。