Kubernetes 弹性伸缩
弹性伸缩概述
从传统意义上,弹性伸缩主要解决的问题是容量规划与实际负载的矛盾。
蓝色水位线表示集群资源容量随着负载的增加不断扩容,红色曲线表示集群资源实际负载变化。
弹性伸缩就是要解决当实际负载增大,而集群资源容量没来得及反应的问题。
Kubernetes弹性伸缩布局
在Kubernetes平台中,资源分为两个维度:
-
Node级别:K8s将多台服务器抽象一个集群资源池,每个Node提供这些资源
-
Pod级别:Pod是K8s最小部署单元,运行实际的应用程序,使用request和limit为Pod配额
因此,K8s实现弹性伸缩也是这两个级别,当Node资源充裕情况下,Pod可任意弹性,当不足情况下需要弹性增加节 点来扩容资源池。
针对Pod负载:当Pod资源不足时,使用HPA(Horizontal Pod Autoscaler)自动增加Pod副本数量
针对Node负载:当集群资源池不足时,使用CA(Cluster Autoscaler)自动增加Node
Node自动扩容/缩容
Node弹性伸缩有两种方案:
- Cluster Autoscaler:是一个自动调整Kubernetes集群大小的组件,需要与公有云一起使用,例如AWS、Azure、Aliyun
项目地址: https://github.com/kubernetes/autoscaler
- 自研发:根据Node监控指标或者Pod调度状态判断是否增加Node,需要一定开发成本
Node自动扩容/缩容:实现思路
Node自动扩容/缩容: Cluster Autoscaler
Cluster Autoscaler支持的云提供商:
-
AWS:https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md
-
GCE:https://kubernetes.io/docs/concepts/cluster-administration/cluster-management/
-
GKE:https://cloud.google.com/container-engine/docs/cluster-autoscaler
Node自动扩容/缩容: 自研发
当集群资源不足时,触发新增Node大概思路:
-
申请一台服务器
-
调用Ansible脚本部署Node组件并自动加入集群
-
检查服务是否可用,加入监控
-
完成Node扩容,接收新Pod
自动增加Node:https://gitee.com/lucky_liuzhe/ansible-install-k8s-v1.20
自动减少Node:
如果你想从Kubernetes集群中删除节点,正确流程如下:
1、获取节点列表
kubectl get node |
2、设置不可调度
kubectl cordon k8s-node3 |
3、驱逐节点上的Pod
kubectl drain k8s-node3 --ignore-daemonsets |
4、移除节点
kubectl delete nodes k8s-node3 |
Pod自动扩容/缩容:HPA介绍
Horizontal Pod Autoscaler(HPA,Pod水平自动伸缩):根据资源利用率或者自定义指 标自动调整Deployment的Pod副本数量,提供应用并发。HPA不适于无法缩放的对象,例 如DaemonSet。
Pod自动扩容/缩容:HPA基本工作原理
Kubernetes 中的 Metrics Server 持续采集所有 Pod 副本的指标数据。HPA 控制器通过 Metrics Server 的 API(聚合 API)获取这些数据,基于用户定义的扩缩容规则进行计算,得到目标 Pod 副本 数量。当目标 Pod 副本数量与当前副本数量不同时,HPA 控制器就向 Pod 的Deployment控制器发起 scale 操作,调整 Pod 的副本数量,完成扩缩容操作。
Pod自动扩容/缩容:使用HPA前提条件
使用HPA,确保满足以下条件:
启用Kubernetes API聚合层
相应的API已注册:
-
对于资源指标(例如CPU、内存),将使用metrics.k8s.io API,一般由metrics-server提供。
-
对于自定义指标(例如QPS),将使用custom.metrics.k8s.io API,由相关适配器(Adapter)服务提供。
已知适配器列表:https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api
Kubernetes API聚合层:
在 Kubernetes 1.7 版本引入了聚合层,允许第三方应用程序通过将自己注册到 kube-apiserver上,仍然通过 API Server 的 HTTP URL 对新的 API 进行访问和 操作。为了实现这个机制,Kubernetes 在 kube-apiserver 服务中引入了一个 API 聚合层(API Aggregation Layer),用于将扩展 API 的访问请求转发到用 户服务的功能。
启用聚合层:
如果你使用kubeadm部署的,默认已开启。
如果 你使用二进制方式部署的话,需要在kubeAPIServer中添加启动参数,增加以下配置:
#vi /opt/kubernetes/cfg/kube-apiserver.conf |
Pod自动扩容/缩容:基于资源指标
Metrics Server:是一个数据聚合器,从kubelet收集资源指标,并通 过Metrics API在Kubernetes apiserver暴露,以供HPA使用。
项目地址:https://github.com/kubernetes-sigs/metrics-server
Metrics Server部署:
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
#vi components.yaml |
kubelet-insecure-tls:不验证kubelet提供的https证书
测试:
kubectl get apiservices |grep metrics |
也可以使用kubectl top访问Metrics API:
kubectl top node #查看Node资源消耗 |
如果能正常显示资源消耗说明Metrics Server服务工作正常。
kubectl top ——>apiserver——>metrics-server——>kubelet(cadivosr)——>pod
1、部署应用
kubectl create deployment web --image=nginx --dry-run=client -o yaml > deployment.yaml |
注意:修改yaml,增加resources.requests.cpu
2、创建HPA
kubectl autoscale deployment web --min=2 --max=10 --cpu-percent=80 |
说明:为名为web的deployment创建一个HPA对象,目标CPU使用率为80%,副本数量配置为2到10之间。
3、压测
yum install httpd-tools |
4、观察扩容状态
kubectl get hpa |
Pod自动扩容/缩容:冷却周期
在弹性伸缩中,冷却周期是不能逃避的一个话题, 由于评估的度量标准是动态特性,副本的数量可能会不断波动, 造成丢失流量,所以不应该在任意时间扩容和缩容。
在 HPA 中,为缓解该问题,默认有一定控制:
-
–horizontal-pod-autoscaler-downscale-delay :当前操作完成后等待多次时间才能执行缩容操作,默认5分钟
-
–horizontal-pod-autoscaler-upscale-delay :当前操作完成后等待多长时间才能执行扩容操作,默认3分钟
可以通过调整kube-controller-manager组件启动参数调整。
Pod自动扩容/缩容:基于自定义指标
为满足更多的需求,HPA也支持自定义指标,例如QPS、5xx错误状态码等,实现自定义指标由autoscaling/v2版本提供,而 v2版本又分为beta1和beta2两个版本。
这两个版本的区别是 autoscaling/v1beta1支持了 :
-
Resource Metrics(资源指标)
-
Custom Metrics(自定义指标)
而在 autoscaling/v2beta2的版本中额外增加了External Metrics(扩展指标)的支持。
对于自定义指标(例如QPS),将使用custom.metrics.k8s.io API,由相关适配器(Adapter)服务提供。
已知适配器列表:https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api
假设我们有一个网站,想基于每秒接收到的HTTP请求对其Pod进行 自动缩放,实现HPA大概步骤:
1、部署Prometheus
2、对应用暴露指标,部署应用,并让Prometheus采集暴露的指标
3、部署Prometheus Adapter
4、为指定HPA配置Prometheus Adapter
5、创建HPA
6、压测、验证
Prometheus(普罗米修斯)是一个开源的监控系统,在Kubernetes平台得到广泛应用。
1、部署Prometheus
kubectl apply -f . |
访问地址:http://NodeIP:30090
2、对应用暴露指标,部署应用,并让Prometheus采集暴露的指标。
在做这步之前先了解下Prometheus如何监控应用的。
如果要想监控,前提是能获取被监控端指标数据,并且这个数据格式必须遵 循Prometheus数据模型,这样才能识别和采集,一般使用exporter提供监 控指标数据。但对于自己开发的项目,是需要自己实现类似于exporter的指 标采集程序。
exporter列表:https://prometheus.io/docs/instrumenting/exporters
先模拟自己开发一个网站,采用Python Flask Web框架,写两个页面:
-
/ 首页
-
/metrics 指标
然后使用Dockefile制作成镜像并部署到Kubernetes平台。
kubectl apply -f metrics-flask-app.yaml #部署应用对外暴露指标并声明让prometheus采集 |
由于我们Prometheus配置了基于Kubernetes服务发现,会自动采集Pod暴露的指标:
3、部署Prometheus Adapter
kubectl apply -f prometheus-adapter.yaml |
验证是否正常工作:
kubectl get apiservices |grep custom |
4、为指定HPA配置Prometheus Adapter
增加一段配置,增加完后删除adapter pod重建生效。
#vi prometheus-adapter.yaml |
配置描述:
-
seriesQuery:Prometheus查询语句,查询应用系列指标。
-
resources:Kubernetes资源标签映射到Prometheus标签。
-
name:将Prometheus指标名称在自定义指标API中重命名, matches正则匹配,as指定新名称。
-
metricsQuery:一个Go模板,对调用自定义指标API转换为 Prometheus查询语句。
Adapter向Prometheus查询语句最终是:
sum(rate(request_count_total{app=“flask-app”, kubernetes_namespace=“default”}[2m])) by (kubernetes_pod_name)
由于HTTP请求统计是累计的,对HPA自动缩放不是特别有用,因此将其转为速率指标。 这条语句意思是:查询每个Pod在2分钟内访问速率,即QPS(每秒查询率)
向自定义指标API访问:
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/qps" |
如果配置没问题,会返回JSON数据,注意里面的value字段,HPA控制器会拿这个值计算然后比对阈值。这个值单位是m,表示 毫秒,千分之一,例如值为500m是每秒0.5个请求,10000m是每秒10个请求(并发)。
进一步模拟验证:
对比请求的数据:
5、创建HPA
#vi hpa-v2-qps.yaml |
每秒超过10个请求进行扩容pod操作