前言
上篇文章介紹了RS罚拟,RS可以保證維持一定數量的副本台诗,多了剔除,少了自動拉起舟舒,可以方便的擴縮容拉庶,可以替換鏡像更新升級,替換之后只對新的Pod有效秃励。但是官方建議我們不應該直接使用RS來控制副本氏仗,而是使用Deployment來間接控制副本。
Deployment可以更好的解決服務編排的問題夺鲜,在1.2版本開始引入皆尔,這種控制器是通過控制RS來間接控制Pod,所以具備RS的所有功能币励,并且對RS的更新升級做了優(yōu)化
在RS中鏡像更新升級只有當我們刪除原來的Pod慷蠕,自動拉起新的Pod時才生效,那么這個刪除原來Pod的動作能不能自動運行食呻,每次按批量的刪除Pod達到一個滾動升級的效果流炕,或者刪除部分Pod停止,等待一段時間再繼續(xù)達到一個灰度發(fā)布的效果仅胞。更新完后上一次的版本能否做版本保留每辟,以便隨時回退。
帶著上面的問題我們看Deployment是否可以解決
Deployment
通過上面介紹干旧,我們知道RS具備的功能還是挺多的渠欺,只是不太自動化,比如更新升級需要刪除原來的Pod椎眯,這個動作是手動的挠将,我們希望是能夠自動的升級,于是Deployment就出現了编整,它在RS之上做個擴展舔稀,跟我們寫框架一樣,最開始提供出來的都是原始的api掌测,然后在這之上做一個二次封裝内贮,以便更好的使用。
Deployment可以持有多個RS,這樣我們就能隨時切換版本贺归,所以她還支持回退的功能
deploy的工作機制如下圖所示
資源文件清單
apiVersion: apps/v1
kind: Deployment # Deployment類型
metadata:
name: # Deployment名稱
namespace:
labels:
spec:
replicas: # 副本數量默認為1
revisionHistoryLimit: # 保留歷史版本數量也是就RS,默認是10個
paused: # 暫停部署断箫,默認是false
progressDeadlineSeconds: # 部署超時時間(s)拂酣,默認是600
strategy: # 更新策略
type: # 更新策略 Recreate(先刪除所有,再創(chuàng)建)與RollingUpdate(滾動 默認)
rollingUpdate: # 滾動更新
maxSurge: # 可以額外多出的Pod數仲义,可以為百分比婶熬,也可以為整數
maxUnavaliable: # 可以忍受多少個Pod不可用,可以為百分比埃撵,也可以為整數
selector: # 與RS一樣通過它指定該控制器管理哪些pod
matchLabels:
matchExpressions:
template: # 與Pod定義一樣
metadata:
spec:
創(chuàng)建Deployment
創(chuàng)建一個具有三個副本的deployment
編寫 deployment.yaml 內容如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 3
revisionHistoryLimit: 5 # 保留五個版本
strategy:
type: Recreate # 更新策略 先刪除所有赵颅,再創(chuàng)建
selector:
matchExpressions:
- {key: app, operator: In,values: [nginx]}
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.1
創(chuàng)建deployment,觀察deploy,rs,pod詳情暂刘,既然Pod通過管理rs來控制Pod饺谬,那么也會創(chuàng)建出一個rs
# 創(chuàng)建deploy
[root@master deploy]# kubectl create -f deployment.yaml
deployment.apps/deployment created
# 查看deploy,rs,pod
[root@master deploy]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 3/3 3 3 14s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-78ff8d9ff6 3 3 3 14s
NAME READY STATUS RESTARTS AGE
pod/deployment-78ff8d9ff6-9xkjl 1/1 Running 0 14s
pod/deployment-78ff8d9ff6-c4jgz 1/1 Running 0 14s
pod/deployment-78ff8d9ff6-c7r65 1/1 Running 0 14s
通過上面結果顯示,可以知道谣拣,創(chuàng)建deploy同時也會創(chuàng)建出一個rs募寨,rs得名字再deploy的基礎上加上一串字符串如78ff8d9ff6,Pod的命名又是在rs的基礎上加上一串字符串如9xkjl
擴縮容
擴縮容實際上是RS的功能森缠,所以使用方式也是一樣的拔鹰,會有編輯文件與命令行兩種方式
編輯文件方式
# 修改文件如下部分將副本擴到5
#spec:
# replicas: 5
[root@master deploy]# kubectl edit deploy deployment
deployment.apps/deployment edited
# 查看詳情,此時已經有五個副本
[root@master deploy]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 5/5 5 5 97s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-78ff8d9ff6 5 5 5 97s
NAME READY STATUS RESTARTS AGE
pod/deployment-78ff8d9ff6-9xkjl 1/1 Running 0 97s
pod/deployment-78ff8d9ff6-c4jgz 1/1 Running 0 97s
pod/deployment-78ff8d9ff6-c7r65 1/1 Running 0 97s
pod/deployment-78ff8d9ff6-xvg6w 1/1 Running 0 3s
pod/deployment-78ff8d9ff6-zj878 1/1 Running 0 3s
通過命令行方式
# 使用命令進行縮容贵涵,將副本數改為3
[root@master deploy]# kubectl scale deploy deployment --replicas=3
deployment.apps/deployment scaled
# 查看詳情列肢,此時只有三個副本
[root@master deploy]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 3/3 3 3 2m21s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-78ff8d9ff6 3 3 3 2m21s
NAME READY STATUS RESTARTS AGE
pod/deployment-78ff8d9ff6-9xkjl 1/1 Running 0 2m21s
pod/deployment-78ff8d9ff6-c4jgz 1/1 Running 0 2m21s
pod/deployment-78ff8d9ff6-zj878 1/1 Running 0 47s
鏡像更新
重建更新
上面我們創(chuàng)建的yaml其更新方式為 Recreate--先刪除所有Pod,再創(chuàng)建新的Pod
為了更好的觀察更新過程宾茂,新打開一個窗口監(jiān)控Pod的變化
# -w 觀察Pod的變化瓷马,有變動會自動打印出日志
[root@master ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
deployment-78ff8d9ff6-9xkjl 1/1 Running 0 3m40s
deployment-78ff8d9ff6-c4jgz 1/1 Running 0 3m40s
deployment-78ff8d9ff6-zj878 1/1 Running 0 2m6s
通過命令方式更新鏡像
# 將鏡像版本改為1.17.1
[root@master deploy]# kubectl set image deploy deployment nginx=nginx:1.17.1
deployment.apps/deployment image updated
# 查看詳情
[root@master ~]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 3/3 3 3 4m7s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-74cdbf844b 3 3 3 5s
replicaset.apps/deployment-78ff8d9ff6 0 0 0 4m7s
NAME READY STATUS RESTARTS AGE
pod/deployment-74cdbf844b-bbn47 1/1 Running 0 5s
pod/deployment-74cdbf844b-dzgl8 1/1 Running 0 5s
pod/deployment-74cdbf844b-jccdz 1/1 Running 0 5s
通過上面數據看出,原先的RS deployment-78ff8d9ff6已經沒有Pod在運行刻炒,新的deployment-74cdbf844b運行中决采,觀察Pod的名稱也與之前的不一樣了,說明Pod都是新創(chuàng)建的坟奥。
觀察Pod的更新詳情(更新之前先打開一個新窗口監(jiān)控)
[root@master ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
deployment-78ff8d9ff6-9xkjl 1/1 Running 0 3m40s
deployment-78ff8d9ff6-c4jgz 1/1 Running 0 3m40s
deployment-78ff8d9ff6-zj878 1/1 Running 0 2m6s
deployment-78ff8d9ff6-zj878 1/1 Terminating 0 2m27s
deployment-78ff8d9ff6-c4jgz 1/1 Terminating 0 4m1s
deployment-78ff8d9ff6-9xkjl 1/1 Terminating 0 4m1s
deployment-78ff8d9ff6-c4jgz 0/1 Terminating 0 4m1s
deployment-78ff8d9ff6-c4jgz 0/1 Terminating 0 4m1s
deployment-78ff8d9ff6-c4jgz 0/1 Terminating 0 4m1s
deployment-78ff8d9ff6-9xkjl 0/1 Terminating 0 4m2s
deployment-78ff8d9ff6-9xkjl 0/1 Terminating 0 4m2s
deployment-78ff8d9ff6-9xkjl 0/1 Terminating 0 4m2s
deployment-78ff8d9ff6-zj878 0/1 Terminating 0 2m28s
deployment-78ff8d9ff6-zj878 0/1 Terminating 0 2m28s
deployment-78ff8d9ff6-zj878 0/1 Terminating 0 2m28s
deployment-74cdbf844b-bbn47 0/1 Pending 0 0s
deployment-74cdbf844b-jccdz 0/1 Pending 0 0s
deployment-74cdbf844b-dzgl8 0/1 Pending 0 0s
deployment-74cdbf844b-bbn47 0/1 Pending 0 0s
deployment-74cdbf844b-jccdz 0/1 Pending 0 0s
deployment-74cdbf844b-dzgl8 0/1 Pending 0 0s
deployment-74cdbf844b-bbn47 0/1 ContainerCreating 0 0s
deployment-74cdbf844b-jccdz 0/1 ContainerCreating 0 0s
deployment-74cdbf844b-dzgl8 0/1 ContainerCreating 0 1s
deployment-74cdbf844b-bbn47 1/1 Running 0 1s
deployment-74cdbf844b-dzgl8 1/1 Running 0 2s
deployment-74cdbf844b-jccdz 1/1 Running 0 2s
從上面的更新過程可以看出树瞭,先是停掉原來的Pod,所有Pod都停止后才創(chuàng)建新的Pod爱谁,這其實是deploy的一種更新策略Recreate晒喷,先刪再建,還有一種更新策略便是滾動更新 RollingUpdate访敌,默認也是滾動更新
滾動更新
滾動更新有兩個參數可以設置
maxSurge: 25% # 可以額外多出的Pod數凉敲,默認為百分比25%,也可以為整數
maxUnavailable: 25% # 可以忍受多少個Pod不可用,默認為百分比25%爷抓,也可以為整數
修改deployment.yaml 內容如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 3
revisionHistoryLimit: 5 # 保留五個版本
strategy: # 更新策略
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
selector:
matchExpressions:
- {key: app, operator: In,values: [nginx]}
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.1
刪除原來的deploy重新創(chuàng)建
# 刪除
[root@master deploy]# kubectl delete -f deployment.yaml
deployment.apps "deployment" deleted
# 創(chuàng)建
[root@master deploy]# kubectl create -f deployment.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/deployment created
# 查看
[root@master deploy]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 3/3 3 3 11s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-78ff8d9ff6 3 3 3 11s
NAME READY STATUS RESTARTS AGE
pod/deployment-78ff8d9ff6-7wfx9 1/1 Running 0 11s
pod/deployment-78ff8d9ff6-gvztv 1/1 Running 0 11s
pod/deployment-78ff8d9ff6-mrndc 1/1 Running 0 11s
在更新升級之前同樣的新打開一個窗口監(jiān)控Pod的變化 kubectl get pod -w
將鏡像版本修改為1.17.1
# 修改鏡像版本
[root@master deploy]# kubectl set image deploy deployment nginx=nginx:1.17.1
deployment.apps/deployment image updated
# 觀察 此時兩個RS都有正在運行的Pod
[root@master deploy]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 3/3 2 3 42s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-74cdbf844b 2 2 1 2s
replicaset.apps/deployment-78ff8d9ff6 2 2 2 42s
NAME READY STATUS RESTARTS AGE
pod/deployment-74cdbf844b-hc2jh 0/1 ContainerCreating 0 1s
pod/deployment-74cdbf844b-qhmzs 1/1 Running 0 2s
pod/deployment-78ff8d9ff6-7wfx9 1/1 Running 0 42s
pod/deployment-78ff8d9ff6-mrndc 1/1 Running 0 42s
#############################################################################
# 在此觀察78ff8d9ff6已經沒有Pod運行势决,所有存活Pod均在新的RS 74cdbf844b
[root@master deploy]# kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment 3/3 3 3 104s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-74cdbf844b 3 3 3 64s
replicaset.apps/deployment-78ff8d9ff6 0 0 0 104s
NAME READY STATUS RESTARTS AGE
pod/deployment-74cdbf844b-2mfqh 1/1 Running 0 61s
pod/deployment-74cdbf844b-hc2jh 1/1 Running 0 63s
pod/deployment-74cdbf844b-qhmzs 1/1 Running 0 64s
從上面的結果可以看出會有兩個RS同時有存活的Pod,并不是先刪除完所有的Pod再創(chuàng)建新的蓝撇。
觀察Pod的更新詳情(更新之前先打開一個新窗口監(jiān)控)
[root@master ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
deployment-78ff8d9ff6-7wfx9 1/1 Running 0 27s
deployment-78ff8d9ff6-gvztv 1/1 Running 0 27s
deployment-78ff8d9ff6-mrndc 1/1 Running 0 27s
deployment-74cdbf844b-qhmzs 0/1 Pending 0 0s
deployment-74cdbf844b-qhmzs 0/1 Pending 0 0s
deployment-74cdbf844b-qhmzs 0/1 ContainerCreating 0 0s
deployment-74cdbf844b-qhmzs 1/1 Running 0 1s
deployment-78ff8d9ff6-gvztv 1/1 Terminating 0 41s
deployment-74cdbf844b-hc2jh 0/1 Pending 0 0s
deployment-74cdbf844b-hc2jh 0/1 Pending 0 0s
deployment-74cdbf844b-hc2jh 0/1 ContainerCreating 0 0s
deployment-78ff8d9ff6-gvztv 0/1 Terminating 0 42s
deployment-78ff8d9ff6-gvztv 0/1 Terminating 0 42s
deployment-78ff8d9ff6-gvztv 0/1 Terminating 0 42s
deployment-74cdbf844b-hc2jh 1/1 Running 0 2s
deployment-78ff8d9ff6-7wfx9 1/1 Terminating 0 43s
deployment-74cdbf844b-2mfqh 0/1 Pending 0 0s
deployment-74cdbf844b-2mfqh 0/1 Pending 0 0s
deployment-74cdbf844b-2mfqh 0/1 ContainerCreating 0 0s
deployment-78ff8d9ff6-7wfx9 0/1 Terminating 0 43s
deployment-78ff8d9ff6-7wfx9 0/1 Terminating 0 43s
deployment-78ff8d9ff6-7wfx9 0/1 Terminating 0 43s
deployment-74cdbf844b-2mfqh 1/1 Running 0 1s
deployment-78ff8d9ff6-mrndc 1/1 Terminating 0 44s
deployment-78ff8d9ff6-mrndc 0/1 Terminating 0 45s
deployment-78ff8d9ff6-mrndc 0/1 Terminating 0 45s
deployment-78ff8d9ff6-mrndc 0/1 Terminating 0 45s
從更新的流程來看先是創(chuàng)建qhmzs果复,然后終止gvztv,創(chuàng)建hc2jh渤昌,終止7wfx9虽抄,創(chuàng)建2mfqh,終止mrndc独柑,這正是滾動更新的效果迈窟。
不止可以監(jiān)控pod,rs也可以監(jiān)控忌栅,下面是rs的監(jiān)控過程车酣,同樣可以反應出滾動更新的效果,78ff8d9ff6由三個副本慢慢變?yōu)?索绪,74cdbf844b由0慢慢變?yōu)?
[root@node02 ~]# kubectl get rs -w
NAME DESIRED CURRENT READY AGE
deployment-78ff8d9ff6 3 3 3 49s
deployment-74cdbf844b 1 0 0 0s
deployment-74cdbf844b 1 0 0 0s
deployment-74cdbf844b 1 1 0 0s
deployment-74cdbf844b 1 1 1 1s
deployment-78ff8d9ff6 2 3 3 53s
deployment-74cdbf844b 2 1 1 1s
deployment-78ff8d9ff6 2 3 3 53s
deployment-78ff8d9ff6 2 2 2 53s
deployment-74cdbf844b 2 1 1 1s
deployment-74cdbf844b 2 2 1 1s
deployment-74cdbf844b 2 2 2 3s
deployment-78ff8d9ff6 1 2 2 55s
deployment-78ff8d9ff6 1 2 2 55s
deployment-74cdbf844b 3 2 2 3s
deployment-78ff8d9ff6 1 1 1 55s
deployment-74cdbf844b 3 2 2 3s
deployment-74cdbf844b 3 3 2 3s
deployment-74cdbf844b 3 3 3 4s
deployment-78ff8d9ff6 0 1 1 56s
deployment-78ff8d9ff6 0 1 1 56s
deployment-78ff8d9ff6 0 0 0 56s
補充:校驗Pod是否使用了更新后的鏡像
# 進入容器查看nginx版本
[root@master deploy]# kubectl exec deployment-74cdbf844b-2dlst -- nginx -V
nginx version: nginx/1.17.1
版本回退
# 查看deploy的狀態(tài)
[root@master deploy]# kubectl rollout status deploy deployment
deployment "deployment" successfully rolled out
# 每次更新應用k8s都會保留當前的配置并且記錄一個版本
# 現在坐了一次更新骇径,所以會有兩個不同版本存在,有了版本保留之后者春,我們就能輕松的做應用回退
[root@master deploy]# kubectl rollout history deploy deployment
deployment.apps/deployment
REVISION CHANGE-CAUSE
1 kubectl create --filename=deployment.yaml --record=true
2 kubectl create --filename=deployment.yaml --record=true
# 通過指定版本號回退到指定的版本
[root@master deploy]# kubectl rollout undo deploy deployment --to-revision=1
deployment.apps/deployment rolled back
# 查看rs已經是使用原來的rs了
[root@master deploy]# kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-74cdbf844b 0 0 0 17m
deployment-78ff8d9ff6 3 3 3 18m
# Pod也是重新創(chuàng)建的
[root@master deploy]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-78ff8d9ff6-g4hx5 1/1 Running 0 10m
deployment-78ff8d9ff6-rw46x 1/1 Running 0 10m
deployment-78ff8d9ff6-ttq5j 1/1 Running 0 10m
# 查看deploy信息破衔,總共更新了三次,當前使用的版本號是 3 使用的鏡像是nginx:1.19.1
[root@master deploy]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment 3/3 3 3 19m nginx nginx:1.19.1 app in (nginx)
# 查看版本列表
[root@master deploy]# kubectl rollout history deploy deployment
deployment.apps/deployment
REVISION CHANGE-CAUSE
2 kubectl create --filename=deployment.yaml --record=true
3 kubectl create --filename=deployment.yaml --record=true
# 驗證是否回滾成功
[root@master deploy]# kubectl exec deployment-78ff8d9ff6-m5jsk -- nginx -V
nginx version: nginx/1.19.1
灰度發(fā)布
灰度發(fā)布其實是在滾動升級的基礎上做的钱烟,假如我們升級的時候可以暫停晰筛,那么就會存在一部分實例已經更新了,一部分還沒更新拴袭,正是金絲雀發(fā)布的場景
# 由于案例升級太快读第,執(zhí)行的命令也要走夠快才行,講兩個操作寫到一起模擬
[root@master deploy]# kubectl set image deploy deployment nginx=nginx:1.17.1 && kubectl rollout pause deploy deployment
deployment.apps/deployment image updated
deployment.apps/deployment paused
# 查看deploy已經有四個pod運行
[root@master deploy]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment 4/3 1 4 28m nginx nginx:1.17.1 app in (nginx)
# 查看rs,兩個不同版本是并存著
[root@master deploy]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
deployment-74cdbf844b 1 1 1 27m nginx nginx:1.17.1 app in (nginx),pod-template-hash=74cdbf844b
deployment-78ff8d9ff6 3 3 3 28m nginx nginx:1.19.1 app in (nginx),pod-template-hash=78ff8d9ff6
# 四個Pod正常運行
[root@master deploy]# kubectl get pods
NAME READY STATUS RESTARTS AGE
deployment-74cdbf844b-sc9pc 1/1 Running 0 58s
deployment-78ff8d9ff6-g4hx5 1/1 Running 0 20m
deployment-78ff8d9ff6-rw46x 1/1 Running 0 20m
deployment-78ff8d9ff6-ttq5j 1/1 Running 0 20m
# 查看更新動作拥刻,正在等待更新完成怜瞒,已經更新完成一個實例
[root@master deploy]# kubectl rollout status deploy deployment
Waiting for deployment "deployment" rollout to finish: 1 out of 3 new replicas have been updated...
# 恢復升級動作 在恢復之前先打開一個窗口監(jiān)控升級 kubectl rollout status deploy deployment
[root@master ~]# kubectl rollout resume deploy deployment
deployment.apps/deployment resumed
# 查看升級狀態(tài),出現successfully表示升級完成
[root@master deploy]# kubectl rollout status deploy deployment
Waiting for deployment "deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment spec update to be observed...
Waiting for deployment spec update to be observed...
Waiting for deployment "deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "deployment" rollout to finish: 1 old replicas are pending termination...
deployment "deployment" successfully rolled out
# 再次查看rs般哼,只有一個版本運行著
[root@master deploy]# kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-74cdbf844b 3 3 3 15m
deployment-78ff8d9ff6 0 0 0 16m
好了吴汪,k8s的deploy操作就記錄到這里,后面會持續(xù)發(fā)布其它的學習筆記
歡迎關注蒸眠,學習不迷路漾橙!