Deployment
Deployment资源是一种更为高阶的资源,它通过创建ReplicaSet的资源的方式,接管匹配标签的Pods。
通常我们使用Deployment来部署应用程序,从而方便通过声明的方式升级应用,即通过Deployment可以更容易地更新应用程序,通过声明Deployment资源需要到达的状态,Kubernetes会帮我们达到最终需要的状态。
创建Deployment
如其他资源一样,可以通过编写YAML配置文件的格式创建Deployment资源。
下面介绍一个具体的Deployment的YAML配置文件:
apiVersion: apps/v1 # 注意版本信息
kind: Deployment # 资源类型为Deployment
metadata:
name: httpd
namespace: default # Deployment所在命名空间,默认为default
labels: # Deployment的标签
run: httpd
spec:
progressDeadlineSeconds: 600 # 滚动升级超时时间,默认为600s,超时后,describe结果中的Conditions会显示ProgressDeadlineExceeded。当超过这个时间后,需要使用kubectl rollout undo来回滚升级
revisionHistoryLimit: 10 # 增加回滚记录中可以保存的版本数(因为Deployment更新后,不会删除旧的RS,所以这里其实就是保存的最大RS数)
replicas: 3 # 产生的副本个数
minReadySeconds: 10 # 用来减慢滚动更新的速度(容器需要至少Ready10s后才能认定其为可用,在Pod可用前,滚动升级过程不会继续),配合Readiness探针,可以实现当滚动升级过程中发现Pod出错,可以立即停止滚动更新
strategy:
type: RollingUpdate # 更新策略(这种是删一个旧的,加一个新的,还有一种是Recreate,即全部删除旧的后,再创建新的)
rollingUpdate: # 定制滚动更新中的策略(适用于RollingUpdate,type为Recreate,则该字段为空)
maxSurge: 35% # 滚动更新中副本总数可超过DESIRED的上限(向上取整)
maxUnavailable: 35% # 滚动更新中不可用的副本占DESIRED的最大比例(向下取整)
selector: # (必须)用于匹配Pod的labels
matchLabels:
run: httpd
template: # (必须)Pod的模板
metadata:
labels:
run: httpd
spec: # Pod的规格
containers:
- name: httpd
image: httpd:2.4.17
ports:
- containerPort: 80 # 容器暴露的Port,其实这里只是一个类似于声明的,这里即使不写,容器的应用可能也暴露该端口
env: # docker的ENV
- name: MYNAME
value: http
nodeSelector: # 根据Nodes的label选择合适的Node部署Pods
disktype: ssd
然后可以使用kubectl apply -f
生成该资源。
通过kubectl get deployments
可以看到创建出来的Deployment资源的名字为httpd
,再通过kubectl get rs
可以看到创建出来的RS的名字为httpd-xxxxxx
,再通过kubectl get pods
可以看到创建的Pods的名字为httpd-xxxxxx-yyyy
(xxxxxxx和yyyy为自动生成的值)。
通过Deployment更新
通过Deployment进行滚动升级是声明式的,即只需要通过修改Deployment中的Pod模板,它会自动将集群中的状态收敛至该目标状态。
Deployment有两种更新策略,具体配置可以看上面的Deployment的YAML配置文件详情:
RollingUpdate
:默认策略,滚动升级,逐个删除旧Pod的同时创建新Pod;Recreate
:一次性删除所有旧Pod,然后创建新Pod;
更新过程
之前提到,Deployment首先创建ReplicaSet,再由ReplicaSet负责创建并接管Pod。
升级Deployment非常容易,只需要修改资源的配置文件即可,修改方式见修改资源。

从上图中,可以将升级流程归纳为以下几步:
Deployment创建一个新的RS,负责创建并接管新的Pod,其与旧RS具有不同值的pod-template-hash标签;
逐步对旧RS缩容的同时,对新RS扩容,直至更新完毕。
在更新完毕后,会保存旧的RS,当使用Deployment进行回滚时,可以使用保存的旧的RS扩容旧的Pod的同时,使用新的RS缩容新的Pod。若Deployment接管的RS总数超过了
spec.revisionHistoryLimit
(默认为10),则删除保存时间最久的RS;
与ReplicationController滚动更新对比,可以总结出以下优势:
更新流程均由Deployment这个控制器完成,与kubectl客户端解耦;
用户不用关心创建或删除RS,对用户无感,Deployment的标签无需修改;
由于Deployment可以保存历史RS,所以可以方便应用回滚;
maxSurge和maxUnavailable
在RollingUpdate
这种滚动更新策略中,可以指定maxSurge和maxUnavailable两个属性。
maxSurge:定义除Deployment的
spec.replicas
个Pod外,最多能超过的Pod数量,默认值为25%,向上取整。例如,spec.replicas=4
,则maxSurge=4*25%=1
,也就是说当前的最多的Pod数不超过4+1=5个;maxUnavailable:定义了相对于Deployment的
spec.replicas
允许有多少Pod实例处于不可用状态,默认值为25%,向下取整。例如,spec.replicas=4
,则maxUnavailable=4*25%=1
,也就是说在滚动更新过程中,原本4个可用的Pod中,可以有一个被替换(若maxSurge计算得1,也就是Pod数不超过5,那么还可以再部署一个新的Pod,也就是同一时间可能有2个Pod不可用,3个Pod可用)。
下面举一个例子,更直观的观察滚动更新的流程,Deployment的spec.replicas=4
,maxSurge=25%
,maxUnavailable=25%
:

假设A=maxSurge,B=maxUnavailable,X=spec.replicas,那么可以得到下面的公式:
更新过程中,最少可用Pod数 = X - B;
每轮更新过程中,新RS可创建最大Pod数 = 旧RS可删除最大Pod数 = A + B;
使用rollout控制更新流程
观察升级过程
可以通过rollout status
观察Deployment资源对象的升级过程。例如,观察Deployment对象kubia的升级过程:
kubectl rollout status deployment kubia
查看滚动升级历史
可以通过rollout history
查看Deployment资源对象的滚动升级历史。例如,观察Deployment对象kubia的滚动升级历史:
kubectl rollout history deployment kubia
回滚升级
可以通过rollout undo
进行回滚,可以加上--to-revision
标志,指定回滚的确切版本。例如,针对Deployment对象进行回滚:
kubectl rollout undo deployment kubia
kubectl rollout undo deployment kubia --to-revision=1
暂停和恢复升级流程
可以通过rollout pause
暂停Deployment资源对象的滚动升级流程,从而方便用户验证新的版本行为是否符合预期,即金丝雀版本(灰度),一部分为新版本,一部分为旧版本。例如,将Deployment对象kubia的滚动更新流程暂停:
kubectl rollout pause deployment kubia
恢复流程可以通过rollout resume
来实现。例如:
kubectl rollout resume deployment kubia
Last updated
Was this helpful?