k8s五 | Pod的作業(yè)副本與滾動更新控制器Deployment

這篇文章主要介紹Pod如何通過Deployment的控制器ReplicatSet實(shí)現(xiàn)水平擴(kuò)展與滾動更新。

一. 控制器模式

在kubernetes項(xiàng)目中的設(shè)計(jì)思想是“控制器”模式谆焊,在前面文章k8s(一) 基本概念與組件原理中介紹的controller manager組件就是一系列控制器的集合航揉,我們可以通過 Kubernetes 項(xiàng)目的 pkg/controller 目錄查看這些控制器:

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

這個目錄下面的每一個控制器驶乾,都以獨(dú)有的方式負(fù)責(zé)某種編排功能邑飒。
以部署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

上面Yaml文件定義的spec.replicas字段為2,即確保攜帶了app=nginx標(biāo)簽的 Pod 的個數(shù)永遠(yuǎn)等于2個级乐,這就是我們定義的期望狀態(tài)疙咸,意味著如果集群中超過兩個副本就會刪除舊的Pod,反之就會有新的Pod創(chuàng)建风科。實(shí)現(xiàn)方式大概如下:

  1. Deployment 控制器從 Etcd 中獲取到所有攜帶了app: nginx標(biāo)簽的 Pod撒轮,然后統(tǒng)計(jì)它們的數(shù)量,這就是實(shí)際狀態(tài)贼穆;
  2. Deployment 對象的 Replicas 字段的值就是期望狀態(tài)题山,即我們事先定義的副本數(shù);
  3. Deployment 控制器將兩個狀態(tài)做比較故痊,然后根據(jù)比較結(jié)果顶瞳,確定是創(chuàng)建 Pod,還是刪除已有的 Pod愕秫。

Deployment 這種控制器的設(shè)計(jì)原理慨菱,就是用一種對象管理另一種對象的方式。

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

unmin.club

二. 作業(yè)副本的水平擴(kuò)展/收縮

在上面例子中簡單介紹了Deployment控制器的實(shí)現(xiàn)方式甜孤,實(shí)現(xiàn)了 Kubernetes 項(xiàng)目中一個非常重要的功能:Pod 的“水平擴(kuò)展 / 收縮”(horizontal scaling out/in)协饲。這個功能,是從 PaaS 時代開始课蔬,一個平臺級項(xiàng)目就必須具備的編排能力囱稽。

舉個例子郊尝,如果你更新了 Deployment 的 Pod 模板(比如二跋,修改了容器的鏡像),那么 Deployment 就需要遵循一種叫作“滾動更新”(rolling update)的方式流昏,來升級現(xiàn)有的容器扎即。而這個能力的實(shí)現(xiàn),依賴的是 Kubernetes 項(xiàng)目中的一個非常重要的概念(API 對象):ReplicaSet况凉。

Deployment 實(shí)際控制的是ReplicaSet對象谚鄙,由ReplicaSet來管理Pod,


unmin.club

通過上圖刁绒,我們可以看到定義了 replicas=3 的 Deployment闷营,與它的 ReplicaSet,以及 Pod 的關(guān)系,實(shí)際上是一種“層層控制”的關(guān)系傻盟。Deployment 通過“控制器模式”速蕊,來操作 ReplicaSet 的個數(shù)和屬性,進(jìn)而實(shí)現(xiàn)“水平擴(kuò)展 / 收縮”和“滾動更新”這兩個編排動作娘赴。

實(shí)現(xiàn)水平擴(kuò)展 / 收縮
Deployment Controller 只需要修改它所控制的 ReplicaSet 的 Pod 副本個數(shù)就可以實(shí)現(xiàn)水平擴(kuò)展 / 收縮规哲。我們可以通過修改YAML文件或者kubectl scale來具體實(shí)現(xiàn),比如將上面的nginx-deployment的副本數(shù)擴(kuò)展為4:

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

三. 滾動更新

1. 滾動更新的實(shí)現(xiàn)原理

我們根據(jù)上面例子中的nginx-deployment來進(jìn)一步的理解滾動更新的實(shí)現(xiàn)過程诽表。

$ kubectl create -f nginx-deployment.yaml --record
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s

--record 記錄下你每次操作所執(zhí)行的命令唉锌,以方便后面查看。
返回結(jié)果中四個字段分別對應(yīng)的含義如下:

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

下面我們通過kubectl rollout status 來實(shí)時查看資源對象的狀態(tài)變化

$ 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é)果中可以看到已經(jīng)有2個Pod進(jìn)入了UP-TO-DATE狀態(tài),稍微等待一下后查看Deployment的狀態(tài)

NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           20s

可以看到3個Pod都已經(jīng)變成了AVAILABLE 狀態(tài)宗雇,然后再查看這個Deployment控制的ReplicaSet

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

根據(jù)上面流程我們可以看到昂芜,當(dāng)提交了創(chuàng)建Deployment請求后,Deployment Controller 就會立即創(chuàng)建一個 Pod 副本個數(shù)為 3 的 ReplicaSet赔蒲,其中ReplicaSet 的 DESIRED泌神、CURRENT 和 READY 字段的含義,和 Deployment 中是一致的舞虱。所以欢际,相比之下,Deployment 只是在 ReplicaSet 的基礎(chǔ)上矾兜,添加了 UP-TO-DATE 這個跟版本有關(guān)的狀態(tài)字段损趋。

現(xiàn)在來修改Deployment的Pod模板來觸發(fā)滾動更新
可以直接使用kubectl edit命令或者通過修改YAML文件更新資源


$ kubectl edit deployment/nginx-deployment
... 
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1 # 1.7.9 -> 1.9.1
        ports:
        - containerPort: 80
...
deployment.extensions/nginx-deployment edited

保存退出,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
...
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
...
  Normal  ScalingReplicaSet  24s   deployment-controller  Scaled up replica set nginx-deployment-1764197365 to 1
  Normal  ScalingReplicaSet  22s   deployment-controller  Scaled down replica set nginx-deployment-3167673210 to 2
  Normal  ScalingReplicaSet  22s   deployment-controller  Scaled up replica set nginx-deployment-1764197365 to 2
  Normal  ScalingReplicaSet  19s   deployment-controller  Scaled down replica set nginx-deployment-3167673210 to 1
  Normal  ScalingReplicaSet  19s   deployment-controller  Scaled up replica set nginx-deployment-1764197365 to 3
  Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set nginx-deployment-3167673210 to 0

通過事件日志我們可以清楚的看到滾動更新的具體流程即:

  1. Deployment Controller 使用這個修改后的 Pod 模板,創(chuàng)建一個新的ReplicaSet(hash=1764197365)返帕,這個新的 ReplicaSet 的初始 Pod 副本數(shù)是:0桐玻。
  2. Deployment Controller 開始將這個新的 ReplicaSet 所控制的 Pod 副本數(shù)從 0 個變成 1 個,即:“水平擴(kuò)展”出一個副本荆萤。
  3. Deployment Controller 又將舊的 ReplicaSet(hash=3167673210)所控制的舊 Pod 副本數(shù)減少一個镊靴,即:“水平收縮”成兩個副本。

直到舊ReplicaSet的Pod副本數(shù)為0,新ReplicaSet的副本數(shù)為3偏竟,則意味著滾動更新完成算行。完成后我們可以查看RS的狀態(tài):

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

可以看到Hash為3167673210的舊ReplicaSet已經(jīng)被水平伸縮為0個副本。

將一個集群中正在運(yùn)行的多個 Pod 版本苫耸,交替地逐一升級的過程州邢,就是“滾動更新”。

2. 滾動更新的配置

為了進(jìn)一步保證服務(wù)的連續(xù)性褪子,Deployment Controller 還會確保量淌,在任何時間窗口內(nèi),只有指定比例的 Pod 處于離線狀態(tài)嫌褪。同時呀枢,它也會確保柠横,在任何時間窗口內(nèi)乔宿,只有指定比例的新 Pod 被創(chuàng)建出來。這兩個比例的值都是可以配置的梁呈,默認(rèn)都是 DESIRED 值的 25%缨伊。

所以摘刑,在上面這個 Deployment 例子中,它有 3 個 Pod 副本刻坊,那么控制器在“滾動更新”的過程中永遠(yuǎn)都會確保至少有 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)在我們可以擴(kuò)展一下 Deployment夸盟、ReplicaSet 和 Pod 的關(guān)系圖


unmin.club

如上所示蛾方,Deployment 的控制器,實(shí)際上控制的是 ReplicaSet 的數(shù)目,以及每個 ReplicaSet 的屬性桩砰。而一個應(yīng)用的版本拓春,對應(yīng)的正是一個 ReplicaSet;這個版本應(yīng)用的 Pod 數(shù)量亚隅,則由 ReplicaSet 通過它自己的控制器(ReplicaSet Controller)來保證硼莽。通過這樣的多個 ReplicaSet 對象,Kubernetes 項(xiàng)目就實(shí)現(xiàn)了對多個“應(yīng)用版本”的描述煮纵。

3. 對應(yīng)用進(jìn)行版本控制

在日常的代碼更新中懂鸵,我們都是通過版本來控制代碼的上線,但上線過程中難免會有升級失敗的情況行疏,下面我們來實(shí)踐操作下Deployment對應(yīng)用進(jìn)行版本控制的具體流程匆光,方便我們了接具體的實(shí)現(xiàn)原理。

