第二章:《Kubernetes弹性伸缩》
2.1 传统弹性伸缩的困境
从传统意义上,弹性伸缩主要解决的问题是容量规划与实际负载的矛盾。
<图片来自网络>
蓝色水位线表示集群资源容量随着负载的增加不断扩容,红色曲线表示集群资源实际负载变化。
弹性伸缩就是要解决当实际负载增大,而集群资源容量没来得及反应的问题。
1、Kubernetes中弹性伸缩存在的问题
常规的做法是给集群资源预留保障集群可用,通常20%左右。这种方式看似没什么问题,但放到Kubernetes中,就会发现如下2个问题。
-
机器规格不统一造成机器利用率百分比碎片化
在一个Kubernetes集群中,通常不只包含一种规格的机器,假设集群中存在4C8G与16C32G两种规格的机器,对于10%的资源预留,这两种规格代表的意义是完全不同的。
<图片来自网络>
特别是在缩容的场景下,为了保证缩容后集群稳定性,我们一般会一个节点一个节点从集群中摘除,那么如何判断节点是否可以摘除其利用率百分比就是重要的指标。此时如果大规格机器有较低的利用率被判断缩容,那么很有可能会造成节点缩容后,容器重新调度后的争抢。如果优先缩容小规格机器,则可能造成缩容后资源的大量冗余。
-
机器利用率不单纯依靠宿主机计算
当使用K8s之后,资源申请者无需再关心底层硬件资源了,而对于K8s来说,它通过Request和Limit的方式进行配额,Request表示资源的申请值,Limit表示资源的限制值。
2、弹性伸缩概念的延伸
不是所有的业务都存在峰值流量,越来越细分的业务形态带来更多成本节省和可用性之间的跳转。
- 在线负载型:微服务、网站、API
- 离线任务型:离线计算、机器学习
- 定时任务型:定时批量计算
不同类型的负载对于弹性伸缩的要求有所不同,在线负载对弹出时间敏感,离线任务对价格敏感,定时任务对调度敏感。
2.2 kubernetes 弹性伸缩布局
在 Kubernetes 的生态中,在多个维度、多个层次提供了不同的组件来满足不同的伸缩场景。
有三种弹性伸缩:
-
CA(Cluster Autoscaler):Node级别自动扩/缩容
cluster-autoscaler组件
-
HPA(Horizontal Pod Autoscaler):Pod个数自动扩/缩容
-
VPA(Vertical Pod Autoscaler):Pod配置自动扩/缩容,主要是CPU、内存
addon-resizer组件
如果在云上建议 HPA 结合 cluster-autoscaler 的方式进行集群的弹性伸缩管理。
2.3 Node 自动扩容/缩容
1、Cluster AutoScaler
**扩容:**Cluster AutoScaler 定期检测是否有充足的资源来调度新创建的 Pod,当资源不足时会调用 Cloud Provider 创建新的 Node。
**缩容:**Cluster AutoScaler 也会定期监测 Node 的资源使用情况,当一个 Node 长时间资源利用率都很低时(低于 50%)自动将其所在虚拟机从云服务商中删除。此时,原来的 Pod 会自动调度到其他 Node 上面。
支持的云提供商:
- 阿里云:https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/alicloud/README.md
- AWS: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md
- Azure: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md
2、Ansible扩容Node
自动化流程:
- 触发新增Node
- 调用Ansible脚本部署组件
- 检查服务是否可用
- 调用API将新Node加入集群或者启用Node自动加入
- 观察新Node状态
- 完成Node扩容,接收新Pod
扩容
# cat hosts
...
[newnode]
192.168.31.71 node_name=k8s-node3
# ansible-playbook -i hosts add-node.yml -k
缩容
如果你想从Kubernetes集群中删除节点,正确流程如下:
1、获取节点列表
kubectl get node
2、设置不可调度
kubectl cordon $node_name
3、驱逐节点上的Pod
kubectl drain $node_name --ignore-daemonsets
4、移除节点
该节点上已经没有任何资源了,可以直接移除节点:
kubectl delete node $node_name
</