前言
大家好,我是秋意零。
在上一篇中,我们介绍了控制器的基本设计思想:控制器模式。通过这个 “控制器模式” 我们来看看 Deployment 是如何依靠它来实现的。
最近搞了一个扣扣群,旨在技术交流、博客互助,希望各位大佬多多支持!
获取方式:
- 1.在我主页推广区域,如图:
- 2.文章底部推广区域,如图:
👿 简介
正文开始:
- 快速上船,马上开始掌舵了(Kubernetes),距离开船还有 3s,2s,1s…
一、介绍水平扩展、水平收缩、滚动更新
Deployment 实现了非常重要的功能:Pod 的水平扩展、水平收缩、滚动更新。
举个栗子:
想象一个场景,现在我们有一个 Deployment 控制器上面部署的是一个 Web 服务,期望 Pod 的个数为:3。对外发布后,起初用户量比较少,我们的 Web 服务还能扛住,但是某一天(618、双11)为了宣传搞活动,导致用户量访问量突然暴涨,这个时候我们 3 个 Pod 部署的 Web 服务就扛不住了。
- 这个时候,我们怎么办呢?当活动结束访问量不大的时候怎么办?手动一个一个添加、删除 Pod 服务吗?这种显然是不现实的。因为,手动操作即费时间,又费人力资源,最重要的是损失了大量流量导致错过商机。
- 这种情况下就需要使用水平扩展、水平收缩(弹性机制)了。而我们控制器就包含这些功能,看看是怎么实现的吧。
- 水平扩展:我们可以设置一个资源阈值,当 CPU 或者 Mem 利用率达到 80% 或 90% 时就利用 Deployment 扩展我们 Pod 服务;
- 水平收缩:当 CPU 或者 Mem 利用率降低到 20% 或 40% 时就利用 Deployment 收缩我们 Pod 服务。
- 如果 Web 程序需要更新版本这时候怎么办?
- 滚动更新:滚动更新,在 Kubernetes 中就是替换掉 YAML 文件中的镜像版本,替换之后,控制器会重新创建一组新版本的服务,一个新版 Pod 服务创建成功之后,会删除一个旧版本的 Pod 服务,这样依次循环直到替换完毕;如果新版不稳定也可以马上回到之前旧版本,这个操作称为:“回滚”。这样的好处是对于用户是透明的,无感知的;对于管理人员来说是便捷高效的。
注意:目前这篇还不会提到监控资源的利用率自动来扩展和收缩 Pod(感兴趣可以先去了解 HorizontalPodAutoscaler(HPA)),这里介绍的是手动执行命令来扩展和收缩 Pod。
二、水平扩展/收缩的实现
知道了这三个功能水平扩展、水平收缩、滚动更新,那么我们就来看看它们是由谁实现的,是 Deployment ?
其实答案在上一篇中结尾部分,我们介绍了 Deployment 管理的 Pod ,这个 Pod 的 ownerReference(所有者)是 ReplicaSet;ReplicaSet 的 ownerReference(所有者)是 Deployment。
答案:所以,水平扩展、水平收缩、滚动更新三个功能主要依靠 ReplicaSet 来实现。不过还是需要 Deployment 管理辅助。
明白了这个原理之后,我们接着来看看 Deployment,如下:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 # 指定副本数量 selector: matchLabels: app: nginx # 选择标签为`app: nginx`的Pod进行管理 template: metadata: labels: app: nginx # Pod的标签,与 matchLabels 字段下的标签绑定 spec: containers: - name: nginx-web image: nginx # 指定应用程序的镜像 imagePullPolicy: IfNotPresent ports: - containerPort: 80 # 应用程序监听的端口号
上述 Deployment 的 YAML 文件,可以用下图表示:
- 通过这张图,我们可以看到,一个定义了
replicas: 3
的 Deployment 与 ReplicaSet 和 Pod 的关系结构,是 “层层控制” 的。 - ReplicaSet 负责通过 “控制器模式”,保证 Pod 的个数永远是 YAML 文件中所期望的个数(replicas: 3),所以 Deployment 只允许容器的 restartPolicy=Always ,这样才能保证,容器始终是 Running 状态的前提下,ReplicaSet 调整 Pod 的个数才有意义。
Deployment 同样通过 “控制器模式”,来操作 ReplicaSet 的个数和属性,从而实现 “水平扩展 / 收缩” 和 “滚动更新” 这两个编排动作。
“水平扩展 / 收缩” 的实现,Deployment 只需要修改它所控制的 ReplicaSet 的 Pod 副本个数就可以了,也就是 replicas: 3
字段。我们将上面 Deployment 的 YAML 文件创建,如下:
1.创建 Deployment:
[root@master01 yaml]# kubectl apply -f deploy-web.yaml deployment.apps/nginx-deployment created [root@master01 yaml]# [root@master01 yaml]# kubectl get -f deploy-web.yaml NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 6s
2.扩展 Pod 的副本数为:6
[root@master01 yaml]# kubectl scale deployment nginx-deployment --replicas=6 deployment.apps/nginx-deployment scaled [root@master01 yaml]# [root@master01 yaml]# kubectl get -f deploy-web.yaml NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 6/6 6 6 119s [root@master01 yaml]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-54fdb8fb59-948nn 1/1 Running 0 2s nginx-deployment-54fdb8fb59-bgqhd 1/1 Running 0 3m13s nginx-deployment-54fdb8fb59-hl9pv 1/1 Running 0 2s nginx-deployment-54fdb8fb59-ptwz2 1/1 Running 0 3m13s nginx-deployment-54fdb8fb59-s9rkp 1/1 Running 0 2s nginx-deployment-54fdb8fb59-wf4mh 1/1 Running 0 2s
3.收缩 Pod 的副本数为:2
[root@master01 yaml]# kubectl scale deployment nginx-deployment --replicas=2 deployment.apps/nginx-deployment scaled [root@master01 yaml]# [root@master01 yaml]# kubectl get -f deploy-web.yaml NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 2/2 2 2 2m46s [root@master01 yaml]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-54fdb8fb59-bgqhd 1/1 Running 0 2m59s nginx-deployment-54fdb8fb59-ptwz2 1/1 Running 0 2m59s [root@master01 yaml]#
三、滚动更新
首先查看 Deployment 所控制的 ReplicaSet
这个 ReplicaSet 的名字,是由 Deployment 的名字和一个随机字符串共同组成。这个随机字符串叫作 pod-template-hash,在我们这个例子里就是:54fdb8fb59。ReplicaSet 会把这个随机字符串加在它所控制的所有 Pod 的标签里,从而保证这些 Pod 不会与集群里的其他 Pod 混淆。
[root@master01 yaml]# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-54fdb8fb59 2 2 2 65s
现在,修改了 Deployment 的 Pod 模板,“滚动更新” 就会被自动触发。
我们可以使用 kubectl edit 指令编辑 Etcd 里的 API 对象。 kubectl edit 指令,会帮你直接打开 nginx-deployment 的 API 对象。然后,你就可以修改这里的 Pod 模板部分了。
- kubectl edit 并不神秘,它不过是把 API 对象的内容下载到了本地文件,让你修改完成后再提交上去。