天天看點

kubernetes-Deployment部署無狀态服務的原理詳解(二十五)

本文主要介紹kubernetes-Deployment部署無狀态服務的原理詳解。

引言

  k8s部署無狀态應用後,若需要更新應用時,可以通過使用ReplicationController或ReplicaSet實作更新,主要有兩種方式:

  • 直接删除所有現有的pod,然後建立新的pod;
  • 先建立新的pod,再删除舊pod。這裡面也有兩種方式,一種是先等所有新pod都運作成功後,應用切換到新pod通路,一次性删除所有舊pod;另一種是滾動更新方式逐漸建立pod代替舊pod。

      下面我們将先看一下常用的相關術語,然後看一下更新pod的演進方式。

其他相關術語

  Pod:每個Pod是一個或一組緊密相關的容器,每個Pod就像是一個獨立的邏輯機器,擁有自己的IP、主機名、程序等,運作一個獨立的應用程式,是K8S排程的基本機關。

  ReplicationController:簡稱RC,旨在建立和管理一個Pod的多個副本(replicas)。當Pod副本數少于指定數目,RC就會啟動運作新的Pod副本;多于指定數目,RC就會殺死多餘的Pod副本。

  ReplicaSet:是新一代的RC,其相比于RC,Pod選擇器的表達能力更強,其選擇器可比對缺少某個标簽或特定标簽名的Pod。

删舊pod,建新pod

  假設ReplicationController管理一組v1版本的pod,直接通過将pod模闆修改為v2版本的鏡像,删除舊的pod執行個體,RC檢測到目前沒有pod比對标簽選擇器,就會建立新的執行個體。

  1. 階段1:原v1版本的RC有3個副本pod-v1。
  2. 階段2:pod模闆發生修改,由初始的v1版本修改為v2版本。
  3. 階段3:pod-v1被手動删除。
  4. 階段4:RC檢測到目前沒有pod比對标簽選擇器,根據模闆建立新的pod-v2。在階段3過渡到階段4期間,服務會出現短暫的不可用。

建新pod,删舊pod

  如果客戶不能接受更新更新期間出現短暫的不可用的服務,那就需要先建立新的pod,再删除舊pod,這需要更多的硬體資源來支撐新舊pod同時存在的場景。

建立所有新pod,删除所有舊pod

  pod一般是通過Service來暴露服務的,在運作新版本pod前,Service都是通路的舊版本pod,當新版本pod建立且正常運作後,修改服務标簽選擇器切換Service流量至新pod,切換完畢後,删除舊RC,就可以删除所有舊pod。這種方式就是所謂的

藍綠部署

  1. 階段2:建立v2版本的RC,并且RC-v2自動建立了新的v2版本的pod。
  2. 階段3:Service的流量切換到pod-v2,正常運作起來。
  3. 階段4:删除RC-v1,進而自動删除pod-v1。

滾動建立和删除pod

  除了一次性建立新pod再一次性删除舊pod,我們還可以逐漸遞進的對舊版本pod進行删除,對新版本pod進行建立。這個可以通過對舊版本RC逐漸縮容,同時對新版本RC進行擴容來實作。

  1. 階段1:v1版本的RC副本數為3,有3個pod-v1。
  2. 階段2:RC-v1副本數降為2,自動删除一個pod-v1,此時,建立一個v2版本的RC,且pod副本數為1,會自動建立一個v2版本的pod。
  3. 階段3:RC-v1副本數降為1,自動再删除一個pod-v1,RC-v2的副本數為2,再自動建立一個pod-v2。
  4. 階段4:RC-v1副本數降為0,并且删掉RC-v1,RC-v2副本數升為3,進而建立第3個pod-v2,至此完成滾動更新。

引入Deployment

  ReplicationController和ReplicaSet這兩種資源對象需要其他控制器進行配合才可以實作滾動更新,并且難度大,是以k8s提供了一種基于ReplicaSet的資源對象Deployment可以支援

聲明式

地更新應用。

Deployment介紹

Deployment概述

  Deployment是K8s在1.2版本引入的,是一種更高階的資源,用于部署應用程式并以聲明的方式更新應用,進而更好地解決pod編排問題。

