K8S--資源控制器&Pod詳解&探針


一、資源控制器

  K8S中內建了很多的控制器,這些控制器都是用來空指Pod的具體狀態和行為。從控制器的角度來說,Pod可以分為自主式Pod和控制器管理的Pod。自主式的Pod一旦退出,該類型的Pod就不會被重新創建,而控制器管理的Pod,在控制器的生命周期里,始終要維持Pod的副本數量。

  常用的控制器,在K8S--架構及基本概念中已經說過,主要有ReplicationController(舊版本)、ReplaSet、Deployment、DaemonSet、Job、CronJob,具體的概念就不再說多,直接上代碼示例。

  對於RC、RS、Deployment的配置可以參見K8S--實戰

(一)DaemonSet

  DaemonSet確保全部Node上運行一個Pod副本,當有Node加入集群時,也會為他們新增一個pod,當有Node從集群中被移除時,這些pod也會被回收,刪除DaemonSet將會刪除其創建的所有pod。最典型的場景就是每個Pod里面都有服務在運行,需要收集服務運行日志,但是Pod是由K8S自動創建或刪除的,因此需要使用DaemonSet來設定在每一個Pod中進行日志收集。

#確保只運行一個副本,運行在集群中每一個節點上。(也可以部分節點上只運行一個且只有一個pod副本,如監控ssd硬盤)
# kubectl explain ds
# vim  filebeat.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-deamon
  namespace: default
  labels: 
    app: daemonset
spec:
  selector:
    matchLabels:
      app: my-daemonset
  template:
    metadata:
      labels:
        app: my-daemonset
    spec:
      containers:
      - name: daemon-app
        image: nginx:1.16

  使用:kubectl apply -f xxx.yaml執行該配置文件即可,就會在每個節點中創建一個名為my-deamon的pod。

  然后可以使用:kubectl get daemonset查看在運行的daemonset
      

  實際上,K8S自己就在用deamonSet在運行組件系統。

      

 (二)Job

  Job負責處理任務,即僅執行一次的任務,它保證批處理任務的一個或多個Pod成功結束。而CronJob則就是在Job上加上了時間調度。

# 我們用Job這個資源對象來創建一個任務,我們定一個Job來執行一個倒計時的任務,定義YAML文件:
apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
spec:
  template:
    metadata:
      name: job-demo
    spec:
      restartPolicy: Never
      containers:
      - name: counter
        image: busybox
        command:
        - "bin/sh"
        - "-c"
        - "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"

  上面的配置文件是創建了一個job,並從9輸出到1。

  使用命令執行配置文件: kubectl apply -f job.yaml

  查看pod:

      

   可以看到job已經執行完成,然后查看輸出日志:

      

   可以看到已經正常打印。

(三)CronJob

  CronJob其實就是在Job的基礎上加上了時間調度,我們可以:在給定的時間點運行一個任務,也可以周期性地在給定時間點運行。這個實際上和我們Linux中的crontab就非常類似了。

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cronjob-demo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: hello
            image: busybox
            args:
            - "bin/sh"
            - "-c"
            - "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"

  執行該配置文件: kubectl apply -f cronjob.yaml

  可以使用以下命令查看:

# 查詢cronjob
kubectl get cronjob
# 查詢jon ,cronjon會循環多個job
kubectl get job 
# 實時監控查詢job 
kubectl get job -w

二、Pod

(一)Pod生命周期

  Pod的status屬性描述了Pod處於生命周期的階段。

階段 描述
Pending Pod 已被 Kubernetes 接受,但尚未創建一個或多個容器鏡像。這包括被調度之前的時間以及通過網絡下載鏡像所花費的時間,執行需要一段時間。
Running Pod 已經被綁定到了一個節點,所有容器已被創建。至少一個容器正在運行,或者正在啟動或重新啟動。
Succeeded 所有容器成功終止,也不會重啟。
Failed 所有容器終止,至少有一個容器以失敗方式終止。也就是說,這個容器要么已非 0 狀態退出,要么被系統終止。
Unknown 由於一些原因,Pod 的狀態無法獲取,通常是與 Pod 通信時出錯導致的。

  重啟策略:

  對於Pod的重啟策略,有Always、OnFailure、Never三種,默認為Always,其中Always表示容器失敗時,kubectl會自動重啟該容器,Onfailure表示容器終止運行且退出碼不為0時重啟,Never表示無論什么狀態,kubectl都不會重啟該容器。

  失敗的容器由kubectl以五分鍾為上限的指數延遲重新啟動(10秒、20秒、40秒),並在成功執行十分鍾后重置。

  Pod的生命周期如下圖所示:

       

     流程說明:

      (1)初始化容器階段,初始化Pod中的每一個容器,他們是串行執行的,執行完就退出了。

      (2)啟動主容器main container

      (3)在main container剛剛啟動之后可以執行post start命令(勾子程序)

      (4)在整個main container執行的過程中可以做兩類探測:liveness probe(存活探測)和readiness probe(就緒探測)

      (5)在main container結束前可以執行pre stop命令(勾子程序)

    配置啟動后勾子(post start)和終止前勾子(pre stop):

      post start:容器創建之后立即執行,如果失敗了就會按照重啟策略重啟容器

      pre stop:容器終止前立即執行,執行完成后容器將成功終止

    可以使用以下命令查看post start和pre stop的設置格式:

kubectl explain pod.spec.containers.lifecycle.preStop
kubectl explain pod.spec.containers.lifecycle.postStart

(二)Pod init

  1、init容器

  Pod能夠持有多個容器,應用運行在容器里面,但是它也可能有一個或多個先於應用程序啟動的init容器,init容器與普通容器非常相似,只有以下兩點區別:

    (1)init容器總是運行到成功完成為止

    (2)每個init容器都必須在下一個init容器啟動之前成功完成

  如果pod的init容器失敗,K8S會不斷的重啟該Pod,直到init容器成功為止,不過也有特里,就是如果將Pod的重啟策略restartPolicy設置為Never,他就不會重啟了。

  2、init的作用

  因為init容器與應用程序容器的鏡像是分離的,所以他們啟動相關代碼具有以下優勢:

    (1)它們可以包含並運行實用工具,但是處於安全考慮,一般不建議在應用程序容器鏡像中包含這些實用工具

    (2)他們可以包含實用工具和定制化代碼來安裝,但是不能出現在現有應用程序鏡像中,例如創建鏡像沒有必要FROM另一個鏡像,只需要在安裝過程中使用類似sed、awk、python或dig這樣的工具

    (3)應用程序鏡像可以分離出創建和部署的角色,而沒有必要聯合他們構建一個單獨的鏡像。

    (4)init容器使用LinuxNamespace,所以相對應用程序來說,其具有不同文件系統視圖,因此,他們能夠具有訪問Secret的權限,而應用程序容器則不能。

    (5)他們必須在應用程序啟動之前運行完成,而應用程序是並行運行的,所以init容器能夠提供一種簡單的阻塞或延遲應用容器啟動的方法,直到滿足了一組先決條件。

  3、特殊說明

    (1)在pod啟動過程中,init容器會按照順序在網絡和數據卷初始化之后啟動(網絡和數據卷初始化是在pause容器中),每個容器必須在下一個容器啟動前成功退出

    (2)如果由於運行時或失敗退出,將導致容器啟動失敗,它會根據Pod的restartPolicy指定的重啟策略來進行處理

    (3)在所有的init容器沒有成功之前,Pod將不會變成Ready狀態,init容器的端口將不會在Service中進行聚集,正在初始化的Pod處於Pending狀態,但應該會將Initializing狀態設置為true

    (4)如果Pod重啟,所有的Init容器必須重新執行

    (5)對init容器spec的修改被限制在容器的image字段,修改其他字段都不會生效,更改init容器的image字段,等價於重啟了Pod

    (6)Init容器具有應用容器的所有字段,除了readinessProbe(就緒檢測),因為init容器無法定義不同於完成(Completion)的就緒(readiness)之外的其他狀態,這會在驗證過程中強制執行。

    (7)在Pod中的每個app和init容器的名稱必須唯一,與任何其他容器共享一個名稱,會在驗證時拋出錯誤。

  4、演示

  創建一個init容器的配置文件,在該配置文件中,創建了一個initPod叫init-mydb,該initpod需要執行一個連接inint-db的pod

#init-pod.yaml
apiVersion: v1
kind: Pod
metadata:
 name: init-pod
 labels:
   app: nginx
spec:
 containers:
 - name: myapp
   image: nginx
   command: ['sh', '-c', 'echo -n "running at " && date +%T && sleep 600']
 initContainers:
 - name: init-mydb
   image: nginx
   command: ['sh', '-c', 'until nslookup init-db; do echo waiting for init-db;date +%T; sleep 2;echo; done;']

  創建:

#創建
kubectl apply -f init-pod.yaml
#查看pod狀態 init沒成功
kubectl get pod
#查看log
kubectl logs init-pod -c init-mydb

    

  使用上述命令可以看到,上面創建的容器一直連不上db,導致一直不能完成。

  然后創建db容器

#init-db.yaml
kind: Service
apiVersion: v1
metadata:
 name: init-db
spec:
 ports:
   - protocol: TCP
     port: 80
     targetPort: 3366

  創建

#創建svr
kubectl create -f init-db.yaml
#查看
kubectl get svc

#svc有ip地址,等待init容器運行成功
kubectl get pod

  顯示原來的容器已經啟動成功。

  刪除容器

#刪除
kubectl delete -f init-pod.yaml
kubectl delete -f init-db.yaml

三、容器探針

