目录:
(1)k8s指南-概述
(2)k8s指南-架构
(3)k8s指南-工作负载(1)
(4)k8s指南-工作负载(2)
(5)k8s指南-工作负载(3)
(6)k8s指南-工作负载(4)
(7)k8s指南-Service
(8)k8s指南-Ingress
(9)k8s指南-DNS与服务发现
(10)K8S指南-平滑升级与自动扩缩容
首先给个结论:
在本系列前文中介绍Deployment的时候介绍过,pod的基本数量是由ReplicaSet控制的,参数字段为.spec.replicas
。
如果未指定
.spec.replicas
字段,则默认值为1。
当deployment更新时,在rs指定pod数量的基础上,根据更新策略来更新pod。也就是说,如果当前pod数不为1,而.spec.replicas
参数为1时,rs控制器会将初始pod数量降为1。
Deployment支持两种更新策略,分别是滚动更新(RollingUpdate)和删除时更新(Recreate),后者也称为单批次更新。
RS可以控制pod的基本数量,但是需要手动去调整。
HPA(HorizontalPodAutoscaler)可以控制Deployment及其ReplicaSet的规模,从而可以实现自动控制pod的数量。
HPA自动扩缩不适用于无法扩缩的对象,例如DaemonSet。
HorizontalPodAutoscaler 被实现为 Kubernetes API 资源和控制器。
资源决定了控制器的行为。 在 Kubernetes 控制平面内运行的水平 Pod 自动扩缩控制器会定期调整其目标(例如:Deployment)的所需规模,以匹配观察到的指标, 例如,平均 CPU 利用率、平均内存利用率或你指定的任何其他自定义指标。间隔时间由kube-controller-manager
的--horizontal-pod-autoscaler-sync-period
参数设置,默认为15s。
HPA的任何目标资源都可以基于其中的Pods的资源用量来实现扩缩。在定义Pod规约时,cpu
和memory
这类资源请求是必须被设定的。这些设定值被用来确定资源利用量并被HPA控制器用来对目标资源完成扩缩操作。下面是一个示例:
spec:
minReplicas: 1
maxReplicas: 5
metrics:
type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
基于这一配置,HPA控制器会根据全部pod的平均cpu利用率是否达到60%来决定要不要扩缩容。
注意,利用率是pod的当前资源用量与request请求值之间的比值。
设置基于内存的扩缩容策略其实是有坑的,原因在于pod的内存使用之后是不会主动归还给操作系统的,从而导致pod的内存使用量只增不减,永远不会缩容。具体参见pod内存使用高问题分析
HPA除了支持pod级别的资源指标外,还支持容器级别的资源指标。这使得用户可以为pod中最重要的容器配置扩缩阈值。
比如说,当前pod中有一个web应用和一个执行日志操作的容器,你可以基于web容器的资源用量来执行扩缩,而不管日志操作容器的资源用量。下面是一个示例:
type: ContainerResource
containerResource:
name: cpu
container: application // 容器名
target:
type: Utilization
averageUtilization: 60
在HPA中可以通过behavior
参数来设置扩容和缩容行为,包括扩/缩容速率,扩/缩容之后的稳定窗口期。下面是一个示例:
behavior:
scaleDown:
stabilizationWindowSeconds: 600 # 等待10分钟再开始缩容
policies:
- type: Pods
value: 4
periodSeconds: 60 // 每分钟最多只允许缩容4
- type: Percent
value: 10
periodSeconds: 60 // 每分钟最多只允许缩容10%
以上配置为缩容时的策略,第一个策略允许在一分钟内最多缩容4个pod,第二个表示在一分钟内最多缩容当前pod数量的10%。当存在多个策略时,取最大更改量的策略为默认策略。
稳定窗口
在上面扩缩行为示例代码中有一个参数为stabilizationWindowSeconds
, 这个时间叫稳定窗口,目的是为了避免因为指标利用率的毛刺现象而出现频繁的扩缩容。
有了稳定窗口期之后,当HPA控制器判断需要扩缩容时,需要先保持窗口期的时间稳定不变。稳定期结束后,根据稳定期时间段的最终期望结果来进行扩缩容。
从最基本的角度来看,HPA控制器是基于指标期望值和实际值的比例来进行工作的。计算方式为:
期望副本数 = ceil[当前副本数 *(当前指标值 / 期望指标值)]
举个例子,假设当前指标值为200m
, 期望值为100m
,则hpa会将当前pod数量扩容2倍(200/100)。
如果当前值为 50m
,则pod数量会减半(50/100)。其中ceil为天花板函数,表示向上取整。
但有一点需要注意,如果期望值与实际值的比值接近1,则控制面不会进行扩缩容。那接近1是怎么衡量的呢?这里实际上是可以通过参数进行控制的,如果没有显式设置,则默认值为0.1。换句话说,默认情况下,当期望值与实际值的比值在0.9~1.1之间时,hpa不会实际发生扩缩容。
要使用自定义扩缩容,不必指定所有字段。可以在基础配置中指定默认行为,并在自定义配置中覆写自定义参数。
下面是一个默认配置:
behavior:
scaleDown:
stabilizationWindowSeconds: 300 // 缩容稳定窗口期
policies:
- type: Percent
value: 100
periodSeconds: 15 //15s内最多缩容50%
scaleUp:
stabilizationWindowSeconds: 0 // 扩容稳定窗口期为0
policies:
- type: Percent
value: 100
periodSeconds: 15 // 15s内最多扩容100%
- type: Pods
value: 4
periodSeconds: 15 // 15s内最多扩容4个pod
selectPolicy: Max // 更改值最大的策略生效,默认就是该策略
然后在自定义配置中覆写缩容策略:
behavior:
scaleDown:
policies:
- type: Percent
value: 10
periodSeconds: 60
该配置会与默认配置合并,最终的缩容策略为:60s内最多缩容10%。
selectPolicy:Disable
会关闭扩/缩容
在HPA中可以指定副本数的上下限。比如minReplicas: 1 maxReplicas: 5
表示pod数量下限为1,上限为5,换句话说,不管如何缩容,pod数都不能少于1,不管如何扩容,pod数不能大于5。
HPA中副本数的上下限也会对Deployment中的ReplicaSet有影响。
当Deployment上线或更新时,pod初始数量会被设置为Deployment中的rs数量,随后会受到HPA中的副本数限制。
举例说明,当前pod数量为20。Deployment更新时,其rs参数为1,因此rs控制器会将pod数量Scale down到1。
如果HPA中的minReplicas和maxReplica为15~25,则会将pod数量Scale up到15。随后Deployment中更新策略才会对pod执行更新。
这个就是本文开头给出的结论。
比如说有一个配置如下:
behavior:
scaleUp:
policies:
- type: Percent
value: 900
periodSeconds: 10
表示允许每10秒最大扩容900%。
但在实际中发现,pod扩容没有达到预期效果。通常原因是计算周期与指标延迟。
在上文中说过HPA控制器是周期性计算期望副本数的,默认值为15秒。每次计算时获取到的监控指标也可能是有延迟的。
这两部分的时长之和为扩容的延迟时间。
通常都不需要HPA极度的灵敏,有一定的延时一般都是可接受的。
Kubernetes默认提供了CPU和内存作为HPA弹性伸缩的指标,如果有更复杂的场景需求,比如基于业务单副本QPS大小来进行自动扩缩容,可以考虑安装prometheus-adapter来实现基于自定义指标来进行弹性伸缩。
[1]. https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale