欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

k8s編排之Deployment知識點詳解

 更新時間:2023年01月17日 11:03:48   作者:半芽灣  
這篇文章主要為大家介紹了k8s編排之Deployment知識點詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

Pod 復雜的API對象

Pod 這個看似復雜的 API 對象,實際上就是對容器的進一步抽象和封裝而已。

說得更形象些,“容器”鏡像雖然好用,但是容器這樣一個“沙盒”的概念,對于描述應用來說,還是太過簡單了。這就好比,集裝箱固然好用,但是如果它四面都光禿禿的,吊車還怎么把這個集裝箱吊起來并擺放好呢?

所以,Pod 對象,其實就是容器的升級版。它對容器進行了組合,添加了更多的屬性和字段。這就好比給集裝箱四面安裝了吊環(huán),使得 Kubernetes 這架“吊車”,可以更輕松地操作它。

而 Kubernetes 操作這些“集裝箱”的邏輯,都由控制器(Controller)完成。 Deployment 這個最基本的控制器對象。

nginx-deployment

現(xiàn)在,我們一起來回顧一下這個名叫 nginx-deployment 的例子:

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

這個 Deployment 定義的編排動作非常簡單,即:確保攜帶了 app=nginx 標簽的 Pod 的個數(shù),永遠等于 spec.replicas 指定的個數(shù),即 2 個。

這就意味著,如果在這個集群中,攜帶 app=nginx 標簽的 Pod 的個數(shù)大于 2 的時候,就會有舊的 Pod 被刪除;反之,就會有新的 Pod 被創(chuàng)建。

這時,你也許就會好奇:究竟是 Kubernetes 項目中的哪個組件,在執(zhí)行這些操作呢?

我在前面介紹 Kubernetes 架構(gòu)的時候,曾經(jīng)提到過一個叫作 kube-controller-manager 的組件。

實際上,這個組件,就是一系列控制器的集合。我們可以查看一下 Kubernetes 項目的 pkg/controller 目錄:

$ cd kubernetes/pkg/controller/
$ ls -d */              
deployment/             job/                    podautoscaler/          
cloud/                  disruption/             namespace/              
replicaset/             serviceaccount/         volume/
cronjob/                garbagecollector/       nodelifecycle/          replication/ 

這個目錄下面的每一個控制器,都以獨有的方式負責某種編排功能。而我們的 Deployment,正是這些控制器中的一種。

實際上,這些控制器之所以被統(tǒng)一放在 pkg/controller 目錄下,就是因為它們都遵循 Kubernetes 項目中的一個通用編排模式,即:控制循環(huán)(control loop)。

在具體實現(xiàn)中,實際狀態(tài)往往來自于 Kubernetes 集群本身。

比如,kubelet 通過心跳匯報的容器狀態(tài)和節(jié)點狀態(tài),或者監(jiān)控系統(tǒng)中保存的應用監(jiān)控數(shù)據(jù),或者控制器主動收集的它自己感興趣的信息,這些都是常見的實際狀態(tài)的來源。

而期望狀態(tài),一般來自于用戶提交的 YAML 文件。

比如,Deployment 對象中 Replicas 字段的值。很明顯,這些信息往往都保存在 Etcd 中。

接下來,以 Deployment 為例,我和你簡單描述一下它對控制器模型的實現(xiàn):

  • Deployment 控制器從 Etcd 中獲取到所有攜帶了“app: nginx”標簽的 Pod,然后統(tǒng)計它們的數(shù)量,這就是實際狀態(tài);
  • Deployment 對象的 Replicas 字段的值就是期望狀態(tài);
  • Deployment 控制器將兩個狀態(tài)做比較,然后根據(jù)比較結(jié)果,確定是創(chuàng)建 Pod,還是刪除已有的 Pod

可以看到,一個 Kubernetes 對象的主要編排邏輯,實際上是在第三步的“對比”階段完成的。

這個操作,通常被叫作調(diào)諧(Reconcile)。這個調(diào)諧的過程,則被稱作“Reconcile Loop”(調(diào)諧循環(huán))或者“Sync Loop”(同步循環(huán))。

所以,如果你以后在文檔或者社區(qū)中碰到這些詞,都不要擔心,它們其實指的都是同一個東西:控制循環(huán)。

而調(diào)諧的最終結(jié)果,往往都是對被控制對象的某種寫操作。

比如,增加 Pod,刪除已有的 Pod,或者更新 Pod 的某個字段。這也是 Kubernetes 項目“面向 API 對象編程”的一個直觀體現(xiàn)。

其實,像 Deployment 這種控制器的設計原理,就是我們前面提到過的,“用一種對象管理另一種對象”的“藝術(shù)”。

其中,這個控制器對象本身,負責定義被管理對象的期望狀態(tài)。比如,Deployment 里的 replicas=2 這個字段。

而被控制對象的定義,則來自于一個“模板”。比如,Deployment 里的 template 字段。

可以看到,Deployment 這個 template 字段里的內(nèi)容,跟一個標準的 Pod 對象的 API 定義,絲毫不差。而所有被這個 Deployment 管理的 Pod 實例,其實都是根據(jù)這個 template 字段的內(nèi)容創(chuàng)建出來的。

像 Deployment 定義的 template 字段,在 Kubernetes 項目中有一個專有的名字,叫作 PodTemplate(Pod 模板)。

這個概念非常重要,因為后面我要講解到的大多數(shù)控制器,都會使用 PodTemplate 來統(tǒng)一定義它所要管理的 Pod。更有意思的是,我們還會看到其他類型的對象模板,比如 Volume 的模板。

Deployment 及類似控制器總結(jié)

至此,我們就可以對 Deployment 以及其他類似的控制器,做一個簡單總結(jié)了:

類似 Deployment 這樣的一個控制器,實際上都是由上半部分的控制器定義(包括期望狀態(tài)),加上下半部分的被控制對象的模板組成的。

這就是為什么,在所有 API 對象的 Metadata 里,都有一個字段叫作 ownerReference,用于保存當前這個 API 對象的擁有者(Owner)的信息。

那么,對于我們這個 nginx-deployment 來說,它創(chuàng)建出來的 Pod 的 ownerReference 就是 nginx-deployment 嗎?或者說,nginx-deployment 所直接控制的,就是 Pod 對象么?

Deployment 看似簡單,但實際上,它實現(xiàn)了 Kubernetes 項目中一個非常重要的功能:Pod 的“水平擴展 / 收縮”(horizontal scaling out/in)。這個功能,是從 PaaS 時代開始,一個平臺級項目就必須具備的編排能力。

舉個例子,如果你更新了 Deployment 的 Pod 模板(比如,修改了容器的鏡像),那么 Deployment 就需要遵循一種叫作“滾動更新”(rolling update)的方式,來升級現(xiàn)有的容器。

而這個能力的實現(xiàn),依賴的是 Kubernetes 項目中的一個非常重要的概念(API 對象):ReplicaSet。

ReplicaSet 的結(jié)構(gòu)非常簡單,我們可以通過這個 YAML 文件查看一下:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-set
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9

從這個 YAML 文件中,我們可以看到,一個 ReplicaSet 對象,其實就是由副本數(shù)目的定義和一個 Pod 模板組成的。不難發(fā)現(xiàn),它的定義其實是 Deployment 的一個子集。

更重要的是,Deployment 控制器實際操縱的,正是這樣的 ReplicaSet 對象,而不是 Pod 對象。

對于一個 Deployment 所管理的 Pod,它的 ownerReference 是誰?這個問題的答案就是:ReplicaSet。

明白了這個原理,我再來和你一起分析一個Deployment:

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

可以看到,這就是一個我們常用的 nginx-deployment,它定義的 Pod 副本個數(shù)是 3(spec.replicas=3)。

那么,在具體的實現(xiàn)上,這個 Deployment,與 ReplicaSet,以及 Pod 的關(guān)系是怎樣的呢?

我們可以用一張圖把它描述出來:

通過這張圖,我們就很清楚的看到,一個定義了 replicas=3 的 Deployment,與它的 ReplicaSet,以及 Pod 的關(guān)系,實際上是一種“層層控制”的關(guān)系。

其中,ReplicaSet 負責通過“控制器模式”,保證系統(tǒng)中 Pod 的個數(shù)永遠等于指定的個數(shù)(比如,3 個)。這也正是 Deployment 只允許容器的 restartPolicy=Always 的主要原因:只有在容器能保證自己始終是 Running 狀態(tài)的前提下,ReplicaSet 調(diào)整 Pod 的個數(shù)才有意義。

而在此基礎上,Deployment 同樣通過“控制器模式”,來操作 ReplicaSet 的個數(shù)和屬性,進而實現(xiàn)“水平擴展 / 收縮”和“滾動更新”這兩個編排動作。

其中,“水平擴展 / 收縮”非常容易實現(xiàn),Deployment Controller 只需要修改它所控制的 ReplicaSet 的 Pod 副本個數(shù)就可以了。

比如,把這個值從 3 改成 4,那么 Deployment 所對應的 ReplicaSet,就會根據(jù)修改后的值自動創(chuàng)建一個新的 Pod。這就是“水平擴展”了;“水平收縮”則反之。

而用戶想要執(zhí)行這個操作的指令也非常簡單,就是 kubectl scale,比如:

$ kubectl scale deployment nginx-deployment --replicas=4
deployment.apps/nginx-deployment scaled

那么,“滾動更新”又是什么意思,是如何實現(xiàn)的呢?

接下來,我還以這個 Deployment 為例,來為你講解“滾動更新”的過程。

首先,我們來創(chuàng)建這個 nginx-deployment:$ kubectl create -f nginx-deployment.yaml --record 注意,在這里,我額外加了一個–record 參數(shù)。它的作用,是記錄下你每次操作所執(zhí)行的命令,以方便后面查看。

然后,我們來檢查一下 nginx-deployment 創(chuàng)建后的狀態(tài)信息:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s

在返回結(jié)果中,我們可以看到四個狀態(tài)字段,它們的含義如下所示。

  • DESIRED:用戶期望的 Pod 副本個數(shù)(spec.replicas 的值);
  • CURRENT:當前處于 Running 狀態(tài)的 Pod 的個數(shù);
  • UP-TO-DATE:當前處于最新版本的 Pod 的個數(shù),所謂最新版本指的是 Pod 的 Spec 部分與 Deployment 里 Pod 模板里定義的完全一致;
  • AVAILABLE:當前已經(jīng)可用的 Pod 的個數(shù),即:既是 Running 狀態(tài),又是最新版本,并且已經(jīng)處于 Ready(健康檢查正確)狀態(tài)的 Pod 的個數(shù)。

可以看到,只有這個 AVAILABLE 字段,描述的才是用戶所期望的最終狀態(tài)。

而 Kubernetes 項目還為我們提供了一條指令,讓我們可以實時查看 Deployment 對象的狀態(tài)變化。這個指令就是 kubectl rollout status:

$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment.apps/nginx-deployment successfully rolled out

在這個返回結(jié)果中,“2 out of 3 new replicas have been updated”意味著已經(jīng)有 2 個 Pod 進入了 UP-TO-DATE 狀態(tài)。

Deployment 所控制的 ReplicaSet查看

繼續(xù)等待一會兒,我們就能看到這個 Deployment 的 3 個 Pod,就進入到了 AVAILABLE 狀態(tài)

此時,你可以嘗試查看一下這個 Deployment 所控制的 ReplicaSet:

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-3167673210   3         3         3       20s

如上所示,在用戶提交了一個 Deployment 對象后,Deployment Controller 就會立即創(chuàng)建一個 Pod 副本個數(shù)為 3 的 ReplicaSet。這個 ReplicaSet 的名字,則是由 Deployment 的名字和一個隨機字符串共同組成。

這個隨機字符串叫作 pod-template-hash,在我們這個例子里就是:3167673210。ReplicaSet 會把這個隨機字符串加在它所控制的所有 Pod 的標簽里,從而保證這些 Pod 不會與集群里的其他 Pod 混淆。

而 ReplicaSet 的 DESIRED、CURRENT 和 READY 字段的含義,和 Deployment 中是一致的。所以,相比之下,Deployment 只是在 ReplicaSet 的基礎上,添加了 UP-TO-DATE 這個跟版本有關(guān)的狀態(tài)字段。

這個時候,如果我們修改了 Deployment 的 Pod 模板,“滾動更新”就會被自動觸發(fā)。

修改 Deployment 有很多方法。比如,我可以直接使用 kubectl edit 指令編輯 Etcd 里的 API 對象。kubectl edit deployment/nginx-deployment

這個 kubectl edit 指令,會幫你直接打開 nginx-deployment 的 API 對象。然后,你就可以修改這里的 Pod 模板部分了。比如,在這里,我將 nginx 鏡像的版本升級到了 1.9.1。

kubectl edit 指令編輯完成后,保存退出,Kubernetes 就會立刻觸發(fā)“滾動更新”的過程。你還可以通過 kubectl rollout status 指令查看 nginx-deployment 的狀態(tài)變化:

$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment.extensions/nginx-deployment successfully rolled out

