Deployment控制器
Deployment(简写 deploy)是 Kubernetes 控制器的又一种实现,它构建于 ReplicaSet 控制器之上,可为 Pod 和 ReplicaSet 资源提供声明式更新。
Deployment 控制器资源的主要职责同样是为了保证 Pod 资源的健康运行,其大部分功能均可通过调用 ReplicaSet 控制器来实现,同时还增添了部分特性。
-
- 事件和状态查看:必要时可以查看 Deployment 对象升级的详细进度和状态。
- 回滚:升级操作完成后发现问题时,支持使用回滚机制将应用返回到前一个或由用户指定的历史记录中的版本上。
- 版本记录:对 Deployment 对象的每一次操作都予以保存,以供后续可能执行的回滚操作使用。
- 暂停和启动:对于每一次升级,都能够随时暂停和启动。
- 多种自动更新方案:一是 Recreate,即重建更新机制,全面停止、删除旧有的 Pod 后用新版本替代;另一个是 RollingUpdate,即滚动升级机制,逐步替换旧有的 Pod 至新的版本。
1、创建 Deployment
Deployment 是标准的 Kubernetes API 资源,它构建于 ReplicaSet 资源之上,于是其 spec 字段中嵌套使用的字段包含了 ReplicaSet 控制器支持的 replicas、selector、template 和 minReadySeconds,它也正是利用了这些信息完成了其二级资源 ReplicaSet 对象的创建。下面是一个 Deployment 控制器资源的配置清单示例:
kind: Deployment
apiVersion: apps/v1
metadata:
name: deployment-name
namespace: deployment-name
annotations:
deployment.kubernetes.io/revision: '1'
spec:
replicas: 0
selector:
matchLabels:
app: deployment-name
template:
metadata:
creationTimestamp: null
labels:
app: deployment-name
spec:
volumes:
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
type: ''
containers:
- name: deployment-name
image: >-
harbor-name.com/name:DEV-feature_feature_v1.0-3
ports:
- containerPort: 8086
protocol: TCP
- containerPort: 9995
protocol: TCP
env:
- name: ENV
value: UAT
- name: SKYWALKING_SERVICE_NAME
value: '-Dskywalking.agent.service_name=deployment-name'
- name: SKYWALKING_AGENTDIR
value: '-javaagent:/data/agent/skywalking-agent.jar'
- name: JAVA_OPTS
value: >-
-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0
-XX:ActiveProcessorCount=1 -XX:+UseG1GC -Duser.timezone=GMT+08
- name: MAIN_CLASS
value: cn.com.name.admin.video.WebAdminVideoApplication
resources:
limits:
cpu: '1'
memory: 3Gi
requests:
cpu: '0'
memory: 3Gi
volumeMounts:
- name: timezone
mountPath: /etc/localtime
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: Always
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
imagePullSecrets:
- name: harbor
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
2、更新策略
ReplicaSet 控制器的应用更新需要手动分成多步并以特定的次序进行,过程繁杂且容易出错,而 Deployment 却只需要由用户指定在 Pod 模板中要改动的内容,例如容器镜像文本的版本,余下的步骤可交由其自动完成。同样,更新应用程序的规模也只需要修改期望的副本数量,余下的事情交给 Deployment 控制器即可。
Deployment 控制器详细信息中包含了其更新策略的相关配置信息:
kubectl describe deployment deployment-name
Deployment 控制器支持两种更新策略:滚动更新(rolling update)和重新创建(recreate)(就是先把旧版本副本置为0,再一次创建到期望副本数),默认为滚动更新。
滚动升级是默认的更新策略,它在删除一部分旧版本 Pod 资源的同时,补充创建一部分新版本的 Pod 对象进行应用升级,其优势是升级期间,容器中应用提供的服务不会中断,但要求应用程序能够对新旧版本同时工作的情形。
Deployment 控制器的滚动更新操作并非在同一个 ReplicaSet 控制器对象下删除并创建 Pod 资源,而是将它们分置于两个不同的控制器之下:
旧的控制器的 Pod 对象数量不断减少的同时,新控制器的 Pod 对象数量不断增加,直到旧控制器不再拥有 Pod 对象,而新控制器的副本数量变得完全符合期望值为止。
滚动更新时,应用升级期间还需要保证可用的 Pod 对象数量不低于某阈值以确保可以持续处理客户端的服务请求,变动的方式和 Pod 对象的数量范围通过 spec.strategy.rollingUpdate.maxSurge 和 spec.strategy.rollingUpdate.maxUnavailable 两个属性协同进行定义,具体如下:
kubectl explain deployment.spec.strategy
KIND: Deployment
VERSION: apps/v1
RESOURCE: strategy <Object>
DESCRIPTION:
The deployment strategy to use to replace existing pods with new ones.
DeploymentStrategy describes how to replace existing pods with new ones.
FIELDS:
rollingUpdate <Object>
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
type <string>
Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
RollingUpdate.
[root@mh-k8s-master-242-10 ~]#
继续查看 FIELDS:rollingUpdate 字段:
kubectl explain deployment.spec.strategy.rollingUpdate
KIND: Deployment
VERSION: apps/v1
RESOURCE: rollingUpdate <Object>
DESCRIPTION:
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
Spec to control the desired behavior of rolling update.
FIELDS:
maxSurge <string>
The maximum number of pods that can be scheduled above the desired number
of pods. Value can be an absolute number (ex: 5) or a percentage of desired
pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number
is calculated from percentage by rounding up. Defaults to 25%. Example:
when this is set to 30%, the new ReplicaSet can be scaled up immediately
when the rolling update starts, such that the total number of old and new
pods do not exceed 130% of desired pods. Once old pods have been killed,
new ReplicaSet can be scaled up further, ensuring that total number of pods
running at any time during the update is at most 130% of desired pods.
maxUnavailable <string>
The maximum number of pods that can be unavailable during the update. Value
can be an absolute number (ex: 5) or a percentage of desired pods (ex:
10%). Absolute number is calculated from percentage by rounding down. This
can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set
to 30%, the old ReplicaSet can be scaled down to 70% of desired pods
immediately when the rolling update starts. Once new pods are ready, old
ReplicaSet can be scaled down further, followed by scaling up the new
ReplicaSet, ensuring that the total number of pods available at all times
during the update is at least 70% of desired pods.
[root@mh-k8s-master-242-10 ~]#
- maxSurge:指定升级期间存在的总 Pod 对象数量最多可超出预期值的个数,其值可以是 0 或正整数,也可以是一个期望值的百分比;例如,如果期望值是 3 ,当前的属性值是 1,则表示 Pod 对象的总数不能超过 4个。
- maxUnavailable:升级期间正常可用的 Pod 副本数(包括新旧版本)最多不能低于期望数值的个数,其值可以是 0 或正数,也可以是一个期望值的百分比;默认值为 1,该值意味着如果期望值是 3,则升级期间至少要有两个 Pod 对象处于正常服务的提供状态。
配置时,用户还可以使用 Deployment 控制器的 spec.minReadySeconds 属性来控制应用升级的速度。新旧更替过程中,新创建的 Pod 对象一旦成功响应就绪探测即被视为可用(efaults to 0 (pod will be considered available as soon as it is ready)),而后即可立即开始下一轮的替换操作。
kubectl explain deployment.spec KIND: Deployment VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: Specification of the desired behavior of the Deployment. DeploymentSpec is the specification of the desired behavior of the Deployment. FIELDS: minReadySeconds <integer> Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) paused <boolean> Indicates that the deployment is paused. progressDeadlineSeconds <integer> The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s. replicas <integer> Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1. revisionHistoryLimit <integer> The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10. selector <Object> -required- Label selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment. It must match the pod template's labels. strategy <Object> The deployment strategy to use to replace existing pods with new ones. template <Object> -required- Template describes the pods that will be created.
spec.minReadySeconds 能够定义在新的 Pod 对象创建后至少要等待多久才会将其视作就绪,在此期间,更新操作会被阻塞。因此,它可以用来让 Kubernetes 在每次创建出 Pod 资源后都要等上一段时长后再开始下一轮的更替,这个时间长度的理想值是等到 Pod 对象中的应用已经可以接受并处理请求流量。事实上,一个精心设计的等待时长和就绪性探测能让 Kubernetes 系统规避一部分因程序 Bug 而导致的升级故障。
3、版本历史记录
Deployment 控制器也支持用户保留其滚动更新历史中的旧 ReplicaRest 对象版本。
如上图,这赋予了 deployment 控制器进行应用回滚的能力:用户可以按需回滚到指定的历史版本。控制器可保存的历史版本数量由 "spec.revisionHistoryLimit" 属性进行定义。当然,也只有保存于 version 历史版本中的 ReplicaSet 版本可用于回滚,因此,用户要习惯性地在更新操作时指定保留旧版本。
为了保存版本升级的历史,需要在创建 Deployment 对象时于命令中使用 "--record" 选型。
尽管滚动更新以节约系统资源著称,但它也存在一些劣势。直接改动现有环境,会使系统引入不确定性风险,而且升级过程出现问题后,执行回滚操作也会较缓慢。有鉴于此,金丝雀部署可能是较为理想的实现方式,当然,如果不考虑系统资源的可用性,那么传统的部署也是不错的选择。
4、升级 Deployment
修改 Pod 模板相关的配置参数便能完成 Deployment 控制器资源的更新。由于是声明式配置,因此对 Deployment 控制器资源的修改尤其适合使用 apply 和 patch 命令来进行;当然,如果仅是修改容器镜像,"set image" 命令更为易用。
我比较习惯性使用 apply 来对 Deployment 控制器的资源更新。
"kubeclt rollout status" 命令可用于打印滚动更新过程中的状态信息。
kubectl rollout status deployments deployment-name
5、金丝雀发布
Deployment 控制器还支持自定义控制更新过程中的滚动节奏,如 "暂停"(pause)或 "继续"(resume)更新操作,尤其是借助于前文讲到的 maxSurge 和 maxUavailable 属性还能实现更为精巧的过程控制。
金丝雀发布:待第一批新的 Pod 资源创建完成后立即暂停更新过程,此时,仅存在一小部分新版本的应用,主体部分还是旧的版本。然后,再根据用户特征精心筛选出小部分用户的请求路由至新版本的 Pod 应用,并持续观察其是否能稳定地按期望的方式运行。确定没有问题后再继续完成余下 Pod 资源的滚动更新,否则理解回滚更新操作。
为了尽可能地降低现有系统及其容量的影响,金丝雀发布过程通常建议采用 "先添加,再删除,且可用 Pod 资源对象总数不低于期望值" 的方式进行。
首次添加的 Pod 对象数量取决于其接入的第一批请求的规则及单个 Pod 的承载能力,视具体需求而定,为了能够更简单地说明问题,接下来采用首批添加 1 个 Pod 资源的方式。将 Deployment 控制器的 maxSurge 属性值设置为 1,并将 maxUnavailable 属性的值设置为 0。
接下来,启动 deployment 控制器的更新过程,在修改相应容器的镜像版本后立即暂停更新进度,它会在启动第一批新版本 Pod 对象的创建操作之后转为暂停状态。需要注意的是,这里之所以能够在第一批更新启动后就暂停,有赖于此前为 maxReadySeconds 属性设置的时长,因此用户要在更新命令启动后的此时长指定的时间范围内启动暂停操作。
6、回滚 Deployment 控制器下的应用发布
Deployment 控制器的回滚操作可使用 "kubectl rollout undo"命令完成,其操作命令如下:
kubectl rollout undo deployments myapp-deploy
kubectl rollout history deployments myapp-deploy
在 "kubectl rollout undo" 命令上使用 "--to-revision" 选项指定 revision 号码即可回滚到历史特定版本。
kubectl rollout undo deployments myapp-deploy --to-revision=2
回滚操作种,其 version 记录中的信息会发生变动,回滚操作会被当做一次滚动更新追加进历史记录中,而被回滚的条目则会被删除。
需要注意的是,如果此前的滚动更新过程处于 "暂停" 状态,那么回滚操作就需要先将 Pod 模版的版本改回到之前的版本。然后 "继续" 更新,否则,其一直处于暂停状态而无法回滚。
7、扩容和缩容
通过修改 .spec.replicas 即可修改 Deployment 控制器中 Pod 资源的副本数量,它将实时作用于控制器并直接生效。Deployment 控制器是声明式配置,replicas 属性的值可直接修改资源配置文件,然后使用 "kubectl apply" 进行应用,也可以使用 "kubectl edit" 对其进行实时修改。而前一种方式能够将修改结果予以长期留存。
另外,"kubectl scale" 是专用于扩展某些控制器类型的应用规模的命令,包括 Deployment 和 Job 等。而 Deployment 通过 ReplicaSet 控制其 Pod 资源,因此扩缩容的方式是相同的,除了命令直接作用的资源对象有所不同之处,这里不具体说明。