Deployment使用機制

  Deployment在内部使用了ReplicaSet實作編排pod功能,當建立一個Deployment時,ReplicaSet資源會随之建立,ReplicaSet是新一代的ReplicationController,并推薦使用它替代ReplicationController來複制和管理Pod,在使用Deployment時,實際的Pod是由Deployment的ReplicaSet建立和管理的。

Deployment使用場景

  1. 建立Deployment對象生成對應的ReplicaSet并完成pod副本建立;
  2. 通過檢查Deployment狀态(檢視pod副本數量是否達到預期值)檢驗應用部署是否完成;
  3. 更新Deployment進而建立新的pod;
  4. 目前Deployment不穩定或故障,復原到之前某個版本的Deployment(曆史版本revision)
  5. 暫停Deployment并修改多個pod的template spec配置項,再恢複Deployment進行新的釋出部署;
  6. 擴充Deployment進而應對高負載場景;
  7. 清理不再需要使用的舊版本ReplicaSet;

Deployment使用

Deployment基本指令

  假設Deployment的服務名稱為test-tomcat-deploy,yaml模闆檔案名為test-tomcat.yaml。使用指令時,deploy等價于deployment等價于deployments。若需要指定命名空間ns_name時,需要加上

-n ns_name

建立deployment

  • 基于模闆建立

    $ kubectl create -f test-tomcat.yaml

删除deployment

  • 基于模闆删除

    $ kubectl delete -f test-tomcat.yaml

  • 基于名稱删除

    $ kubectl delete deployment test-tomcat-deploy

更新deployment

  • 基于模闆更新

    $ kubectl apply -f test-tomcat.yaml

  • 基于名稱更新

    $ kubectl edit deploy/test-tomcat-deploy

檢視deployment

  • 基于模闆檢視

    $ kubectl get deploy test-tomcat-deploy -o yaml

  • 基于名稱檢視

    $ kubectl describe deployments test-tomcat-deploy

  • 檢視清單

    $ kubectl get deploy

資源對象資訊

Deployment資訊

[root@localhost ~]# kubectl get deploy -n kube-system
NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
st-ui-wnunzeyg   1         1         1            1           1d
st-ui-x3w4xumy   1         1         1            1           1d
           
  • DESIRED

    :pod副本數量的期望值(Deployment中定義的Replica數)
  • CURRENT

    :目前Replica值(Deployment實際建立的ReplicaSet中Replica值),該值會一直增加到DESIRED值為止才算整個應用執行個體建立完畢,部署才算完成。
  • UP-TO-DATE

    :最新版本的pod副本數量,用于訓示在滾動更新過程中,有多少pod副本已成功更新。(Deployment滾動更新過程中ReplicaSet的Replica成功數)
  • AVAILABLE

    :目前叢集中可用pod副本數。(Deployment建立的ReplicaSet中Replica存活數)
  • AGE

    :表示距離最後一次操作的時長。

ReplicaSet資訊

[root@localhost ~]# kubectl get rs -n kube-system
NAME                        DESIRED   CURRENT   READY     AGE
st-ui-wnunzeyg-391614280    1         1         1         1d
st-ui-x3w4xumy-1656786196   1         1         1         1d
           

  我們可以看到ReplicaSet的命名和Deployment是相關的,ReplicaSet命名是以Deployment名為字首,在Deployment名字基礎上又加了一串随機數。

Pods資訊

[root@localhost ~]# kubectl get pods -n kube-system
NAME                              READY     STATUS    RESTARTS   AGE
st-ui-wnunzeyg-391614280-3brk8    1/1       Running   0          1d
st-ui-x3w4xumy-1656786196-f4w8z   1/1       Running   0          1d
           

  pod名稱以Deployment中的ReplicaSet名稱為字首,在此基礎上又加了随機字元串。

Deployment更新

更新政策

  在Deployment中,可以通過spec.strategy指定Pod更新的政策,目前支援:

Recreate(重建)

RollingUpdate(滾動更新)

,預設是RollingUpdate。

  Recreate:設定

spec.strategy.type=Recreate

,更新方式為:Deployment在更新Pod時,會先殺掉所有正在運作的Pod,然後建立新的Pod。

  RollingUpdate:設定

spec.strategy.type=RollingUpdate

,更新方式為:Deployment會以滾動的方式來漸變性的更新Pod,即Pod新版本的遞增,舊版本的遞減的一個過程。

滾動更新

概念

  “滾動”,給人的是一種“圓”的印象,持續,不中斷的意思,類似于“持續傳遞”的理念。RollingUpdate政策指

一次僅更新一個Pod

,并且逐個更新,而不是一次性将所有的服務都關閉,避免業務中斷。

原理

  1. 初始建立Deployment,系統建立了一個ReplicaSet,并按照使用者的需求建立了3個Pod副本;
  2. 當更新Deployment時,系統建立一個新的ReplicaSet,并将其副本數量擴充到1,然後将舊的ReplicaSet縮減為2;
  3. 系統繼續按照相同的更新政策對新舊兩個ReplicaSet進行逐個調整。
  4. 最後,新的ReplicaSet運作了3個新版本的Pod副本,舊的ReplicaSet副本數量則縮減為0。

Deployment復原

  復原:通過滾動更新的政策可以平滑的更新Deployment,若更新出現問題,需要最快且最好的方式回退到上一次能夠提供正常工作的版本。為此K8S提供了復原機制。

  revision:更新應用時,K8S都會記錄目前的版次,即為revision,當更新出現問題時,可通過復原到某個特定的revision,預設配置下,K8S隻會保留最近的幾個revision,可以通過Deployment配置檔案中的spec.revisionHistoryLimit屬性增加revision數量。

  更新或復原:每次更新或復原時,revision都會自增1,復原可以看作是一次更新,是一次更新為原版本的操作。

kubectl指令使用

檢視修訂版本記錄

$ kubectl rollout history deployment deployment_name

檢視某個曆史記錄的詳細資訊

$ kubectl rollout history deployment deployment_name --revision=2

其中

--revision

表示指定修訂版本;

復原到上一個版本

$ kubectl rollout undo deployment deployment_name

復原到指定版本

$ kubectl rollout undo deployment deployment_name --to-revision=2

其中,

--to-revision

表示復原到指定的修訂版本。

API接口使用

POST

/apis/apps/v1beta1/namespaces/{namespace}/deployments/{name}/rollback
如:
curl -k -H 'Authorization: Bearer token_xxxx' -H 'Content-Type:application/json' -X POST -d '{
    "kind": "DeploymentRollback",
    "apiVersion": "extensions/v1beta1",
    "name": "deployment_name",
    "rollbackTo": {
        "revision": 2
    }
}' https://localhost:6443/apis/extensions/v1beta1/namespaces/default/deployments/deployment_name/rollback
           

  其中:name和rollbackTo.revision為必須字段,name為資源名稱,rollbackTo.revision為回退的版本,若要回退上一個版本,即為0。

Q&A

什麼是聲明式?和其他方式有什麼差別?

  除了聲明式,我們一般還有指令式,也就是指令式。我們看看這兩者定義和差別。

指令式:

  1. 定義

    :使用計算機某種語言的指令(指令)來完成程式的運作,比如我們通過編寫shell腳本、python腳本運作程式應用。
  2. 編寫

    :編寫複雜,強依賴開發人員的經驗,需要考慮目标環境以及流程細節,處理各種異常情況和邊緣情況等。
  3. 事務性

    :較難保持事務性,強依賴腳本流程,若腳本在執行過程中出現異常,程式應用會處于一個中間狀态,是以多次運作,可能會達到不同的狀态和結果。
  4. 維護性

    :開發後,需要有對應的運維文檔來協助運維人員維護同一個腳本,不便于維護。

聲明式:

  1. 定義

    :使用配置檔案直接描述最終狀态,比如k8s中的yaml檔案,描述最終要啟動多少副本,要多少cpu之類的狀态和結果。
  2. 編寫

    :易于編寫,隻要會寫配置檔案,告訴應用達到什麼樣的結果和狀态即可,不需要考慮流程和目标環境的細節,
  3. 事務性

    :天然的事務性,要麼執行成功,要麼失敗,不會出現多種中間狀态,重複執行保持一緻的狀态和結果。
  4. 維護性

    :配置檔案中直接描述了最終狀态和結果,無需過多的運維文檔來描述資訊。

參考

《Kubernetes in Action》

《Kubernetes權威指南》

k8s官網

燒不死的鳥就是鳳凰

繼續閱讀