(一)概述  

  探針是由kubectl對容器執行的定期診斷,要執行診斷,kubelet調用由容器實現的Handler,探測的診斷結果有成功、失敗和未知三種情況,探測類型有以下三種:

    1、ExecAction:在容器內執行指定命令,如果命令退出時返回碼為0則認為診斷成功

    2、TCPSocketAction:對指定端口上的容器的IP地址進行TCP檢查,如果端口打開,則認為診斷成功

    3、HTTPGetAction:對指定的端口和路徑上的容器IP執行http get請求,如果響應狀態碼大於200小於400,則認為診斷成功。

  上面提到了存活探測和就緒探測,那么對於兩種探測的方式做個解釋:

    1、livenessProbe(存活探測):存活探測是用來探測容器是否正在運行,如果探測失敗,lubelet會殺死容器,並且容器將受到重啟策略的影響。如果容器不提供存活探測,則默認為狀態一直為Success。

    2、readinessProbe(就緒探測):就緒探測是用來探測容器是否准備好接收服務請求,如果探測失敗,端點控制器將從與Pod匹配的所有Service的端點中刪除該Pod的IP地址。初始延遲之前的就緒狀態默認為Failure,如果容器不提供就緒探針,則默認狀態一直為Success。

(二)就緒探針

  就緒探針配置:

#readinessProbe-httpget
apiVersion: v1 
kind: Pod 
metadata:
  name: readiness-httpget-pod 
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container 
    image: nginx
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html 
      initialDelaySeconds: 1
      periodSeconds: 3

  以上的配置文件表示創建一個名字為readiness-httpget-pod的就緒探針,readinessProbe的配置就是就緒探針的具體配置,首先使用的是httpget的方式訪問80端口,訪問路徑是/index1.html,延遲一秒訪問,每三秒探測一次。

  執行以上yaml文件,查看結果:

      

   可以看到,雖然這個Pod狀態為Running,但是卻為就緒,使用命令查看原因:

kubectl describe pod readiness-httpget-pod

      

   可以看到是就緒探測結果為404。

  那么就為該pod創建一個/index1.html配置文件

# 進入pod
kubectl exec -it readiness-httpget-pod sh
# 進入nginx默認訪問目錄
cd /usr/share/nginx/html
# 創建index1.html
 echo 'hello lcl' >> index1.html
# 從pod中退出
exit

  重新查看,該pod已經正常運行

    

   說明:實際生產中,訪問的路徑一般都是健康檢查的路徑,這里只是為了做個演示。

(三)存活檢測--livenessProbe-exec

  配置文件:

apiVersion: v1 
kind: Pod 
metadata:
  name: liveness-exec-pod
  namespace: default 
spec:
  containers: 
  - name: liveness-exec-container 
    image: hub.lcl.cn/library/busybox:v1
    imagePullPolicy: IfNotPresent 
    command: ["/bin/sh","-c","touch /tmp/live;sleep 60;rm -rf /tmp/live;sleep 3600"] 
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/live"]
      initialDelaySeconds: 1
      periodSeconds: 3

  配置文件簡單說明:

    容器(liveness-exec-container)的command命令,創建一個/tmp/live文件,然后休眠60秒,然后將該文件刪除,然后再休眠3600秒

    創建了一個存活探針(livenessProbe),檢測/tmp/live文件,延遲一秒開始檢測,每三秒探測一次。

  執行yaml文件,查看pod運行情況

      

   可以看到,Pod在一段時間后,檢測不到/tmp/live文件,自動重啟。

(四)存活檢測--livenessProbe-Httpget

  yaml文件

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

  配置文件說明:

    創建了一個存活探針(livenessProbe),使用httpget方式請求/index.html,檢測/tmp/live文件,延遲3秒開始檢測,每10秒探測一次。

  運行yaml文件:因為nginx默認就有index.html文件,因此pod狀態正常

      

   進入pod中,將index.html刪除

# 進入容器
kubectl exec -it liveness-httpget-pod sh
# 切換到nginx默認訪問目錄
cd /usr/share/nginx/html
# 刪除文件
rm -f index.html

      

   可以看到pod就開始重啟了。

(五)存活檢測-livenessProbe-TCP

  yaml文件

apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: probetcp
    image: nginx
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 80
      periodSeconds: 3

  配置文件說明:使用tcp檢測,延遲5秒開始檢測,檢測超時時間為1秒,檢測端口80,每3秒檢測一次。

(六)存活探測和就緒探測

  在實際生產中,一個Pod中應該同時存在就緒探測和存活探測,yaml樣例如下所示

apiVersion: v1 
kind: Pod 
metadata:
  name: liveness-httpget-pod 
  namespace: default 
spec:
  containers: 
  - name: liveness-httpget-container 
    image: hub.lcl.com/library/myapp:v1 
    imagePullPolicy: IfNotPresent 
    ports:
    - name: http 
      containerPort: 80 
    readinessProbe:
      httpGet: 
        port: 80
        path: /index1.html 
      initialDelaySeconds: 1 
      periodSeconds: 3 
    livenessProbe:
      httpGet:
        port: http 
        path: /index.html 
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

(七)勾子函數  

  在前面說Pod的生命周期中有start勾子函數和stop勾子函數,就是在啟動前和停止后分別要做哪些事情,這里做個演示:

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-startstop
spec:
  containers:
  - name: lifecycle-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh","-c","echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh","-c","echo Hello container stop"]

   配置文件也比較簡單,就是在啟動的時候輸出一句話到message文件,在pod停止時,再輸出一句話

  執行yaml文件,待pod運行后,進入pod,查看message文件

      

   停止的由於已經停止,就看不了~~~

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM