傲視Kubernetes(六):Pod管理及控制器

本文主要內容:

1、Kubernetes如何管理Pod?

2、Kubernetes Control Plane組件有哪幾種?作用效果是什麼?

一、Kubernetes如何管理Pod

Kubernetes中的Pod根據創建方式的不同,可以分爲兩種:一種是直接創建的Pod,比如自己寫了一個Pod的yaml文件,通過kubectl create命令創建的Pod;一種是通過控制器,也就是Control Plane創建的Pod。

對於第一種Pod,也就是自己創建的Pod,創建完成之後由它所在的Node節點上的Kubelet管理。第二種Pod由控制器Control Plane管理。

Kubelet管理Pod

Kubelet管理Pod的手段很簡單,就是重啓大法。每個Pod創建時,都可以給配置存活探針,如下所示,創建Pod之後Kubernetes會每隔一段時間調用一次這個存活探針,也就是請求,如果執行失敗或者沒有響應,Kubelet則重啓Pod

...
spec:
  containers:
  -  image:xxx
     livenessProbe:
       httpGet: /
       port: 8080

Kubernetes提供了三種探針類型,上面示例中的是httpGet(返回的狀態碼是2xx或3xx則會被認定成功),還有兩種是TCP套接字探針和Exec探針。常用的一般都是HttpGet類型。

注意,如果不設置存活探針,kubelet只會根據容器進程是否存在來判斷進程是否健康,也就是沒有了健康檢查應有的效果(因爲比如OOM這樣的異常發生時,JVM進程仍然運行),所以存活探針基本是一個必須的配置項。

在存活探針的配置項livenessProbe的同一級,還可以配置探針的其他屬性,比如delay、timeout、period等,還有一個參數叫初始延遲initialDelaySeconds一般來說也需要配置上。如果不配置初始延遲參數,探針將在容器啓動時就探測容器,這很容易失敗,因爲應用還沒完成啓動。配置這個參數就能有效避免這種情況的發生。

到此爲止,都是在講Pod出異常之後的重啓處理,但如果Pod所在的Node節點出異常導致宕機呢?此時Node節點上的kubelet也就掛了,從而那些我們自己創建的依賴於Kubelet管理的Pod也就徹底GG了。

遇到這種情況該怎麼辦呢?這時候Kubernetes Control Plane就可以發揮作用了。

Control Plane管理Pod

 Kubernetes的控制器,也就是Control Plane組件,有很多種,比如ReplicationController、ReplicationSet、DaemonSet、Job等。

在創建這些控制器的時候,會指定對應非副本數,控制器創建完成之後就會檢測實際運行的pod數是否跟副本數一致,如果實際運行的少了(Pod出異常掛掉了或者Pod所在的節點掛了),控制器會根據配置的模板創建新的Pod;如果實際運行的多了,則會刪掉多餘的Pod。總之控制器會控制實際運行的Pod數與配置的副本數目一致

當然,如果這些控制器所屬Pod的探針存活檢測異常,還是由Pod所在節點的kubelet來重啓容器。即kubelet負責重啓,控制器負責創建/刪除

二、Kubernetes Control Plane的組件有哪些?作用各是什麼?

下面分別對五種Control Plane的作用進行說明,其實除此之外還有兩種最常用的Deployment和StatefulSet,這兩種會在後面着重學習。

1、ReplicationController

ReplicationController顧名思義,副本的控制器。它主要由三部分組成: 標籤選擇器(label selector)、副本個數(replica count)、pod模板(pod template)。ReplicationController的yaml配置示例如下:

apiVersion: v1
kind: ReplicationController
metadata:
   name: kubia
spec:
   replicas: 3  # 副本數
   selector:  # 標籤選擇器
      app: kubia
   template: # pod模板
      metadata:
         labels:
            app: kubia
      spec:
         containers:
         -  name: kubia
            image: xxx/kubia
            port:
            -  containerPort:8080

標籤選擇器用戶查詢並監控所有擁有這個標籤的Pod;而副本數則用戶控制跟標籤選擇器匹配上的Pod的數量;如果Pod數量少於副本數,則會按照Pod模板創建新的Pod。所以這裏的標籤選擇器必須要與pod模板中的標籤一致,當然也可以不指定標籤選擇器,此時會默認按照pod模板中的標籤來選擇。

從上面就可以知道很重要的一點:Kubernetes是通過標籤與標籤選擇器實現的控制器與Pod的歸屬關係

具體操作的指令如下,很多操作跟操作其他對象沒什麼差別:

kubectl create -f kubia-rc.yaml  # 根據yaml文件創建ReplicationController

kubectl get rc   # 查看ReplicationController

kubectl delete pod kubia-xxx # 刪掉一個pod後再用get pod會看到正在創建新pod

kubectl delete rc kubia # 刪除kubia這個rc,此時連它所對應的Pod也都會被刪掉

kubectl delete rc kubia --cascade=false # 刪除kubia這個rc,但它所對應的Pod會被保留下來 kubectl describe rc kubia # 查看ReplicationController的詳細信息

kubectl label pod kubia-xxx app=kulet --overwrite # 改變pod的標籤,此時rs會創建一個新Pod來達到3個的副本數

kubectl get pods -L app # 查看pod的標籤

kubectl edit rc kubia # 進入修改名爲kubia的rc的頁面,修改後會立即生效,如果改了pod模板,只會對從此以後新創建的pod有效,不會影響已有pod

kubectl scale rc kubia --replicas=4 # 將副本數置爲4,此時如果實際pod數少了則會新建

注意,如果是一個Node節點不可用導致的Pod失效,Kubernetes會等待一段時間(幾分鐘)來等待Node的恢復,如果幾分鐘後仍未恢復,纔會創建新Pod來代替之前失效的Pod。

 

2、ReplicationSet

 ReplicationSet是ReplicationController的升級版,前者rs擁有rc所有的功能,而且還有更富表達力的標籤選擇器,所以後者現在完全可以棄之不用。

ReplicationSet的yaml示例:

apiVersion: apps/v1beta2
kind: ReplicationSet
metadata:
   name: kubia
spec:
   replicas: 3  # 副本數
   selector:  # 標籤選擇器
      matchLabels:
         app: kubia
   template: # pod模板
      metadata:
         labels:
            app: kubia
      spec:
         containers:
         -  name: kubia
            image: xxx/kubia
            port:
            -  containerPort:8080

對比ReplicationController可以看到有兩處有區別:一是apiVersion不再是v1了(此處的apps是api組,後面的v1beta2是實際的api版本),二是選擇器那裏中間又加了一級matchLabels。

上面所有對ReplicationController的指令都可以用於ReplicationSet,只需將rc替換爲rs即可。

 下面着重看看ReplicationSet對於標籤選擇器的升級:

1)、matchLabels

具體用法已經在上面的yaml示例中體現了,它的作用跟ReplicationController中的標籤選擇器相同,即完全匹配key和value(允許有其他的標籤)。

2)matchExpressions

使用方式如下:

selector:
   matchExpressions:
     - key: app 
       operator: In
       values:
         - kubia   # 表示標籤的值必須是kubia

matchExpressions下面必須有key和operator標籤,而value標籤有還是無取決於operator的值。operator有如下幾種:

In: 此時需要有values標籤,表示pod必須有與其中一個指定的values匹配的標籤

NotIn:此時需要有values標籤,表示pod必須的標籤與任何指定的values不匹配

Exists:不需要values標籤,表示pod必須包含指定key的標籤,不關注value

DoesNotExist:不需要values標籤,表示pod不得包含有指定key的標籤

需要注意的是,selector下面可以指定多個標籤表達式,即matchLabels和matchExpressions可以有一個也可以有多個也可以混合,此時這多個match的關係是與的關係,即都爲true的pod才滿足要求。一般不建議設置多個。

 

3、DaemonSet

 該控制器可以達到一種效果,即在每個Node節點上創建一個Pod。如果Node有增加或減少,相應的Pod也增加減少。DaemonSet的yaml配置如下所示:

apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
   name: kubia-monitor
spec:
   selector:  # 標籤選擇器
      matchLabels:
         app: kubia-monitor
   template: # pod模板
      metadata:
         labels:
            app: kubia-monitor
      spec:
         nodeSelector: # 節點選擇器
            disk: ssd
         containers:
         -  name: kubia-monitor
            image: xxx/kubia-monitor
            port:
            -  containerPort:8080

可以看到,DaemonSet不需要設置副本數,因爲每個Node節點只有一個Pod。在上面的配置中,還多了一個節點選擇器nodeSelector,它是用於控制只在滿足節點選擇器的節點上創建Pod,即對節點做一個過濾。注意,DaemonSet對Pod的創建是繞過了調度器的,所以即使對節點設置了不可調度,只要滿足DaemonSet的節點選擇器,則仍然可以在上面創建一個Pod

對DaemonSet的create、get、describe、delete等操作與其他控制器相同,就不在此贅述了,只需將對應的描述改成ds即可。

 

4、Job

上面介紹的三種控制器都是啓動後一直運行的,而Job是用於執行一次性任務的,執行完之後就會被自動刪掉。Job的yaml文件示例如下:

apiVersion: batch/v1  #Job屬於batch API組,版本爲v1
kind: Job
metadata:
   name: kubia-job
spec:
   template: # pod模板
      metadata:
         labels:
            app: kubia-job
      spec:
         restartPolicy: OnFailure  # 設置重啓策略
         containers:
         -  name: main
            image: xxx/kubia-job
            port:
            -  containerPort:8080

着重看一下重啓策略 restartPolicy。重啓策略一共有三種:Always(總是重啓,即執行完成之後會再次啓動,一直這樣進行下去)、OnFailure(失敗重啓)、Never(不重啓,即使執行失敗)。一般來說只會用

後兩者,不會用Always。

Job執行完之後,通過kubectl get pod是無法查看到它的,需要用 kubectl get pod -a ,狀態是Completed。

Job還支持運行多次和並行執行,配置方式如下:

apiVersion: batch/v1  
kind: Job
metadata:
   name: kubia-job
spec:
   completions: 5
   parallelism: 2
   template: # pod模板
       ...

completions配置的數目,表示要執行多少次。如果未配置parallelism,則默認並行度是1,即同一時間只有一個Pod在運行,運行完這個Pod再創建第二個,一直運行完5個爲止。

若如上所示,配置了parallelism=2,則同一時間會有兩個Pod在運行,其中一個執行完之後再創建一個,一直執行完5個爲止。

在Job運行時更改parallelism的指令:

kubectl scale job kubia-job --replicas=3

可以看到,跟擴容指令相同。

爲應對異常情況,Job還有兩個屬性配置:

spec.activeDeadlineSeconds: 設置超時時間,Job實例運行時間超過這個配置時間,會被標記爲失敗,pod被終止運行。

spec.backoffLimit:重試次數,未配置時默認爲6次。

 

5、CronJob

 熟悉定時任務的,應該不難猜到,該類型的控制器用於精確控制Pod定期執行的。配置的yaml如下所示:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
   name: kubia-cronjob
spec:
   schedule: "0,15,30,45 * * * *"
   startingDeadlineSeconds: 15  #表示如果離預定時間15s後還未啓動Job,則本次任務不會執行
   jobTemplate: 
      metadata:
         labels:
            app: kubia-cronjob
      spec:
         restartPolicy: OnFailure  # 設置重啓策略
         containers:
         -  name: main
            image: xxx/kubia-cronjob
            port:
            -  containerPort:8080

CronJob創建後,會在每個指定的cron表達式時間點創建一個新的Job。但有點坑的地方在於,它可能一下子創建兩個Job,也可能一個不創建。所以需要在業務側進行兼容,一方面是可以冪等,另一方面後面運行的任務需將前面未運行的任務未做的事情給做了。

 

本文到這裏就結束了,下一節將一起學習Kubernetes中的服務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章