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》

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