下面来简单回顾下Deployment的概念。
Deployment在K8s架构中属于控制器。
Deployment 是对 ReplicaSet(RS)更高层次的封装, 可以来自动管理 ReplicaSet,从而来管理Pod的副本数。还可以通过标签选择器选择对哪些Pod生效。
而ReplicaSet用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而异常多出来的容器也会自动回收。
所以使用Deployment可以确保健康 Pod 的数量、弹性伸缩、滚动升级以及应用多版本发布跟踪等。
创建 Deployment可以有两种方式:
执行如下命令:
kubectl create deploy nginx-deploy --image=nginx:1.7.9
# deployment.apps/nginx-deploy created
然后我们可以看下创建的Deployment:
kubectl get deploy
# 结果如下
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 1/1 1 1 44s
除了创建了Deployment,他还会帮我们创建对应RS和Pod,查看如下:
# 查看rs
kubectl get rs
# 结果如下:
NAME DESIRED CURRENT READY AGE
nginx-deploy-58dcf5bbfb 1 1 1 110s
# 查看pod
kubectl get po
# 结果如下:
NAME READY STATUS RESTARTS AGE
nginx-deploy-58dcf5bbfb-52j95 1/1 Running 0 2m33s
我们还可以获取Deployment的信息时,通过yaml的方式输出:
kubectl get deploy nginx-deploy -o yaml
其结果如下:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2023-08-16T14:54:24Z"
generation: 1
labels: # Deployment的标签
app: nginx-deploy
name: nginx-deploy
namespace: default
resourceVersion: "509161"
uid: decc3132-c0ab-44f1-bcf0-0f26d66acef5
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx-deploy
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx-deploy
spec:
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2023-08-16T14:54:26Z"
lastUpdateTime: "2023-08-16T14:54:26Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2023-08-16T14:54:24Z"
lastUpdateTime: "2023-08-16T14:54:26Z"
message: ReplicaSet "nginx-deploy-58dcf5bbfb" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
创建文件nginx-deploy.yaml,内容如下:
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为deployment
metadata: # 元信息
labels: # 标签
app: nginx-deploy
name: nginx-deploy # deployment的名字
namespace: default # 所在命名空间
spec:
replicas: 1 # 期望副本数
revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
selector: # 选择器,用于找到匹配的RS,管理指定标签的Rs
matchLabels: # 按照标签匹配
app: nginx-deploy # 匹配的标签
strategy: # 更新策略
rollingUpdate: # 滚动更新配置
maxSurge: 25% # 进行滚动更新时,更新的个数超过期望副本数的比例
maxUnavailable: 25% # 进行滚动更新时,最大不可用更新比例,也就是更新不成功最多能有多少个
type: RollingUpdate # 更新策略采用滚动更新
template: # pod模板
metadata: # pod的元信息
labels: # pod的标签
app: nginx-deploy
spec: # pod的描述信息
containers: # pod的描述信息
- image: nginx:1.7.9 # pod使用镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
name: nginx # 容器名称
restartPolicy: Always # 重启策略
terminationGracePeriodSeconds: 30 # 容器删除等待时间
执行命令:
kubectl create -f nginx-deploy.yaml
# deployment.apps/nginx-deploy created
检查结果:
kubectl get deploy
# 结果如下
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 1/1 1 1 5s
kubectl get rs
# 结果如下
NAME DESIRED CURRENT READY AGE
nginx-deploy-58dcf5bbfb 1 1 1 11s
kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deploy-58dcf5bbfb-6jszh 1/1 Running 0 97s
所谓的扩缩容就是可以动态的去更新pod的副本数。扩容即增加副本数,缩容即减少副本数。
实现扩缩容有如下4种方式:
ubectl edit
命令,修改 spec:replicas:n
即可kubectl edit deployment nginx-deploy
scale
命令实现扩缩容kubectl scale deploy nginx-deploy --replicas=3
kubectl apply -f xxx.yaml
命令即可vim nginx-deploy.yaml
kubectl apply -f nginx-deploy.yaml
kubectl patch statefulset web -p '{"spec":{"replicas":3}}'
下面我们使用edit命令演示:
kubectl edit deploy nginx-deploy
如下副本数改为3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hxlSKhio-1692547564785)(./imgs/7-1.png)]
然后就会帮我们立马创建3个pod出来,但是deployment和RS还是一个:
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 15m
kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-58dcf5bbfb 3 3 3 15m
get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deploy-58dcf5bbfb-6jszh 1/1 Running 0 16m app=nginx-deploy,pod-template-hash=58dcf5bbfb
nginx-deploy-58dcf5bbfb-6q5k7 1/1 Running 0 2m4s app=nginx-deploy,pod-template-hash=58dcf5bbfb
nginx-deploy-58dcf5bbfb-t5k8p 1/1 Running 0 2m4s app=nginx-deploy,pod-template-hash=58dcf5bbfb
注意pod标签会自动加一个pod-template-hash=58dcf5bbfb,用来表示pod使用的哪个模板。可以看到,3个pod使用的模板是一个。
Deployment 支持两种镜像更新策略:重建更新
和滚动更新
,可以通过 strategy
字段进行配置:
strategy: # 指定新的Pod替代旧的Pod的策略,支持两个属性
type: # 指定策略类型,支持两种策略 Recreate:在创建出新的Pod之前会先杀掉所有已经存在的Pod RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本的Pod
rollingUpdate: # 当type为RollingUpdate的时候生效,用于为rollingUpdate设置参数,支持两个属性:
maxUnavailable: 25% # 用来指定在升级过程中不可用的Pod的最大数量,默认为25%。
maxSurge: 25% # 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。
Deployment 的默认的镜像更新策略是 RollingUpdate(滚动更新),实际开发的时候,使用默认镜像更新策略即可。
重建更新即创建出新的Pod之前会先杀掉所有已经存在的Pod。这样会有一段时间服务不可用。所以不常用。
修改我们上面yaml文件如下:
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为deployment
metadata: # 元信息
labels: # 标签
app: nginx-deploy
name: nginx-deploy # deployment的名字
namespace: default # 所在命名空间
spec:
replicas: 3 # 期望副本数
revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
selector: # 选择器,用于找到匹配的RS,管理指定标签的Rs
matchLabels: # 按照标签匹配
app: nginx-deploy # 匹配的标签
strategy: # 更新策略
type: Recreate # Recreate:在创建出新的Pod之前会先杀掉所有已经存在的Pod
template: # pod模板
metadata: # pod的元信息
labels: # pod的标签
app: nginx-deploy
spec: # pod的描述信息
containers: # pod的描述信息
- image: nginx:1.7.9 # pod使用镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
name: nginx # 容器名称
restartPolicy: Always # 重启策略
terminationGracePeriodSeconds: 30 # 容器删除等待时间
然后执行命令创建Deployment:
kubectl create -f nginx-deploy.yaml
# deployment.apps/nginx-deploy created
然后可执行如下命令更新使用的镜像:
kubectl set image deployment nginx-deploy nginx=nginx:1.20.2
或者也可以直接修改yaml文件。
结果会看到以前3个被删除,重新创建了三个pod
所谓滚动更新就是并不是一次性全部删除,而是先更新一部分pod,再删除一部分老的pod,直至所有的pod更新完成,以前的老的pod也全部删除。
滚动更新也是Deployment默认的更新策略。
下面修改yaml文件如下:
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为deployment
metadata: # 元信息
labels: # 标签
app: nginx-deploy
name: nginx-deploy # deployment的名字
namespace: default # 所在命名空间
spec:
replicas: 3 # 期望副本数
revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
selector: # 选择器,用于找到匹配的RS,管理指定标签的RS
matchLabels: # 按照标签匹配
app: nginx-deploy # 匹配的标签
strategy: # 更新策略
rollingUpdate: # 滚动更新配置
maxSurge: 25% # 进行滚动更新时,更新的个数超过期望副本数的比例
maxUnavailable: 25% # 进行滚动更新时,最大不可用更新比例,也就是更新不成功最多能有多少个
type: RollingUpdate # 更新策略采用滚动更新
template: # pod模板
metadata: # pod的元信息
labels: # pod的标签
app: nginx-deploy
spec: # pod的描述信息
containers: # pod的描述信息
- image: nginx:1.7.9 # pod使用镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
name: nginx # 容器名称
restartPolicy: Always # 重启策略
terminationGracePeriodSeconds: 30 # 容器删除等待时间
设置了副本数为3,好演示更新的效果。
然后执行命令创建Deployment:
kubectl create -f nginx-deploy.yaml
# deployment.apps/nginx-deploy created
然后可执行如下命令更新使用的镜像:
kubectl set image deployment nginx-deploy nginx=nginx:1.9.1
然后多次查看deployment的状态:
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 2 3 10s
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 2 3 10s
test@testdeMacBook-Pro ~ % kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 10s
可以看到,deployment的READY数量一直是3,UP-TO-DATE 的数量是逐渐增加的。这就是滚动更新策略的效果。
可以使用describe命令查看deployment的事件:
kubectl describe deploy nginx-deploy
主要查看事件,结果如下:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 2m24s deployment-controller Scaled up replica set nginx-deploy-58dcf5bbfb to 3
Normal ScalingReplicaSet 2m16s deployment-controller Scaled up replica set nginx-deploy-6d5979b84b to 1
Normal ScalingReplicaSet 2m15s deployment-controller Scaled down replica set nginx-deploy-58dcf5bbfb to 2 from 3
Normal ScalingReplicaSet 2m15s deployment-controller Scaled up replica set nginx-deploy-6d5979b84b to 2 from 1
Normal ScalingReplicaSet 2m14s deployment-controller Scaled down replica set nginx-deploy-58dcf5bbfb to 1 from 2
Normal ScalingReplicaSet 2m14s deployment-controller Scaled up replica set nginx-deploy-6d5979b84b to 3 from 2
Normal ScalingReplicaSet 2m13s deployment-controller Scaled down replica set nginx-deploy-58dcf5bbfb to 0 from 1
从上面信息也可以看到滚动更新的步骤。
还是以上面我们创建的3副本yaml文件为例,演示下如何进行版本回滚。
首先可以使用如下命令查询历史版本:
kubectl rollout history deployment nginx-deploy
结果如下:
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
1
2
可以看到已经有两个版本了,其中第一列表示版本号,第二列是修改的信息,现在是空的,我们可以在更新deployment时,在命令后面加上–record,如下:
kubectl set image deployment nginx-deploy nginx=nginx:1.7.9
然后再查看下历史版本;
kubectl rollout history deployment nginx-deploy
# 结果如下
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
4 kubectl set image deployment nginx-deploy nginx=nginx:1.9.1 --record=true
5 kubectl set image deployment nginx-deploy nginx=nginx:1.7.9 --record=true
然后我们可以看下rs的数量
kubectl get rs
# 结果如下
NAME DESIRED CURRENT READY AGE
nginx-deploy-58dcf5bbfb 3 3 3 16m
nginx-deploy-6d5979b84b 0 0 0 16m
可以看到RS也有两个,其中第二个nginx-deploy-6d5979b84b的READY为0,它就是上个版本用到的RS。
Deployment 之所以能够实现版本的回退,就是通过记录下历史的 ReplicaSet 来实现的,一旦想回滚到那个版本,只需要将当前版本的 Pod 数量降为 0 ,然后将回退版本的 Pod 提升为目标数量即可。
好了,下面就开始回滚版本。
如果我想使用第4个版本,把镜像版本改回到nginx:1.9.1,可使用如下命令:
kubectl rollout undo deployment nginx-deploy --to-revision=4
# deployment.apps/nginx-deploy rolled back,说明回滚成功
再看下RS:
kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-58dcf5bbfb 0 0 0 20m
nginx-deploy-6d5979b84b 3 3 3 20m
nginx-deploy-6d5979b84b的READY变回了3,上面的nginx-deploy-58dcf5bbfb变成了0。
Deployment 支持版本升级过程中的暂停、继续功能等诸多功能:
kubetl rollout 参数 deploy xx # 支持下面的选择
# status 显示当前升级的状态
# history 显示升级历史记录
# pause 暂停版本升级过程
# resume 继续已经暂停的版本升级过程
# restart 重启版本升级过程
# undo 回滚到上一级版本 (可以使用--to-revision回滚到指定的版本),前面说过
这里就不再演示了。