這時,你可以通過查看 Deployment 的 Events,看到這個“滾動更新”的流程: kubectl describe deployment nginx-deployment

可以看到,首先,當你修改了 Deployment 里的 Pod 定義之后,Deployment Controller 會使用這個修改后的 Pod 模板,創(chuàng)建一個新的 ReplicaSet(hash=1764197365),這個新的 ReplicaSet 的初始 Pod 副本數(shù)是:0。

然后,在 Age=24 s 的位置,Deployment Controller 開始將這個新的 ReplicaSet 所控制的 Pod 副本數(shù)從 0 個變成 1 個,即:“水平擴展”出一個副本。

緊接著,在 Age=22 s 的位置,Deployment Controller 又將舊的 ReplicaSet(hash=3167673210)所控制的舊 Pod 副本數(shù)減少一個,即:“水平收縮”成兩個副本。

如此交替進行,新 ReplicaSet 管理的 Pod 副本數(shù),從 0 個變成 1 個,再變成 2 個,最后變成 3 個。而舊的 ReplicaSet 管理的 Pod 副本數(shù)則從 3 個變成 2 個,再變成 1 個,最后變成 0 個。這樣,就完成了這一組 Pod 的版本升級過程。

像這樣,將一個集群中正在運行的多個 Pod 版本,交替地逐一升級的過程,就是“滾動更新”。

在這個“滾動更新”過程完成之后,你可以查看一下新、舊兩個 ReplicaSet 的最終狀態(tài):

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1764197365   3         3         3       6s
nginx-deployment-3167673210   0         0         0       30s

其中,舊 ReplicaSet(hash=3167673210)已經(jīng)被“水平收縮”成了 0 個副本。

這種“滾動更新”的好處是顯而易見的。 比如,在升級剛開始的時候,集群里只有 1 個新版本的 Pod。如果這時,新版本 Pod 有問題啟動不起來,那么“滾動更新”就會停止,從而允許開發(fā)和運維人員介入。而在這個過程中,由于應用本身還有兩個舊版本的 Pod 在線,所以服務并不會受到太大的影響。

當然,這也就要求你一定要使用 Pod 的 Health Check 機制檢查應用的運行狀態(tài),而不是簡單地依賴于容器的 Running 狀態(tài)。要不然的話,雖然容器已經(jīng)變成 Running 了,但服務很有可能尚未啟動,“滾動更新”的效果也就達不到了。

而為了進一步保證服務的連續(xù)性,Deployment Controller 還會確保,在任何時間窗口內(nèi),只有指定比例的 Pod 處于離線狀態(tài)。同時,它也會確保,在任何時間窗口內(nèi),只有指定比例的新 Pod 被創(chuàng)建出來。這兩個比例的值都是可以配置的,默認都是 DESIRED 值的 25%。

所以,在上面這個 Deployment 的例子中,它有 3 個 Pod 副本,那么控制器在“滾動更新”的過程中永遠都會確保至少有 2 個 Pod 處于可用狀態(tài),至多只有 4 個 Pod 同時存在于集群中。這個策略,是 Deployment 對象的一個字段,名叫 RollingUpdateStrategy,如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
...
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1

在上面這個 RollingUpdateStrategy 的配置中,maxSurge 指定的是除了 DESIRED 數(shù)量之外,在一次“滾動”中,Deployment 控制器還可以創(chuàng)建多少個新 Pod;而 maxUnavailable 指的是,在一次“滾動”中,Deployment 控制器可以刪除多少個舊 Pod。

同時,這兩個配置還可以用前面我們介紹的百分比形式來表示,比如:maxUnavailable=50%,指的是我們最多可以一次刪除“50%*DESIRED 數(shù)量”個 Pod。

結(jié)合以上講述,現(xiàn)在我們可以擴展一下 Deployment、ReplicaSet 和 Pod 的關(guān)系圖了。

如上所示,Deployment 的控制器,實際上控制的是 ReplicaSet 的數(shù)目,以及每個 ReplicaSet 的屬性。

而一個應用的版本,對應的正是一個 ReplicaSet;這個版本應用的 Pod 數(shù)量,則由 ReplicaSet 通過它自己的控制器(ReplicaSet Controller)來保證。

通過這樣的多個 ReplicaSet 對象,Kubernetes 項目就實現(xiàn)了對多個“應用版本”的描述。

以上就是k8s編排之Deployment知識點詳解的詳細內(nèi)容,更多關(guān)于k8s編排Deployment的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論