Kubernetes Controller詳解

deachiy發表於2020-10-30


執行容器化應用是Kubernetes最重要的核心功能。為滿足不同的業務需要,Kubernetes提供了多種Controller,主要包括Deployment、DaemonSet、Job、CronJob等。
1、建立資源的兩種方式
建立資源主要有通過命令列配置引數和通過配置檔案這兩種方式。
通過命令列主要是使用kubectl命令來進行建立,主要可能用到的是kubectl run和kubectl create,具體的用法我們可以在命令後面加上–-help引數來檢視幫助文件。
這種方式的好處就是簡單快捷,部署的速度比較快,但是遇到要求比較複雜多樣的資源部署,後面就要附帶一大串引數,容易出錯,所以這種方式一般來說比較適用於小規模的簡單資源部署或者是上線前的簡單測試
通過配置檔案則主要是json格式或yaml格式的檔案,好處是可以詳細配置各種引數,保留的配置檔案還可以用到其他的叢集上進行大規模的部署操作,缺點就是部署比較麻煩,並且需要一定的門檻(要求對json或yaml有一定的瞭解)
配置檔案主要是通過kubectl apply -f和kubectl create -f來進行配置。
2、Deployment
2.1 cli部署
我們先使用命令列(cli)建立一個deployment,名字(NAME)是nginx-clideployment,使用的映象(image)版本為1.17,建立的副本(replicas)數量為3。
kubectl run nginx-clideployment --image=nginx:1.17 --replicas=3
我們檢視一下部署是否成功:

這裡的kubectl get rs中的rs其實就是ReplicaSet(RS)
我們還可以發現ReplicaSet的命名就是在我們指定的NAME後面加上了一串雜湊數值。
-.
想要檢視更詳細的pod情況,我們可以這樣:
kubectl get pod -o wide

這裡我們可以發現三個pod被k8s自動的分配到了三個節點上而實現叢集中的負載均衡(LB),而這裡的IP是建立pod的時候進行隨機分配的,我們並不能預知。
如果想要檢視某一個pod部署之後的情況,我們可以這樣:
kubectl describe pods nginx-clideployment-5696d55d9d-gdtrt
如果我們只是輸入nginx-clideployment的話就會把所有相關的nginx-clideployment都列出來。

這裡的資訊很多,我們可以看到namespace是使用的預設default(一般都是default,除非是數十人以上在同時使用這個叢集,否則一般不建議新建namespace來區分pod,大多數情況下使用label即可區分各類pod。)
Controlled By:則說明了這個deployment是由ReplicaSet控制的。
Conditions:則表明了當前的pod狀況

Volumes稱之為卷,這個概念我們暫時還沒有接觸到,等到我們的宿主機需要與容器內的服務進行資料互動的時候再進行了解。
Events則相當於log,記錄了pod執行的所有情況,如果遇到了執行不正常的情況,我們也可以檢視這裡來了解詳情。

2.2 yaml配置檔案部署
接下來我們嘗試使用yaml檔案來進行部署,新建一個檔案,命名為nginx-yamldeployment.yml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-yamldeployment
spec:
replicas: 5
template:
metadata:
labels:
app: web_server
spec:
containers:
- name: nginx
image: nginx:1.17.1
apiVersion是當前配置格式的版本。
kind是要建立的資源型別,這裡是Deployment。
metadata是該資源的後設資料,name是必需的後設資料項。
spec部分是該Deployment的規格說明。
replicas 指明副本數量,預設為1。
template 定義Pod的模板,這是配置檔案的重要部分。
metadata定義Pod的後設資料,至少要定義一個label。label的key和value可以任意指定。
spec 描述Pod的規格,此部分定義Pod中每一個容器的屬性,name和image是必需的。
接下來我們使用kubectl apply指令進行部署。
kubectl apply -f nginx-yamldeployment.yml


我們可以看到這裡是已經執行正常了,那麼如果我們想要修改這個deployment的屬性,比如說副本數量從5改為6,那麼我們可以直接編輯剛剛的nginx-yamldeployment.yml檔案,然後再執行kubectl apply -f nginx-yamldeployment.yml,但是如果檔案找不到了,我們可以使用另外的方法:
kubectl edit deployments.apps nginx-yamldeployment
這樣子我們就能直接編輯這個deployment的yaml配置檔案,編輯的操作方式和vim相同,修改完成後會自動生效。

