【无标题】

前言

上篇文章介绍了RS,RS可以保证维持一定数量的副本,多了剔除,少了自动拉起,可以方便的扩缩容,可以替换镜像更新升级,替换之后只对新的Pod有效。但是官方建议我们不应该直接使用RS来控制副本,而是使用Deployment来间接控制副本。

Deployment可以更好的解决服务编排的问题,在1.2版本开始引入,这种控制器是通过控制RS来间接控制Pod,所以具备RS的所有功能,并且对RS的更新升级做了优化

在RS中镜像更新升级只有当我们删除原来的Pod,自动拉起新的Pod时才生效,那么这个删除原来Pod的动作能不能自动运行,每次按批量的删除Pod达到一个滚动升级的效果,或者删除部分Pod停止,等待一段时间再继续达到一个灰度发布的效果。更新完后上一次的版本能否做版本保留,以便随时回退。

带着上面的问题我们看Deployment是否可以解决

Deployment

通过上面介绍,我们知道RS具备的功能还是挺多的,只是不太自动化,比如更新升级需要删除原来的Pod,这个动作是手动的,我们希望是能够自动的升级,于是Deployment就出现了,它在RS之上做个扩展,跟我们写框架一样,最开始提供出来的都是原始的api,然后在这之上做一个二次封装,以便更好的使用。

Deployment可以持有多个RS,这样我们就能随时切换版本,所以她还支持回退的功能

deploy的工作机制如下图所示

【无标题】_第1张图片

资源文件清单
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(先删除所有,再创建)与RollingUpdate(滚动 默认)
    rollingUpdate:  # 滚动更新
      maxSurge: # 可以额外多出的Pod数,可以为百分比,也可以为整数
      maxUnavaliable: # 可以忍受多少个Pod不可用,可以为百分比,也可以为整数
  selector:  # 与RS一样通过它指定该控制器管理哪些pod
    matchLabels:
    matchExpressions:
  template:  # 与Pod定义一样
    metadata:
    spec:
创建Deployment

创建一个具有三个副本的deployment

编写 deployment.yaml 内容如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  replicas: 3
  revisionHistoryLimit: 5 # 保留五个版本
  strategy:
    type: Recreate # 更新策略 先删除所有,再创建
  selector:
    matchExpressions:
    - {key: app, operator: In,values: [nginx]}
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19.1

创建deployment,观察deploy,rs,pod详情,既然Pod通过管理rs来控制Pod,那么也会创建出一个rs

# 创建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

通过上面结果显示,可以知道,创建deploy同时也会创建出一个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
镜像更新
重建更新

上面我们创建的yaml其更新方式为 Recreate–先删除所有Pod,再创建新的Pod

为了更好的观察更新过程,新打开一个窗口监控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都是新创建的。

观察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
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都停止后才创建新的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重新创建

# 删除
[root@master deploy]# kubectl delete -f deployment.yaml
deployment.apps "deployment" deleted

# 创建
[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

在更新升级之前同样的新打开一个窗口监控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再创建新的。

观察Pod的更新详情(更新之前先打开一个新窗口监控)

[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

从更新的流程来看先是创建qhmzs,然后终止gvztv,创建hc2jh,终止7wfx9,创建2mfqh,终止mrndc,这正是滚动更新的效果。

不止可以监控pod,rs也可以监控,下面是rs的监控过程,同样可以反应出滚动更新的效果,78ff8d9ff6由三个副本慢慢变为0,74cdbf844b由0慢慢变为3

[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的状态
[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也是重新创建的
[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

灰度发布

灰度发布其实是在滚动升级的基础上做的,假如我们升级的时候可以暂停,那么就会存在一部分实例已经更新了,一部分还没更新,正是金丝雀发布的场景

# 由于案例升级太快,执行的命令也要走够快才行,讲两个操作写到一起模拟
[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...
# 恢复升级动作 在恢复之前先打开一个窗口监控升级 kubectl rollout status deploy deployment
[root@master ~]# kubectl rollout resume deploy deployment
deployment.apps/deployment resumed

# 查看升级状态,出现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操作就记录到这里,后面会持续发布其它的学习笔记


欢迎关注,学习不迷路!

你可能感兴趣的:(k8s,docker,容器,kubernetes)