首先我們通過kubectl set image的指令來修改nginx-depolyment使用的鏡像酿联,把原先的鏡像替換為錯誤的鏡像终息,來模擬升級失敗。

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
deployment.extensions/nginx-deployment image updated

由于這個 nginx:1.91 鏡像在 Docker Hub 中并不存在贞让,所以這個 Deployment 的“滾動更新”被觸發(fā)后周崭,會立刻報錯并停止。這時喳张,我們來檢查一下 ReplicaSet 的狀態(tài)休傍,如下所示:

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1764197365   2         2         2       24s
nginx-deployment-3167673210   0         0         0       35s
nginx-deployment-2156724341   2         2         0       7s

現(xiàn)在新版本的 ReplicaSet(hash=2156724341)已經(jīng)創(chuàng)建了兩個 Pod,但是它們都沒有進(jìn)入 READY 狀態(tài)蹲姐。這當(dāng)然是因?yàn)檫@兩個 Pod 都拉取不到有效的鏡像磨取。與此同時,舊版本的 ReplicaSet(hash=1764197365)的“水平收縮”柴墩,也自動停止了忙厌。此時,已經(jīng)有一個舊 Pod 被刪除江咳,還剩下兩個舊 Pod逢净。

現(xiàn)在我們可以通過kubectl rollout undo命令將Deployment回滾到上一個版本。

$ kubectl rollout undo deployment/nginx-deployment
deployment.extensions/nginx-deployment

如果我們需要回滾到指定版本的話歼指,可以通過kubectl rollout history來查看歷史變更的版本爹土,這是因?yàn)榍懊嫖覀儎?chuàng)建的時候添加--record參數(shù),所以都會被記錄下來踩身。

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl create -f nginx-deployment.yaml --record
2           kubectl edit deployment/nginx-deployment
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.91

可以看到變更次數(shù)為三次胀茵,失敗的則為版本3,現(xiàn)在我們通過--to-revision=2 指定回滾到版本2挟阻。

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment.extensions/nginx-deployment

當(dāng)發(fā)布的版本次數(shù)過多時琼娘,Deployment同樣會創(chuàng)建很多的ReplicaSet峭弟,我們可以通過修改 spec.revisionHistoryLimit參數(shù),來控制 Kubernetes 為 Deployment 保留的“歷史版本”個數(shù)脱拼。

總結(jié):現(xiàn)在我們通過實(shí)踐知道了kubernetes設(shè)計(jì)思想實(shí)際是通過一個個控制器來具體實(shí)現(xiàn)的瞒瘸,也了解了Deployment 這個 Kubernetes 項(xiàng)目中最基本的編排控制器的實(shí)現(xiàn)原理和使用方法。Deployment 實(shí)際上是一個兩層控制器熄浓。首先情臭,它通過 ReplicaSet 的個數(shù)來描述應(yīng)用的版本;然后赌蔑,它再通過 ReplicaSet 的屬性(比如 replicas 的值)俯在,來保證 Pod 的副本數(shù)量。


上篇文章:k8s四 | 深入理解Pod資源對象
系列文章:深入理解Kuerneters
參考資料:深入剖析Kubernetes-張磊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惯雳,一起剝皮案震驚了整個濱河市朝巫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌石景,老刑警劉巖劈猿,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異潮孽,居然都是意外死亡揪荣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門往史,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仗颈,“玉大人,你說我怎么就攤上這事椎例“ぞ觯” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵订歪,是天一觀的道長脖祈。 經(jīng)常有香客問我,道長刷晋,這世上最難降的妖魔是什么盖高? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮眼虱,結(jié)果婚禮上喻奥,老公的妹妹穿的比我還像新娘。我一直安慰自己捏悬,他們只是感情好撞蚕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著邮破,像睡著了一般诈豌。 火紅的嫁衣襯著肌膚如雪仆救。 梳的紋絲不亂的頭發(fā)上抒和,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天矫渔,我揣著相機(jī)與錄音,去河邊找鬼摧莽。 笑死庙洼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的镊辕。 我是一名探鬼主播油够,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼征懈!你這毒婦竟也來了石咬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤卖哎,失蹤者是張志新(化名)和其女友劉穎鬼悠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亏娜,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡焕窝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了维贺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片它掂。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖溯泣,靈堂內(nèi)的尸體忽然破棺而出虐秋,到底是詐尸還是另有隱情,我是刑警寧澤垃沦,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布客给,位于F島的核電站,受9級特大地震影響栏尚,放射性物質(zhì)發(fā)生泄漏起愈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一译仗、第九天 我趴在偏房一處隱蔽的房頂上張望抬虽。 院中可真熱鬧,春花似錦纵菌、人聲如沸阐污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笛辟。三九已至功氨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間手幢,已是汗流浹背捷凄。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留围来,地道東北人跺涤。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像监透,于是被迫代替她去往敵國和親桶错。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348