kubernetes控制器-Deployment
# kubernetes控制器-Deployment
学习Deployment之前,首先要清楚两个概念:
- 无状态应用:任意一个Web请求端提出请求时,请求本身包含了响应端为响应这一请求所需的全部信息(认证信息等)。
- 有状态应用:Web请求端的请求必须被提交到保存有其相关状态信息(比如session)的服务器上,否则这些请求可能无法被理解,这也就意味着在此模式下服务器端无法对用户请求进行自由调度。
分辨有无状态应用的关键点就在数据的存储位置,存储在客户端的就是无状态应用,存储在服务端的就是有状态应用。
而Deployment管理的就是无状态应用。kubernetes中也有针对有状态应用的控制器Statefulset,但本篇文章不进行讲解。
# 1. Deployment的工作原理
# 1.1. 水平扩缩
了解Deployment的工作原理之前,我们先新建一个Deployment,新建 Deployment.yml
如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx-deployment
replicas: 3
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx-deployment
image: nginx:latest
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
下面我们画一张图分析一下Deployment的结构:
而从这个Deployment,我们能看出来,控制器的结构如图所示,由上半部分的控制器定义(包括期望状态),加上下半部分的被控制对象的模板(template)组成的。
创建这个Deployment,并查看Deployment的状态:
kubectl apply -f Deployment.yml
kubectl get deployments.apps
2
- READY:当前已经可用的Pod的个数/用户期望的Pod副本个数(spec.replicas的值)。
- UP-TO-DATE:当前处于最新版本的Pod的个数,所谓最新版本指的是Pod的Spec部分与Deployment里Pod模板里定义的完全一致。
- AVAILABLE:当前已经可用的Pod的个数,即:既是Running状态,又是最新版本,并且已经处于Ready(健康检查正确)状态的Pod的个数。
而在所有API对象的Metadata里,都有一个字段叫作ownerReference,用于保存当前这个API对象的拥有者(Owner)的信息。
而Deployment实际操纵的是ReplicaSet。在创建完Deployment之后,Namespace中多出了一个ReplicaSet,这时,我们查看ReplicaSet的yaml中的ownerReference,就能找到依据:
kubectl get replicasets.apps -o yaml | grep ownerReference -A 10
Pod的的拥有者(Owner)是ReplicaSet,而ReplicaSet的拥有者(Owner)是Deployment。而三者之间的关系,实际上是一种“层层控制”的关系。
而实现水平扩缩就简单了,Deployment通过控制ReplicaSet的副本数就能实现。
# 1.2. 滚动更新
我们也是先执行一次滚动更新,需要注意的是只有spec.template(Pod模板)更新时才会触发Deployment的更新。如更改CPU,镜像等等。
执行滚动更新有两种方式,可以更改yaml文件后使用 kubectl apply -f
进行更新,也可以使用 kubectl edit
进行编辑Deployment来更新。我们这里把nginx的版本号由 latest
改为 1.25.1
:
spec:
containers:
- name: nginx-deployment
image: nginx:1.25.1
2
3
4
使用 kubectl apply -f
进行更新:
kubectl apply -f Deployment.yml
查看Deployment的Events来观察滚动更新的过程:
kubectl describe deployments.apps nginx-deployment
- Deployment创建一个新ReplicaSet、这个ReplicaSet叫
nginx-deployment-cb699c677
,并且这个新ReplicaSet的初始Pod副本数是0。 - Deployment将旧ReplicaSet
nginx-deployment-7c864f7c
由三个收缩为2个。并把新ReplicaSetnginx-deployment-cb699c677
扩展为1个。 - 新ReplicaSet和旧ReplicaSet分别进行水平扩容和水平收缩,直到新ReplicaSet的副本数为3,旧ReplicaSet的副本数为0,就完成了这次滚动更新。
查看集群内ReplicaSet的最终状态,也正如我们预想的那样,旧ReplicaSet已经水平收缩为0:
像这样,将一个集群中正在运行的多个Pod版本,交替地逐一升级的过程,就是“滚动更新”。
# 2. Deployment的更新
可以使用 edit
命令直接编辑Deployment进行更新:
kubectl edit deployments.apps/nginx-deployment
使用 rollout status
查看更新过程:
kubectl rollout status deployments.apps/nginx-deployment
当进行Deployment新建或者更新后,Deployment都会把 pod-template-hash
标签添加到 每个由Deployment控制的ReplicaSet上,确保每个ReplicaSet的唯一性。不要更改此标签
# 3. Deployment的回滚
当更新了版本不稳定或配置不合理时,可以对其进行回滚操作。默认情况下,Deployment 的所有上线记录都保留在系统中,以便可以随时回滚。
# 3.1. 查看历史版本
使用 rollout history
查看更新历史:
kubectl rollout history deployment/nginx-deployment
其中,CHANGE-CAUSE
的内容是从 Deployment 的 kubernetes.io/change-cause
注解复制过来的,可以通过以下方式设置:
- 使用
kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to latest"
为 Deployment 添加注解。 - 手动编辑Deployment文件进行更新。
查看更新历史的详细信息:
kubectl rollout history deployment/nginx-deployment --revision=2
# 3.2. 回滚历史版本
使用 rollout undo
从 revision 2
回滚到 revision 1
:
kubectl rollout undo deployment/nginx-deployment
也可以手动指定 revision
:
kubectl rollout undo deployment/nginx-deployment --to-revision=2
# 3.3. 修改历史版本数量限制
默认情况下,revision
保留10个旧的ReplicaSet,其余的将在后台进行垃圾回收,可以在 .spec.revisionHistoryLimit
设置保留 ReplicaSet 的个数。当设置为0时,不保留历史记录,也就意味着无法进行历史版本回滚了。
# 4. Deployment的扩缩容&暂停和恢复
# 4.1. Deployment的扩缩容
使用 scale
进行Deployment的扩容,副本数为5:
kubectl scale deployment/nginx-deployment --replicas=5
# 4.2. Deployment的暂停和恢复
每次我们使用 edit
或者 set image
指令等等进行Deployment更新时,都会生成一个新的ReplicaSet对象,而通过暂停可以使我们对Deployment的多次更新操作的最终结果只生成一个ReplicaSet:
kubectl rollout pause deployment/nginx-deployment
暂停后可以任意修改,最后恢复Deployment:
kubectl rollout resume deployment/nginx-deployment
发现只有一个新的ReplicaSet生成,也就是通过暂停和恢复Deployment,只触发了一次“滚动更新”。
# 5. 控制滚动更新速率
在Deployment的滚动升级期间,有两个属性会决定一次替换多少个pod。可以通过Deployment的 strategy
字段下 rollingUpdate
的子属性来配置:
spec:
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
2
3
4
5
6
种类 | 说明 |
---|---|
maxSurge | 决定了Deployment在滚动更新的过程中最多允许超出的Pod实例的数量。默认值为25%,所以Pod实例最多可以比replicas数量多25%。如果replicas被设置为4,那么在滚动升级期间,不会运行超过5个Pod。值也可以设置为数字。 |
maxUnavailable | 决定了Deployment在滚动更新的过程中最多允许有多少Pod处于不可用状态。默认值也是25%,所以可用 pod 实例的数量不能低于期望副本数的75%,百分数转换成绝对值时这个数字会四舍五入。如果replicas被设置为4,那么在滚动升级期间,只能有一个 pod 处于不可用状态。值也可以设置为数字。 |
# 6. 阻止错误版本的滚动更新
.spec.minReadySeconds
属性指定新创建的pod至少要成功运行多久之后,才能将其视为可用Pod(在容器的健康检查通过之后开始计算),默认值为0。
minReadySeconds
的主要功能是避免部署出错版本的应用,如果一个新的pod运行出错,并且在 minReadySeconds
时间内它的就绪探针出现了失败,那么新版本的滚动更新将被阻止。
参考文章及书籍: