本文分享自华为云社区《根据Nginx Ingress指标对指定后端进行HPA》,作者: 可以交个朋友。
背景
生产场景下,Nginx Ingress 的流量会通过域名和 path 路径最终转发至不同的应用,而有时候 cpu 和内存并不是 nginx 的性能瓶颈,此时可以基于nginx_ingress_controller_requests
指标,为其对应的应用配置 HPA,以实现基于不同域名和 path 的请求量弹性指定后端工作负载
简介
环境准备
注意:由于 HPA 规则中scaleTargetRef
和describedObject
两个字段都无法指定命名空间,所以指标来源、HPA 和弹性目标需在同一命名空间,而 nginx-ingress 和业务工作负载一般处在不同命名空间;本次方案采用 external 类型的 HPA,可以忽略指标来源的命名空间
操作步骤
创建演示需要的弹性目标工作负载,service 以及 ingress
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-hpa
labels:
app: test-app
spec:
replicas: 1
selector:
matchLabels:
app: test-app
template:
metadata:
labels:
app: test-app
spec:
containers:
- image: skto/sample-app:v2
name: metrics-provider
ports:
- name: http
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: test-app
namespace: default
labels:
app: test-app
spec:
ports:
- port: 8080
name: http
protocol: TCP
targetPort: 8080
selector:
app: test-app
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
labels:
app: sample-app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- image: skto/sample-app:v2
name: metrics-provider
ports:
- name: http
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: sample-app
namespace: default
labels:
app: sample-app
spec:
ports:
- port: 80
name: http
protocol: TCP
targetPort: 8080
selector:
app: sample-app
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: test.example.com
http:
paths:
- backend:
service:
name: sample-app
port:
number: 80
path: /
pathType: ImplementationSpecific
- backend:
service:
name: test-app
port:
number: 8080
path: /home
pathType: ImplementationSpecific
复制代码
分别查询test.example.com/
和test.example.com/home
的 nginx_ingress_controller_requests 指标,指标正常
创建 external 类型的 apiservices 资源;创建后 apiservices 的状态为 false 是正常现象,添加 externalRules 后状态变为 true
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.external.metrics.k8s.io
spec:
group: external.metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service: #指定prometheus-adapter对应的service,华为CCE插件中adapter名称为custom-metrics-apiserver
name: custom-metrics-apiserver
namespace: monitoring
port: 443
version: v1beta1
versionPriority: 100
复制代码
将 externalRules 规则添加到 adapter 的 configmap 中,修改后需要重启 prometheus-adapter 服务
kubectl -n monitoring edit configmap user-adapter-config
复制代码
externalRules:
- metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)
name:
as: ${1}_per_second
matches: ^(.*)
resources:
namespaced: false #忽略指标来源的命名空间,该配置不适用rules规则
seriesQuery: nginx_ingress_controller_requests
复制代码
seriesQuery:原始指标;可以直接写指标名称,也可以使用{labelKey=labelValue}的方式筛选出原始指标
metricsQuery:用 PromQL 对指标进行筛选汇聚;.Series
表示原始指标,.LabelMatchers
表示对指标进行标签筛选,hpa 中可以配置具体的筛选规则
name:将指标重命名
resources:hpa 查询指标时通过 api 的方式调用,调用路径为:
而 resources 的作用就是将指标中命名空间标签的值替换路径中的 ${namespace},而我们本次方案需要忽略指标来源命名空间。
custom-metrics-apiserver 服务重启后需要等待 1 分钟左右,执行命令查看指标是否正常
kubectl get --raw /apis/external.metrics.k8s.io/v1beta1/namespaces/*/nginx_ingress_controller_requests_per_second
复制代码
创建 HPA 规则
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: sample-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: External
external:
metric:
name: nginx_ingress_controller_requests_per_second
selector:
matchLabels: #可以通过该字段对指标进行过滤,这里标签筛选条件会加入到externalRules的<<.LabelMatchers>>中。
exported_service: sample-app #筛选后端服务为sample-app的请求
host: test.example.com #筛选访问域名为test.example.com的请求
target:
type: AverageValue #External指标类型下只支持Value和AverageValue类型的目标值。
averageValue: 30
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: test-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: test-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: External
external:
metric:
name: nginx_ingress_controller_requests_per_second
selector:
matchLabels:
exported_service: test-app
host: test.example.com
target:
type: AverageValue
averageValue: 30
复制代码
弹性演示
使用命令压测 sample-app 对应的访问域名和路径,正常触发弹性;请自行配置域名与 ELB 地址的映射
ab -c 50 -n 5000 http://test.example.com/
复制代码
用同样的方式压测 test-app,正常触发弹性
ab -c 50 -n 5000 http://test.example.com/home
复制代码
点击关注,第一时间了解华为云新鲜技术~
评论