我們前面講了很多關於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具有以下特性:
每個Pod都能獨立判斷和決定釋放還有任務項需要處理;
如果某個Pod正常結束,則Job不會再啟動新的Pod,並且其他Pod應該處於即將結束的狀態,畢竟佇列裡沒任務了嘛;
如果所有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