Docker 與 K8S學習筆記(二十四)—— 工作負載的使用

語言: CN / TW / HK

我們前面講了很多關於Pod的使用,但是在實際應用中,我們不會去直接建立Pod,我們一般通過Kubernetes提供的工作負載(Deployment、DeamonSet、StatefulSet、Job等)完成對一組Pod全生命週期的控制,本節開始我們來看看這些工作負載是如何使用的。

一、Deployments

Deployments可以自動部署一個容器應用的多個副本,監控其副本數量並始終維持這一數量。我們來建立一個Deployments看看:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

我們的Deployment會建立並維持三個nginx副本,我們通過kubectl create建立此Deployment:

[root@kubevm1 workspace] kubectl create -f demo_deployment.yml
[root@kubevm1 workspace] kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           2m40s
[root@kubevm1 workspace] kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-585449566-b6v88   1/1     Running   0          2m4s
nginx-deployment-585449566-p4vb7   1/1     Running   0          2m4s
nginx-deployment-585449566-s95sr   1/1     Running   0          2m4s

我們看到三個nginx的Pod豆啟動完畢了,當我們手動殺掉一個Pod,Deployment會自動將其恢復:

[root@kubevm1 workspace] kubectl delete pod nginx-deployment-585449566-b6v88
[root@kubevm1 workspace] kubectl get pods
NAME                               READY   STATUS              RESTARTS   AGE
nginx-deployment-585449566-b6v88   0/1     Terminating         0          7m23s
nginx-deployment-585449566-nbrdm   0/1     ContainerCreating   0          6s
nginx-deployment-585449566-p4vb7   1/1     Running             0          7m23s
nginx-deployment-585449566-s95sr   1/1     Running             0          7m23s

我們前面說過Deployment是自動啟動並排程Pod的,這三個Pod最終在哪些節點上執行,完全由master的Scheduler來控制,我們通過-o wide來看看這三個Pod都分佈在哪裡:

[root@kubevm1 workspace] kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE     IP           NODE      NOMINATED NODE   READINESS GATES
nginx-deployment-585449566-nbrdm   1/1     Running   0          3m12s   10.244.1.8   kubevm2   <none>           <none>
nginx-deployment-585449566-p4vb7   1/1     Running   0          10m     10.244.2.5   kubevm3   <none>           <none>
nginx-deployment-585449566-s95sr   1/1     Running   0          10m     10.244.1.7   kubevm2   <none>           <none>

二、DaemonSet

DaemonSet是kubernetes 1.2新增的資源物件,它可以確保在每個Node上僅執行一份Pod的副本,DaemonSet可用於以下場景:

  • 在每個節點上執行叢集守護程序

  • 在每個節點上執行日誌收集守護程序

  • 在每個節點上執行監控守護程序

我們建立一個DaemonSet看看效果,我們還是以Nginx為例,下面的例子定義的Daemon將會為每個Node都啟動一個Nginx容器:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-daemonset
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      name: nginx-daemonset
  template:
    metadata:
      labels:
        name: nginx-daemonset
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

我們建立此DaemonSet看看:

[root@kubevm1 workspace] kubectl create -f demo_daemonset.yml
daemonset.apps/nginx-daemonset created
[root@kubevm1 workspace] kubectl get DaemonSet
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nginx-daemonset   2         2         2       2            2           <none>          11m
[root@kubevm1 workspace] kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
nginx-daemonset-49tcp   1/1     Running   0          14m   10.244.1.13   kubevm2   <none>           <none>
nginx-daemonset-w2xc2   1/1     Running   0          14m   10.244.2.11   kubevm3   <none>           <none>

與Deployment不同的是,我們在yaml中沒有指定replicas,但是DaemonSet自動為除Master節點外每一個Node都建立了一個副本,這裡大家可能會問:為什麼Master沒有Pod副本呢?這個因為預設狀態下,DaemonSet只會在Node中建立副本,如果需要在Master中也啟動Pod,則需要設定容忍度:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-daemonset
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      name: nginx-daemonset
  template:
    metadata:
      labels:
        name: nginx-daemonset
    spec:
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

我們重新建立DaemonSet,看看效果:

[root@kubevm1 workspace] kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
nginx-daemonset-45z95   1/1     Running   0          46s   10.244.2.13   kubevm3   <none>           <none>
nginx-daemonset-9z2lt   1/1     Running   0          46s   10.244.0.5    kubevm1   <none>           <none>
nginx-daemonset-cjf6k   1/1     Running   0          46s   10.244.1.15   kubevm2   <none>           <none>

關於容忍度的內容我們後續會詳細介紹。

三、Jobs

我們使用Jobs可以定義並啟動一個批處理任務,處理完成後,整個批處理任務結束。下面我們建立一個Job,此Job會輸出一段文字:

apiVersion: batch/v1
kind: Job
metadata:
  name: echo
spec:
  template:
    spec:
      containers:
      - name: echo
        image: busybox
        command: ["sh", "-c", "echo this a job"]
      restartPolicy:  Never

我們建立Job看一下效果:

[root@kubevm1 workspace] kubectl get job
NAME   COMPLETIONS   DURATION   AGE
echo   1/1           14s        7h3m
[root@kubevm1 workspace] kubectl get pods
NAME         READY   STATUS      RESTARTS   AGE
echo-c5kmf   0/1     Completed   0          7h3m
[root@kubevm1 workspace] kubectl logs echo-c5kmf
this a job

我們設定Job執行完畢後不會重啟,所以最終其Pod狀態為Complated。

上面的例子只是起了一個Pod比較簡單,在實際應用中,我們往往會啟動多個Pod並行處理任務,因此Job的使用有以下三種常見模式:

    • Non-parallel Jobs:一個Job只啟動一個Pod,當Pod異常會重啟Pod,一旦此Pod正常結束,Job將結束。

    • Parallel Jobs with a fixed completiong count:並行Job會啟動多個Pod,此時需要設定Job的spec.completions為一個正數,當正常結束的Pod數達到此引數設定值後,Job結束。此外,通過設定spec.parallelism可以設定並行度即同時啟動幾個Job來處理工作項。

    • Parallel Jobs with a work queue:工作項都放在訊息佇列中,此模式不需要設定spec.completions引數,而Pod具有以下特性:

  1. 每個Pod都能獨立判斷和決定釋放還有任務項需要處理;

  2. 如果某個Pod正常結束,則Job不會再啟動新的Pod,並且其他Pod應該處於即將結束的狀態,畢竟佇列裡沒任務了嘛;

  3. 如果所有Pod都結束了,且至少有一個Pod成功結束,則整個Job成功結束。

限於篇幅,關於Job的後兩種模式,後面會有專門講解。

四、CronJob

CronJob其實就是具有定時功能的Job,可以設定Job定時執行或者週期性執行,CronJob使用Cron表示式配置執行週期。我們修改下上面Job定義檔案:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: echo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: echo
            image: busybox
            command: ["sh", "-c", "echo this a job"]
          restartPolicy:  OnFailure

我們設定每一分鐘執行一次,這裡也能看出來,在Kubernetes中,CronJob最小排程間隔為分鐘級。

[root@kubevm1 workspace] kubectl get cronjob
NAME   SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
echo   */1 * * * *   False     0        29s             4m48s
[root@kubevm1 workspace] kubectl get pods
NAME                    READY   STATUS      RESTARTS   AGE
echo-1655768220-m5p9x   0/1     Completed   0          2m34s
echo-1655768280-m7gsj   0/1     Completed   0          93s
echo-1655768340-h2n6n   0/1     Completed   0          33s