3.2 控制器之Deployment


Deployment是一種高階控制器資源,在部署時,Deployment創建並管理ReplicaSet,由ReplicaSet創建管理pod。目的方便應用升級時,Deployment便於通過ReplicaSet管理一組pod進行應用升級。

1、Deployment的創建

在這裏插入圖片描述
與pod、replicaset一樣,deployment在k8s中也是一種資源,可以通過yaml的聲明方式聲明一套deployment的定義,然後通過kubectl create創建出deployment。下面以demo_deployment.yaml爲例

apiVersion: apps/v1beta1  		#版本
kind: Deployment   				#資源類型
metadata: 						#deployment的元數據
  name: mydeployment  			#Deployment的資源名字
spec:   						#Deployment描述信息
  minReadySeconds: 10   		#pod創建延遲至少10s然後才ready狀態
  replicas: 3  					#創建pod的副本數
  template:    					#pod的模板信息
    metadata:   				#pod的元數據
      labels:  					#定義pod標籤
        app: mynginx-pod   		#pod的標籤
    spec:     					#pod中容器描述信息
      containers:  				#定義容器
      - name: mynginx  			#容器的名字
        image: mynginx:v0.2   	#容器中鏡像
        ports:  				#定義容器暴露的端口
        - containerPort: 80

根據yaml創建deployment

[root@k8s-master01 deployment_work]# ls
demo_deployment.yaml
#創建deployment
[root@k8s-master01 deployment_work]# kubectl create -f demo_deployment.yaml --record
deployment.apps/mydeployment created

#查詢deployment
[root@k8s-master01 deployment_work]# kubectl get deployment
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
mydeployment   3/3     3            3           10s

#查詢replicaset
[root@k8s-master01 deployment_work]# kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
mydeployment-7fd7865495   3         3         3       17s

#查詢pod
[root@k8s-master01 deployment_work]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
mydeployment-7fd7865495-57jnx   1/1     Running   0          29s
mydeployment-7fd7865495-8vfdl   1/1     Running   0          29s
mydeployment-7fd7865495-c7j7c   1/1     Running   0          29s

由此可見,deployment顯示創建了一個名字爲mydeployment-7fd7865495的replicaset,由replicaset創建了3個pod。–record能顯示變更歷史原因,方便查看每個版本變更的原因。

2、deployment管理應用升級

在這裏插入圖片描述
當應用需要升級時,只需要修改deployment中的pod模板就可以控制pod中應用從舊版本升級到新版本中。deployment升級時,通過新建一個ReplicaSet,然後通過ReplicaSet重建新版本應用的pod,然後刪除舊版本的pod,但是管理舊版本pod的ReplicaSet保留着,以防後續回滾用 deployment在升級pod應用過程 中採用兩種升級策略:

  • Recreate : 刪除舊版本的pod後纔會創建新版本的pod,會導致應用出現短暫的停機狀態,如果應用不支持多版本,可以選擇該策略。
  • RollingUpdate : 刪除舊版本的pod時,同時創建新版本的pod,應用平滑的升級,使應用在升級過程中也保持可用,但需要支持應用多版本,否則會導致數據錯亂。Deployment的默認升級策略。
    下面通過示例演示滾動升級,首先通過deployment部署mynginx:v0.2版本的應用,然後滾動升級成mynginx:v0.3版本,首先查看v0.2版本應用
#查看部署的pod
[root@k8s-master01 deployment_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-6c5cf4c646-8knrf   1/1     Running   0          4m49s   10.244.2.75   k8s-node02   <none>           <none>
mydeployment-6c5cf4c646-jp84k   1/1     Running   0          4m49s   10.244.1.73   k8s-node01   <none>           <none>
mydeployment-6c5cf4c646-mwt2d   1/1     Running   0          4m49s   10.244.2.76   k8s-node02   <none>           <none>

#訪問pod中的應用,輸出當前版本爲2
[root@k8s-master01 deployment_work]# curl 10.244.2.75
hello lzj, this is version 2

下面升級鏡像

kubectl set image deployment mydeployment mynginx=mynginx:v0.3

監控pod滾動更新狀態如下:

[root@k8s-master01 deployment_work]# kubectl get pod -w
NAME                            READY   STATUS    RESTARTS   AGE
mydeployment-6c5cf4c646-8knrf   1/1     Running   0          18m
mydeployment-6c5cf4c646-jp84k   1/1     Running   0          18m
mydeployment-6c5cf4c646-mwt2d   1/1     Running   0          18m
mydeployment-797fcb456f-6x9xm   1/1     Running   0          16s
mydeployment-6c5cf4c646-8knrf   1/1     Terminating   0          18m
mydeployment-797fcb456f-dd26l   0/1     Pending       0          0s
mydeployment-797fcb456f-dd26l   0/1     Pending       0          0s
mydeployment-797fcb456f-dd26l   0/1     ContainerCreating   0          0s
mydeployment-6c5cf4c646-8knrf   0/1     Terminating         0          18m
mydeployment-797fcb456f-dd26l   1/1     Running             0          1s
mydeployment-6c5cf4c646-8knrf   0/1     Terminating         0          18m
mydeployment-6c5cf4c646-8knrf   0/1     Terminating         0          18m
mydeployment-6c5cf4c646-mwt2d   1/1     Terminating         0          18m
mydeployment-797fcb456f-kl2m4   0/1     Pending             0          0s
mydeployment-797fcb456f-kl2m4   0/1     Pending             0          0s
mydeployment-797fcb456f-kl2m4   0/1     ContainerCreating   0          0s
mydeployment-6c5cf4c646-mwt2d   0/1     Terminating         0          18m
mydeployment-797fcb456f-kl2m4   1/1     Running             0          2s
mydeployment-6c5cf4c646-mwt2d   0/1     Terminating         0          18m
mydeployment-6c5cf4c646-mwt2d   0/1     Terminating         0          18m
mydeployment-6c5cf4c646-jp84k   1/1     Terminating         0          18m
mydeployment-6c5cf4c646-jp84k   0/1     Terminating         0          18m
mydeployment-6c5cf4c646-jp84k   0/1     Terminating         0          19m
mydeployment-6c5cf4c646-jp84k   0/1     Terminating         0          19m

[root@k8s-master01 deployment_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-797fcb456f-6x9xm   1/1     Running   0          5m14s   10.244.1.74   k8s-node01   <none>           <none>
mydeployment-797fcb456f-dd26l   1/1     Running   0          4m52s   10.244.2.77   k8s-node02   <none>           <none>
mydeployment-797fcb456f-kl2m4   1/1     Running   0          4m31s   10.244.1.75   k8s-node01   <none>           <none>

#請求pod,發現pod返回內容當前版本爲3
[root@k8s-master01 deployment_work]# curl 10.244.1.74
hello lzj, this is version 3

發現pod是先創建一個v0.3版本的pod,然後停止一個v0.2版本的pod,直至滾動結束。從更新的狀態中可以看出,deployment滾動更新時,是通過創建了另外一個ReplicaSet,然後通過ReplicaSet創建了3個v0.3版本的pod。最後把原來的ReplicaSet下的3個v0.2版本的pod刪除掉。

注意:如果修改了deployment中的pod模板,會立即觸發滾動更新,如果沒修改pod模板,只是修改了deployment的一些屬性,不會觸發滾動更新的。

3、deployment管理應用回滾

當deployment部署應用升級後,如果發現當前版本有bug,需要回滾到上一版本,則可以通過deployment的rollout undo進行回滾。回滾的原理就是根據舊版本的ReplicaSet重新建舊版本的Pod應用,然後刪除新版本的pod。如下所示,當前應用鏡像版本爲mynginx:v0.3,需要回滾到上一應用版本

[root@k8s-master01 dockerfile_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-797fcb456f-2xj82   1/1     Running   0          82s   10.244.1.80   k8s-node01   <none>           <none>
mydeployment-797fcb456f-8kczn   1/1     Running   0          60s   10.244.2.81   k8s-node02   <none>           <none>
mydeployment-797fcb456f-c7z25   1/1     Running   0          39s   10.244.1.81   k8s-node01   <none>           <none>

#訪問pod中的當前應用,輸出內容爲v0.3版本的應用
[root@k8s-master01 dockerfile_work]# curl 10.244.1.80
hello lzj, this is version 3

#回滾到上一版本應用
[root@k8s-master01 dockerfile_work]# kubectl rollout undo deployment mydeployment
deployment.extensions/mydeployment rolled back

[root@k8s-master01 dockerfile_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-6c5cf4c646-4nbfv   1/1     Running   0          77s   10.244.1.82   k8s-node01   <none>           <none>
mydeployment-6c5cf4c646-5nj5j   1/1     Running   0          55s   10.244.2.83   k8s-node02   <none>           <none>
mydeployment-6c5cf4c646-88sjf   1/1     Running   0          99s   10.244.2.82   k8s-node02   <none>           <none>

#回滾結束後,重新訪問pod中的應用,發現版本已經回退到v0.2版本
[root@k8s-master01 dockerfile_work]# curl 10.244.1.82
hello lzj, this is version 2

注意:執行上述操作後,應用已經回滾到了v0.2版本,如果按上述步驟再次執行就又會回到v0.3版本,可以通過指定回滾到的版本進行回滾。

#查詢deployment的滾動歷史,創建deployment時添加了--record,所以下面CHANGE-CAUSE纔會有變更步驟的記錄原因
[root@k8s-master01 dockerfile_work]# kubectl rollout history deployment mydeployment
deployment.extensions/mydeployment 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=demo_deployment.yaml --record=true
3         kubectl create --filename=demo_deployment.yaml --record=true
4         kubectl create --filename=demo_deployment.yaml --record=true

#其中REVISION代表每次滾動時的版本編號,回滾時可以指定版本編號回滾到指定的版本。下面回滾到最初的應用版本。
[root@k8s-master01 dockerfile_work]# kubectl rollout undo deployment mydeployment --to-revision=1
deployment.extensions/mydeployment rolled back

[root@k8s-master01 dockerfile_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-7fd7865495-7kdjl   1/1     Running   0          2m37s   10.244.1.83   k8s-node01   <none>           <none>
mydeployment-7fd7865495-m77pm   1/1     Running   0          2m15s   10.244.2.84   k8s-node02   <none>           <none>
mydeployment-7fd7865495-tr2mm   1/1     Running   0          114s    10.244.1.84   k8s-node01   <none>           <none>

#回滾到最初的版本後,訪問pod中的應用,發現輸出了最初的NGINX內容
[root@k8s-master01 dockerfile_work]# curl 10.244.1.83
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

4、滾動失敗,deployment自動回滾

在應用版本升級時,如果版本有bug,應控制deployment自動回滾到前一個版本。實現該功能需藉助minReadySeconds和探針實現。
minReadySeconds用來指定沒有任何容器crash的Pod並被認爲是可用狀態的最小秒數。默認是0(Pod在ready後就會被認爲是可用狀態)。如果minReadySeconds設置10s,可以使用minReadySeconds可以讓deployment在第一個pod就緒之後繼續等待10s,如pod沒有問題,繼續升級下一個pod繼續等待10s,如此類推。一般設置minReadySeconds時間等於應用啓動後可以正常接受流量的長度。在pod中設置就緒探針,如果在minReadySeconds時間內,探針失敗了,deployment進行自動回滾。下面通過demo_deployment.yaml實例演示

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mydeployment
spec:
  minReadySeconds: 10
  replicas: 3
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      name: myreplicaset
      labels:
        app: myreplicaset
    spec:
      containers:
      - name: mynginx
        image: mynginx:v0.3
        ports:
        - containerPort: 80

其中可以通過定義deployment的屬性maxSurge與maxUnavailable控制滾動升級速率。
maxSurge:決定了deployment配置的副本數之外,最多允許超出的pod實例數量,比如副本數設置3,maxSurge設置的1,在deployment的滾動升級之間,最多允許存在4個 pod實例數量;
maxUnavailable:決定了deployment滾動升級之間,相對於期望副本數量最多有多少個pod實例數量處於不可用狀態。比如副本設置爲3,maxUnavailable設置爲1,滾動升級時最多有2個pod實例處於可用狀態。

#創建mydeployment
[root@k8s-master01 deployment_work]# kubectl apply -f demo_deployment.yaml --record
deployment.apps/mydeployment created

#查詢創建出來的pod
[root@k8s-master01 dockerfile_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-768bc94c96-gtf9w   1/1     Running   0          15s   10.244.1.92   k8s-node01   <none>           <none>
mydeployment-768bc94c96-mphqp   1/1     Running   0          15s   10.244.2.93   k8s-node02   <none>           <none>
mydeployment-768bc94c96-s8npx   1/1     Running   0          15s   10.244.1.93   k8s-node01   <none>           <none>

#訪問pod中應用,版本爲2
[root@k8s-master01 dockerfile_work]# curl 10.244.1.92
hello lzj, this is version 2

下面修改yaml中鏡像併爲pod添加探針

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mydeployment
spec:
  minReadySeconds: 10
  replicas: 3
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      name: myreplicaset
      labels:
        app: myreplicaset
    spec:
      containers:
      - name: mynginx
        image: mynginx:v0.3   	#鏡像修改爲v0.3版本
        readinessProbe:  		#增加就緒探針
          periodSeconds: 1
          httpGet:
            path: /test.html
            port: 8080
        ports:
        - containerPort: 80

容器中暴漏的是80端口,而探針探測的時8080端口,探針必定時失敗的,下面執行deployment的滾動升級

#滾動升級mydeployment
[root@k8s-master01 deployment_work]# kubectl apply -f demo_deployment.yaml --record
deployment.apps/mydeployment configured

#查看升級後的pod,發現滾動失敗,創建第一個pod時,狀態爲就緒,因此deployment自動回滾,回到v0.2版本
[root@k8s-master01 dockerfile_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
mydeployment-5bcf884b6d-4ldjx   0/1     Running   0          11m   10.244.2.94   k8s-node02   <none>           <none>
mydeployment-768bc94c96-gtf9w   1/1     Running   0          13m   10.244.1.92   k8s-node01   <none>           <none>
mydeployment-768bc94c96-mphqp   1/1     Running   0          13m   10.244.2.93   k8s-node02   <none>           <none>
mydeployment-768bc94c96-s8npx   1/1     Running   0          13m   10.244.1.93   k8s-node01   <none>           <none>

#訪問pod中應用,發現應用沒有升級到v0.3版本,依然是v0.2版本
[root@k8s-master01 dockerfile_work]# curl 10.244.1.92
hello lzj, this is version 2

注意

1. kubectl create 與 kubectl apply區別
kubectl create只能執行一次,不能重複執行;
kubectl apply可以重複執行,是增量的執行,yaml中增加了什麼東西,apply執行時只會創建增加的資源。

2. deployment相關操作命令

kubectl rollout status deployment mydeployment #查看deployment部署狀態
kubectl set image deployment mydeployment mynginx=mynginx:v0.2 #版本升級爲v0.2
kubectl rollout undo deployment mydeployment #回滾到上一級
kubectl rollout undo deployment mydeployment  --to-revision=2 #回滾到指定的步驟
kubectl rollout pause deployment mydeployment #暫停升級,可以多次修改deployment後再恢復執行
kubectl rollout resume deployment mydeployment #恢復升級

參考《kubenetes in Action》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章