一、导读
所有的 Deployment 对象都是由 Kubernetes 集群中的 DeploymentController 进行管理,DeploymentController 会在启动时通过 Informer 监听三种不同资源的通知,Pod、ReplicaSet 和 Deployment,这三种资源的变动都会触发 DeploymentController 中的回调。
不同的事件最终都会在被过滤后进入控制器持有的队列,等待工作进程的消费,下面的这些事件都会触发:
- Deployment 的同步;
- Deployment 的变动;
- Deployment 相关的 ReplicaSet 变动;
- Deployment 相关的 Pod 数量为 0 时,Pod 的删除事件;
二、Deployment的控制流程
2.1.Deployment 的yaml文件定义:
Deployment 定义的 template 字段,在 Kubernetes 项目中有一个专有的名字,叫作 PodTemplate即Pod 模板。后面提到的大多数控制器,都会使用 PodTemplate 来统一定义它所要管理的 Pod。 Deployment 这样的一个控制器,实际上都是由上半部分的控制器定义,包括期望状态,加上下半部分的被控制对象的模板组成的。nginx-deployment 所直接控制的,就是 Pod 对象么?不是,而是ReplicaSet。
2.2.控制流程:
(1)Deployment 控制器从 Etcd 中获取到所有携带了“app: nginx”标签的 Pod,然后统计它们的数量,这就是实际状态;
(2)Deployment 对象的 Replicas 字段的值就是期望状态;
(3)Deployment 控制器将两个状态做比较,然后根据比较结果,确定是创建 Pod,还是删除已有的 Pod。
2.3.Deployment控制器与ReplicaSet控制器关系:
Deployment控制器建立在ReplicaSet控制器之上,管理多个ReplicaSet,每次更新镜像版本,都会生成一个新的ReplicaSet,把旧的ReplicaSet替换掉,多个ReplicaSet同时存在,但只运行一个ReplicaSet。
ReplicaSet V1版本控制了三个Pod,ReplicaSet V1版本删除一个Pod,会在ReplicaSet V2版本新建一个Pod,以此类推,直到ReplicaSet V2版本完全替换完。如果ReplicaSet V2版本更新上去存在问题,还可以回滚,Deployment建立在ReplicaSet之上,多个ReplicaSet组成一个Deployment,但只有一个ReplicaSet处于活跃状态。
2.4.Deployment资源清单:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment-1
labels:
env: uat
spec:
replicas: 3
minReadySeconds: 10 # 更新场景,等待时间,如果没有设置K8S会假设该容器启动起来后就提供服务了
paused: # 暂停,当更新Pod时,先暂停,而不是立马更新
progressDeadlineSeconds: 60 # 更新场景,等待时间超过此值,状态标记False,并说明原因,但是它并不会阻止 Deployment 继续进行卡住后面的操作
strategy:
rollingUpdate: # 滚动更新,定义滚动更新方式,也就是pod能多几个,少几个
maxSurge: 20% # 允许更新中,最多超过Pod数值
maxUnavailable: 20% # 允许更新中,最多允许几个不可用
selector:
matchLabels:
app: demo-nginx
template:
metadata:
labels:
app: demo-nginx
spec:
containers:
- name: demo-nginx
image: nginx
imagePullPolicy: IfNotPresent
startupProbe: # 启动探测
tcpSocket:
port: 80
livenessProbe: # 存活探测
httpGet:
port: 80
path: /index.html
readinessProbe: # 就绪探测
httpGet:
port: 80
path: "/index.html"
2.4.2.核心参数讲解:
- spec.minReadySeconds:更新场景,等待时间,如果没有设置K8S会假设该容器启动起来后就提供服务了。
- spec.paused: 暂停,当更新Pod时,先暂停,而不是立马更新,后面金丝雀发布要用到
- spec.progressDeadlineSeconds:更新场景,等待时间超过此值,状态标记False,并说明原因,但是它并不会阻止 Deployment 继续进行卡住后面的操作
- spec.strategy.rollingUpdate:滚动更新,定义滚动更新方式,也就是pod能多几个,少几个
- spec.strategy.rollingUpdate.maxSurge:指定在更新期间可以创建的新Pod的最大数量。例如,如果maxSurge设置为1,而Deployment中有3个Pod,则在更新期间可以创建4个Pod,其中3个是旧的Pod,1个是新的Pod。
- spec.strategy.rollingUpdate.maxUnavailable:指定在更新期间可以同时停止的旧Pod的最大数量。例如,如果maxUnavailable设置为1,而Deployment中有3个Pod,则在更新期间可以停止1个Pod。
2.5.Deployment更新策略:
(1)Recreate:重建式更新,把Pod全部删除,在重新创建,风险很大,不建议使用
(2)rollingUpdate:滚动式更新,批量替换更新,平滑升级,用户无感知
三、功能与特点
(1)声明式更新机制: 使用Deployment定义应用的期望状态,系统将自动调整Pod数量和配置,以确保应用达到用户所定义的期望状态。这种声明式的特性使得部署和更新应用变得简单和可预测。
(2)副本管理: Deployment控制器通过ReplicaSet来管理Pod的副本数量。用户可以指定所需的副本数,并且控制器会自动调整Pod数量以保持与期望状态一致。
(3)滚动更新: Deployment支持滚动更新策略,允许逐步替换旧版本的Pod实例,从而实现应用的平滑升级。这确保了应用在更新过程中的高可用性和稳定性。
(4)回滚策略: 在部署新版本应用后,如果发现问题,Deployment控制器可以快速回滚到之前的稳定版本,防止应用出现严重故障。
(5)版本历史记录: Deployment会自动维护版本的历史记录,包括每次更新的详情和状态。这使得用户可以随时查看和管理应用的历史版本。
四、ReplicaSet控制器
4.1.ReplicaSet控制器简要介绍
Kubernetes中用于管理Pod副本数量的重要控制器。它可以看作是Deployment控制器的底层组件,专注于维护Pod的副本数量,确保集群中的Pod实例始终符合用户定义的期望状态。
4.2.ReplicaSet控制器与Deployment控制器的差异
(1)更新策略: Deployment控制器提供了滚动更新和回滚策略,支持应用的平滑升级和快速回退。而ReplicaSet控制器并不直接支持这些功能,它主要用于维护指定数量的Pod副本,不会主动进行应用更新。
(2)声明性更新: Deployment控制器通过声明式的方式定义应用的期望状态,并自动处理Pod的创建、更新和删除。而ReplicaSet控制器相对更为底层,需要手动定义ReplicaSet的配置,更加灵活但也更加复杂。
应用场景: Deployment控制器适用于需要进行滚动更新和回滚的场景,更适合部署无状态应用。而ReplicaSet控制器适用于需要确保固定副本数量的场景,更适合部署有状态应用或无状态应用的固定版本。
4.3.ReplicaSet控制器的作用
ReplicaSet控制器的主要作用是确保Pod的副本数始终符合用户定义的期望状态。当集群中的Pod数量少于期望值时,ReplicaSet控制器会自动创建新的Pod实例,使得副本数达到预期。而当Pod数量超过期望值时,控制器会自动删除多余的Pod,确保集群中只有所需数量的Pod在运行。通过ReplicaSet控制器,用户可以方便地进行水平扩展和缩减,根据应用负载的变化来动态调整Pod的数量。这为应对流量高峰和负载波动提供了便利,保障应用的性能和稳定性。
五、实战案例
3.1.创建web-deployment的控制器
编写资源清单:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
env: uat
spec:
replicas: 5
minReadySeconds: 10
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxSurge: 20%
maxUnavailable: 20%
selector:
matchLabels:
app: web-nginx
template:
metadata:
labels:
app: web-nginx
spec:
containers:
- name: web-nginx
image: web:v1
imagePullPolicy: IfNotPresent
startupProbe:
tcpSocket:
port: 80
livenessProbe:
httpGet:
port: 80
path: /index.html
readinessProbe:
httpGet:
port: 80
path: "/index.html"
执行YAML清单文件:
kubectl create -f web-deployment.yaml
查看创建出来的资源:
kubectl get pod,rs -l app=web-nginx
3.2.Deployment针对WEB站点扩缩容
扩容,将副本扩容至 7,根据上面YAML修改 spec.replicas=7
kubectl edit deploy web-deployment
# 修改 spec.replicas=7
缩容,将副本缩容至 3,根据上面YAML修改 spec.replicas=3
kubectl edit deploy web-deployment
# 修改 spec.replicas=3
3.3.Deployment针对WEB站点滚动更新
滚动更新是一种自动化较高的更新方式,即一批一批的更新Pod资源,用户体验比较平滑。滚动更新使用 spec.strategy.rollingUpdate
字段来定义。只有我们对Deployment中的Template作出修改的时候,也就是修改PodTemplate时才会进行更新。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
env: uat
spec:
replicas: 5
minReadySeconds: 10
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxSurge: 30% # 5*30%=1.5(~=2), 2+5=7,更新期间最多创建7个Pod
maxUnavailable: 20% # 5*20%=1, 1-5=4,更新期间最多停止4个Pod
selector:
matchLabels:
app: web-nginx
template:
metadata:
labels:
app: web-nginx
spec:
containers:
- name: web-nginx
image: web:v2 # 版本更新
imagePullPolicy: IfNotPresent
startupProbe:
tcpSocket:
port: 80
livenessProbe:
httpGet:
port: 80
path: /index.html
readinessProbe:
httpGet:
port: 80
path: "/index.html"
查看当前ReplicaSet的信息:
kubectl replicaset
3.4.版本回退
查看历史版本:
kubectl rollout history deployment web-deployment
回滚版本:回滚到V1 版本
kubectl rollout undo deployment web-deployment --to-revision=1
六、总结
(1)Deployment高级控制器建立在ReplicaSet之上,每次更新镜像版本,都会生成一个新的ReplicaSet,把旧的ReplicaSet替换掉,多个ReplicaSet同时存在,但只运行一个ReplicaSet。
(2)Deployment扩缩容:直接修改replicas字段值,重新apply。
(3)Deployment滚动升级:使用字spec.strategy段定义升级策略,目前支持两种升级策略:
(4)rollingUpdate滚动更新:批量替换更新,平滑升级,用户无感知。
- Recreate重建试更新:把Pod全部删除,在重新创建,风险很大,不建议使用。
- Deployment版本回滚:使用rollout history 查看历史版本,使用rollout undo .... --to-revision=x指定回滚版本。