1. 首页
  2. Kubernetes

Kubernetes对象之Deployment

简介

Deployment 提供了声明式的方法,对 PodReplicaSet 进行更新,我们只需要在 Deployment 对象中设置好预期的状态,然后Deployment 就能够控制将实际的状态保持与预期状态一致。使用 Deployment 的典型场景,有如下几个:

  • 创建 ReplicaSet,进而通过 ReplicaSet 启动 Pod,Deployment 会检查启动状态是否成功
  • 滚动升级或回滚应用
  • 应用扩容或缩容
  • 暂停(比如修改Pod模板)及恢复 Deployment 的运行
  • 根据Deployment的运行状态,可以判断对应的应用是否hang住
  • 清除掉不再使用的 ReplicaSet

注意: 您不该手动管理由 Deployment 创建的 ReplicaSet,否则您就篡越了 Deployment controller 的职责!

创建 Deployment

在工作中我一般是直接创建资源配置清单 yaml 文件来进行创建。Deployment 定义和 Pod 定义区别不大。下面定义一个 replicas=3 来启动三个 nginx Pod。

$ vim nginx-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8.1
        ports:
        - name: http
          containerPort: 80

你可以使用 kubectl create 或 kubectl apply 去建立 nginx deployment

root@k8s-master-opsbj:~/manifests # kubectl apply -f nginx-deploy.yaml --record
deployment.apps/nginx-deploy created

将 kubectl的 --record 的 flag 设置为 true 可以在 annotation 中记录当前命令创建或者升级了该资源。这在未来会很有用,例如,查看在每个Deployment revision 中执行了哪些命令。

通过 get可以看到目前 nginx deployment 的部署情況

root@k8s-master-opsbj:~/manifests # kubectl get deploy nginx-deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   3/3     3            3           49s

查看自动产生的 Replica Set

root@k8s-master-opsbj:~/manifests # kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-5b59f7c84f   3         3         3       7m26s

查看 Pod

root@k8s-master-opsbj:~/manifests # kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-5b59f7c84f-8cgtz   1/1     Running   0          7m45s
nginx-deploy-5b59f7c84f-gk642   1/1     Running   0          7m45s
nginx-deploy-5b59f7c84f-jzkps   1/1     Running   0          7m45s

滚动升级 (Rolling Update)

为了让 Kubernetes 能够按照我们所想的方式来进行滚动升级,首先我们必须在刚刚的 yaml 文件内的 spec 加入相关升级策略设定。

.spec.strategy 指定新的 Pod 替换旧的 Pod 的策略。 .spec.strategy.type 可以是 ”Recreate” 或者是 “RollingUpdate”。”RollingUpdate” 是默认值。

Recreate Deployment

.spec.strategy.type==Recreate时,在创建出新的 Pod 之前会先杀掉所有已存在的 Pod。简单理解就是,删除一个,创建一个。

Rolling Update Deployment

.spec.strategy.type==RollingUpdate 时,Deployment 使用 rolling update 的方式更新 Pod 。您可以指定 maxUnavailable 和 maxSurge 来控制 rolling update 节奏。

Max Unavailable

.spec.strategy.rollingUpdate.maxUnavailable 是可选配置项,用来指定在升级过程中不可用 Pod 的最大数量。该值可以是一个绝对值(例如5),也可以是期望 Pod 数量的百分比(例如10%)。通过计算百分比的绝对值向下取整。如果 .spec.strategy.rollingUpdate.maxSurge 为 0 时,这个值不可以为0。默认值是1。

例如,该值设置成 30%,启动 rolling update 后旧的 ReplicatSet 将会立即缩容到期望的 Pod 数量的 70%。新的 Pod ready 后,随着新的 ReplicaSet 的扩容,旧的 ReplicaSet 会进一步缩容,确保在升级的所有时刻可以用的 Pod 数量至少是期望 Pod 数量的70%。

Max Surge

.spec.strategy.rollingUpdate.maxSurge 是可选配置项,用来指定可以超过期望的 Pod 数量的最大个数。该值可以是一个绝对值(例如5)或者是期望的Pod数量的百分比(例如10%)。当 MaxUnavailable 为 0 时该值不可以为0。通过百分比计算的绝对值向上取整。默认值是1。

例如,该值设置成 30%,启动 rolling update 后新的 ReplicatSet 将会立即扩容,新老 Pod 的总数不能超过期望的 Pod 数量的 130%。旧的 Pod 被杀掉后,新的 ReplicaSet 将继续扩容,旧的 ReplicaSet 会进一步缩容,确保在升级的所有时刻所有的 Pod 数量和不会超过期望 Pod 数量的130%。

minReadySeconds

.spec.minReadySeconds 是可选配置项,用来指定容器内应用程序的启动时间,kubernetes 会等待设定的时间后才继续进行升级流程。如果没有此指令的话,kubernetes 会认为该容器一启动就可以提供服务。默认值是0。

注意:若未设定此指令,在某些极端情况下可能会造成服务无法正常运作(新诞生的pod尚未进入可服务阶段

添加滚动升级配置后的 nginx-deploy.yaml 如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8.1
        ports:
        - name: http
          containerPort: 80

apply 新的 nginx-deploy.yaml

root@k8s-master-opsbj:~/manifests # kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx-deploy configured

升级方式

除了修改 yaml 使用 apply 进行更新以外,还有其它方法可以升级对象,接下来介绍三种方式进行滚动升级(以升级 docker image 为例)

set image

语法格式:

kubectl set image deployment <deployment> <container>=<image> --record

举例演示:上面 nginx-deploy.yaml 中 nginx 的版本是 1.8.1 我们升级到 1.11.5

root@k8s-master-opsbj:~/manifests # kubectl set image deploy nginx-deploy nginx=nginx:1.11.5 --record
deployment.extensions/nginx-deploy image updated

检查 nginx 镜像是否更新了

root@k8s-master-opsbj:~/manifests # kubectl get deployments -o wide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-deploy   2/3     2            2           31m   nginx        nginx:1.11.5   app=nginx
kubectl set image 示例
kubectl set image 示例

replace

修改 nginx-deploy.yaml 中的 image 版本。上面我们用 set iamge 的方式修改版本到 1.11.5,为了演示出效果,这次我们在修改镜像版本为 1.10.3;

spec:
  containers:
  - name: nginx
    image: nginx:1.10.3
    ports:
    - name: http
      containerPort: 80

利用 replace 来进行升级而不是 apply

语法格式:

kubectl replace -f <yaml>

举例演示:

root@k8s-master-opsbj:~/manifests # kubectl replace -f nginx-deploy.yaml
deployment.apps/nginx-deploy replaced

检查 nginx 镜像是否更新了

root@k8s-master-opsbj:~/manifests # kubectl get deployments -o wide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-deploy   2/3     2            2           37m   nginx        nginx:1.10.3   app=nginx

edit

语法格式:

kubectl edit deployment <deployment> --record

edit 指令会直接打开编辑器的窗口,让我们来修改 Deployment 中设定的值

root@k8s-master-opsbj:~/manifests # kubectl edit deployment nginx-deploy --record

这次我们修改为 1.13.2 然后保存退出,然后检查 nginx 镜像是否更新

kubect edit 升级镜像示例
kubect edit 升级镜像示例

查询升级状态

root@k8s-master-opsbj:~/manifests # kubectl rollout status deploy nginx-deploy
deployment "nginx-deploy" successfully rolled out

暂停滚动升级

$ kubectl rollout pause deployment <deployment>

继续滚动升级

$ kubectl rollout resume deployment <deployment>

回滚

当升级完成后,如果其他同事发现此次升级造成了服务不稳定的情况,但他们不清除之前我们是在哪个版本。在这种情况下,我们可以利用 rollback 回退到之前的版本。

在之前的操作中,我们在每条指令后面加了一个 –record 的参数,这个参数主要告诉 kubernetes 记录我们此次执行的命令,如此一来我们就能更加清楚不同版本之间我们做了哪些操作。

root@k8s-master-opsbj:~/manifests # kubectl apply -f nginx-deploy.yaml --record
deployment.apps/nginx-deploy created

现在模拟更新镜像到 1.10.3

root@k8s-master-opsbj:~/manifests # kubectl set image deploy nginx-deploy nginx=nginx:1.10.3 --record
deployment.extensions/nginx-deploy image updated

还可以通过查看 ReplicaSet(RS) 来查看 Deployment 管理的 RS 版本

root@k8s-master-opsbj:~/manifests # kubectl get rs -o wide
NAME                      DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES         SELECTOR
nginx-deploy-5b59f7c84f   0         0         0       5m9s    nginx        nginx:1.8.1    app=nginx,pod-template-hash=5b59f7c84f
nginx-deploy-7896c7dbf4   3         3         3       3m17s   nginx        nginx:1.10.3   app=nginx,pod-template-hash=7896c7dbf4

查看历史操作

root@k8s-master-opsbj:~/manifests # kubectl rollout history deploy nginx-deploy
deployment.extensions/nginx-deploy
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=nginx-deploy.yaml --record=true
2         kubectl set image deploy nginx-deploy nginx=nginx:1.10.3 --record=true

要执行回滚操作,需要使用 kubectl rollout undo 子命令。

语法格式:

# 回滚到上一个版本
kubectl rollout undo deployment <deployment>

# 回滚到指定的版本
kubectl rollout undo deployment <deployment> --to-revision=<revision>

举例演示:回滚到上一个版本

root@k8s-master-opsbj:~/manifests # kubectl rollout undo deploy nginx-deploy
deployment.extensions/nginx-deploy rolled back

检查 nginx 是否回滚到之前的版本

kubectl回滚操作验证
kubectl回滚操作验证

还可以设置 Deployment 中的 .spec.revisionHistoryLimit 项来指定保留多少旧的 ReplicaSet。 余下的将在后台被当作垃圾收集。默认的,所有的 revision 历史就都会被保留。在未来的版本中,将会更改为2。

注意: 将该值设置为0,将导致所有的 Deployment 历史记录都会被清除,该 Deployment 就无法再回退了。

添加 revisionHistoryLimit 参数后的 nginx-deploy.yaml 如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  revisionHistoryLimit: 10
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8.1
        ports:
        - name: http
          containerPort: 80

删除 Deployment

删除操作比较简单如下:

# 语法格式
$ kubectl delete -f <yaml>
或者
$ kubectl delete <deployment> deployment_name

# 示例
$ kubectl delete -f nginx-deploy.yaml 
deployment "nginx-deploy" deleted 

或者

$ kubectl delete deployment nginx-deploy

参考资料

https://k8smeetup.github.io/docs/concepts/workloads/controllers/deployment/

如果觉得文章不错,不妨给个『打赏』写作不易,各位的支持,能激发和鼓励我更大的写作热情。谢谢

原创文章,作者:恩志,如若转载,请注明出处:https://www.xbzdr.com/681.html

恩志进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注

评论列表(4条)

  • 腾讯云
    腾讯云 2019年6月19日 11:05

    交换链接吗

    • 恩志
      恩志 回复 腾讯云 2019年6月23日 08:12

      可以,你先加我友链,博客名称:闲不住的人 博客地址:https://www.xbzdr.com 然后把你的博客地址留下

    • 腾讯云
      腾讯云 回复 恩志 2019年6月23日 18:33

      已添加贵站链接
      我站:https://www.laomulu.com/ (腾讯云)

    • 恩志
      恩志 回复 腾讯云 2019年6月25日 15:16

      友链已加

联系我们

在线咨询:点击这里给我发消息

邮件:510749025@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code