我們修改儲存退出後,可以看到這裡已經生效了。

對於使用命令列建立的deployment,我們可以使用命令列來進行修改,也可以直接kubectl edit來編輯對應的yaml配置檔案。

3、DaemonSet
我們先來看一下官網對DaemonSet的解釋:
DaemonSet 確保全部(或者某些)節點上執行一個 Pod 的副本。當有節點加入叢集時,也會為他們新增一個 Pod 。 當有節點從叢集移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它建立的所有 Pod。
使用 DaemonSet 的一些典型用法:
執行叢集儲存 daemon,例如在每個節點上執行 glusterd、ceph。
在每個節點上執行日誌收集 daemon,例如fluentd、logstash。
在每個節點上執行監控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。
一個簡單的用法是在所有的節點上都啟動一個 DaemonSet,將被作為每種型別的 daemon 使用。 一個稍微複雜的用法是單獨對每種 daemon 型別使用多個 DaemonSet,但具有不同的標誌,和/或對不同硬體型別具有不同的記憶體、CPU要求。
實際上,k8s本身的一些系統元件服務就是以DaemonSet的形式執行在各個節點上的。

4、Job
4.1 部署job
Job建立一個或多個Pod並確保指定數量的Pod成功終止。當pod成功完成後,Job會跟蹤成功的完成情況。達到指定數量的成功完成時,Job完成。
刪除Job將清理它建立的Pod。
一個簡單的例子是建立一個Job物件,以便可靠地執行一個Pod併成功完成指定任務。如果第一個Pod失敗或被刪除(例如由於節點硬體故障或節點重啟),Job物件將啟動一個新的Pod。
我們還可以使用Job並行執行多個Pod。
直接照搬官網的解釋可能會有些難以理解,我們來執行一個例子就能很好的說明情況了。
我們先新建一個job的配置檔案,命名為pijob.yml,這個任務是將pi計算到小數點後兩千位,然後再列印出來。我們執行一下看看。

apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4

我們檢視它的詳細情況
kubectl describe jobs/pi

這裡可以看到,執行了37s後成功計算出結果。

檢視pod也可以看到它的狀態是Completed,說明已經完成了。

檢視建立的pod的名稱

pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods

檢視pod的執行結果

kubectl logs $pods

4.2 job執行錯誤
我們現在來看一下執行失敗的情況,我們把command裡面的路徑改錯,使得它無法正常執行。

注意這裡的restartPolicy: Never意味著pod執行失敗了也不會重啟。但是這個時候job會檢測到執行失敗,然後再新建一個pod來執行這個任務。
backoffLimit: 4意味著最多隻會新建4個pod,避免一直失敗一直新建從而耗盡系統資源。

我們檢視event可以看到,確實是由於路徑修改錯誤而導致無法正常執行。

接下來我們把restartPolicy: 改為 OnFailure
這時候我們可以看到並沒有啟動多個pod,二是對發生錯誤的pod進行重啟操作。

4.3 job並行化
在多執行緒早已普及的今天,很多工我們都可以使用並行化來進行加速執行,這裡也不例外。
我們在配置檔案中的spec中加入 completions: 和parallelism: 。

圖中表示需要執行12個,每次並行執行6個。

從圖中我們可以看到確實是每次執行6個(執行時間相同說明同時開始執行)。
等待一段時候之後,我們再次檢視而已看到任務已經順利完成了。

5、CronJob
熟悉linux的同學一定不會對cron感到陌生,因為cron就是用來管理linux中的定時任務的工具,所以CronJob我們可以理解為定時版的Job,其定時任務的編寫格式也和Cron相似。關於Cron可以點選這裡檢視小七之前的部落格。
需要注意的是,CronJob的時間以啟動該CronJob任務的Master節點的時間為準。
Cronjob只負責建立與其計劃相匹配的Job,而Job則負責管理它所代表的Pod。也就是說,CronJob只負責建立Job,具體的管理操作還是由Job來負責。
這裡是CronJob的官方文件。
我們新建一個hellocronjob.yml來檢視一下它的工作情況

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
這個定時任務的操作就是每分鐘輸出一次時間和Hello from the Kubernetes cluster。

檢視cronjob的執行狀態

kubectl get cronjobs.batch
kubectl get jobs.batch --watch

我們隨便檢視其中的一個log可以看到輸出的結果:

更多交流,入群:

相關文章