Kubernetes实战(二十七)-HPA实战
1 HPA简介
HPA 全称是 Horizontal Pod Autoscaler,用于POD 水平自动伸缩, HPA 可以 基于 POD CPU 利用率对 deployment 中的 pod 数量进行自动扩缩容(除了 CPU 也可以基于自定义的指标进行自动扩缩容)。pod 自动缩放不适用于无法缩放的对象,比如 DaemonSets。
HPA 由 Kubernetes API 资源和控制器实现。控制器会周期性的获取平均 CPU 利用率, 并与目标值相比较后调整 deployment 中的副本数量。
2 HPA实战
HPA 是根据指标来进行自动伸缩的,目前 HPA 有两个版本–v1 和 v2beta
HPA 的 API 有三个版本,通过 kubectl api-versions | grep autoscal 可看到
[root@master k8s]# kubectl api-versions | grep autoscal
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
- autoscaling/v1 只支持基于 CPU 指标的缩放;
- autoscaling/v2beta1 支持 Resource Metrics(资源指标,如 pod 内存)和 Custom Metrics (自定义指标)的缩放;
- autoscaling/v2beta2 支持 Resource Metrics(资源指标,如 pod 的内存)和 Custom Metrics (自定义指标)和 ExternalMetrics(额外指标)的缩放,但是目前也仅仅是处于 beta 阶段
K8S 从 1.8 版本开始,CPU、内存等资源的 metrics 信息可以通过 Metrics API 来获取,用户可以直接获取这些 metrics 信息(例如通过执行 kubect top 命令),HPA 使用这些 metics 信息来实现动态伸缩。
Metrics server:
- Metrics server 是 K8S 集群资源使用情况的聚合器
- 从 1.8 版本开始,Metrics server 可以通过 yaml 文件的方式进行部署
- Metrics server 收集所有 node 节点的 metrics 信息
2.1 HPA工作原理
HPA 的实现是一个控制循环,由 controller manager 的--horizontal-pod-autoscaler-syncperiod 参数指定周期(默认值为 15 秒)。每个周期内,controller manager 根据每个 HorizontalPodAutoscaler 定义中指定的指标查询资源利用率。controller manager 可以从 resource metrics API(pod 资源指标)和 custom metrics API(自定义指标)获取指标。
然后通过现有 pods 的 CPU 使用率的平均值(计算方式是最近的 pod 使用量(最近一分钟的平均 值,从 metrics-server 中获得)除以设定的每个 Pod 的 CPU 使用率限额)跟目标使用率进行比较, 并且在扩容时,还要遵循预先设定的副本数限制:MinReplicas <= Replicas <= MaxReplicas。计算扩容后 Pod 的个数:sum(最近一分钟内某个 Pod 的 CPU 使用率的平均值)/CPU 使用上限的 整数+1。
2.2 扩容流程
1)创建 HPA 资源,设定目标 CPU 使用率限额,以及最大、最小实例数
2)收集一组中(PodSelector)每个 Pod 最近一分钟内的 CPU 使用率,并计算平均值
3)读取 HPA 中设定的 CPU 使用限额
4)计算:平均值之和/限额,求出目标调整的实例个数
5)目标调整的实例数不能超过 1)中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数
6)回到 2,不断循环
2.3 HPA部署验证
2.3.1 安装数据采集组件metrics-server
metrics-server 是一个集群范围内的资源数据集和工具,同样的,metrics-server 也只是显示数据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、 请求延时等指标,metric-server 收集数据给 k8s 集群内使用,如 kubectl,hpa,scheduler 等
#通过离线方式获取镜像
需要的镜像是:k8s.gcr.io/metrics-server-amd64:v0.3.6 和 k8s.gcr.io/addon-resizer:1.8.4,把镜像上传 到 k8s 的各个节点,并导入:
docker load -i addon.tar.gzdocker load -i metrics-server-amd64-0-3-6.tar.gz
# 部署metrics-server服务
#在/etc/kubernetes/manifests 里面改一下 apiserver 的配置
注意:这个是 k8s 在 1.17 的新特性,如果是 1.16 版本的可以不用添加,1.17 以后要添加。这个参 数的作用是 Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API。
[root@master ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
增加如下内容: - --enable-aggregator-routing=true
重新更新 apiserver 配置:
[root@master ~]# kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml
pod/kube-apiserver created
[root@master ~]# kubectl apply -f metrics.yaml
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
configmap/metrics-server-config created
deployment.apps/metrics-server created
service/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
#验证 metrics-server 是否部署成功
[root@master ~]# kubectl get pods -n kube-system | grep metrics
metrics-server-6595f875d6-bjgrv 2/2 Running 0 31s# 测试kubectl top命令
[root@master ~]# kubectl top nodes
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 368m 9% 1641Mi 28%
node1 93m 4% 700Mi 19%
node3 75m 3% 559Mi 32% [root@master ~]# kubectl top pods -n kube-system
NAME CPU(cores) MEMORY(bytes)
calico-kube-controllers-56c7cdffc6-n2grp 1m 21Mi
calico-node-lcq82 41m 81Mi
calico-node-ltnpt 39m 101Mi
calico-node-zhvpx 76m 74Mi
coredns-7f89b7bc75-bd6k7 10m 15Mi
coredns-7f89b7bc75-thkbx 6m 15Mi
etcd-master 34m 71Mi
kube-apiserver-master 107m 459Mi
kube-controller-manager-master 40m 54Mi
kube-proxy-gjx9g 1m 18Mi
kube-proxy-wmnd4 1m 18Mi
kube-proxy-xz4b7 1m 18Mi
kube-scheduler-master 6m 23Mi
metrics-server-6595f875d6-bjgrv 1m 15Mi
2.3.2 创建php-apache服务,利用HAP进行自动扩缩容
1)创建并运行一个 php-apache 服务
使用 dockerfile 构建一个新的镜像,在 k8s 的 master 构建
[root@master php]# mkdir /root/php
[root@master php]# cd php
[root@master php]# docker load -i php.tar.gz
[root@master php]# cat dockerfile
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php
[root@master php]# cat index.php
<?php$x = 0.0001;for ($i = 0; $i <= 1000000;$i++) {$x += sqrt($x);}echo "OK!";
?>
2)构建镜像
[root@master php]# docker build -t 192.168.10.12/test/hap-example:v1 .
# 在各节点导入该镜像
[root@master php]# docker save 192.168.10.12/test/hap-example:v1 -o hpa-example.tar.gz
[root@master php]# docker load -i hpa-example.tar.gz
3) 部署php-apache服务
[root@master php]# cat php-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata: name: php-apache
spec:selector:matchLabels:run: php-apachereplicas: 1template:metadata:labels:run: php-apachespec:containers:- name: php-apacheimage: 192.168.10.12/test/hap-example:v1imagePullPolicy: IfNotPresentports:- containerPort: 80resources:limits:cpu: 500mrequests:cpu: 200m
---
apiVersion: v1
kind: Service
metadata:name: php-apachelabels:run: php-apache
spec:ports:- port: 80selector:run: php-apache[root@master php]# kubectl apply -f php-apache.yaml
deployment.apps/php-apache created
service/php-apache created[root@master php]# kubectl get pods
NAME READY STATUS RESTARTS AGE
php-apache-58857b55d7-4sr6m 1/1 Running 0 15s
2.3.3 创建HPA
php-apache服务正在运行,使用kubectl autoscale创建自动缩放器,实现对php-apache 这个 deployment 创建的 pod 自动扩缩容,下面的命令将会创建一个 HPA,HPA 将会 根据 CPU,内存等资源指标增加或减少副本数,创建一个可以实现如下目的的 hpa:
- 让副本数维持在 1-10 个之间(这里副本数指的是通过 deployment 部署的 pod 的副本数)
- 将所有 Pod 的平均 CPU 使用率维持在 50%(通过 kubectl top 看到的每个 pod 如果 是 200 毫核,这意味着平均 CPU 利用率为 100 毫核)
#给上面 php-apache 这个 deployment 创建 HPA
[root@master php]# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
horizontalpodautoscaler.autoscaling/php-apache autoscaled
- --cpu-percent=50(表示 cpu 使用率不超过 50%)
- --min=1(最少一个 pod)
- --max=10(最多 10 个 pod)
# 验证hpa是否创建成功
[root@master php]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 1 38s
注:由于我们没有向服务器发送任何请求,因此当前 CPU 消耗为 0%(TARGET 列显示了由相应的 deployment 控制的所有 Pod 的平均值)。
2.3.4 HPA基于CPU使用率实现Pod自动扩/缩容
压测php-apache服务,只针对CPU进行压测。
1)准备好busybox和nginx镜像,并导入到节点中
[root@master ~]# docker load -i busybox.tar.gz
[root@master ~]# docker load -i nginx-1-9-1.tar.gz
2)启动
启动一个容器,并将无限查询循环发送到 php-apache 服务(复制 k8s 的 master 节点的终端,也就是打开一个新的终端窗口)。
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
php-apache ClusterIP 10.105.167.249 <none> 80/TCP 14m[root@master php]# kubectl run v1 -it --image=busybox:latest --image-pull-policy=IfNotPresent -- /bin/sh
# while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 194%/50% 1 10 1 22m
# 上面可以看到,CPU 消耗已经达到 194%,每个 pod 的目标 cpu 使用率是 50%,所以,php-apache 这个 deployment 创建的 pod 副本数将调整为 4个副本,为什么是 4 个副本,因为 194/50=3,满足 cpu 使用率上限50%需要4个pod。# 自动扩容到7个副本,满足了需求,直到cpu使用率不超过50%
[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 48%/50% 1 10 7 24m[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
php-apache-58857b55d7-skr4b 1/1 Running 0 86s
php-apache-58857b55d7-smkfp 1/1 Running 0 2m27s
php-apache-58857b55d7-vdsdj 1/1 Running 0 3m18s
php-apache-58857b55d7-wfvjg 1/1 Running 0 2m27s
v1 1/1 Running 0 2m57s
注意:可能需要几分钟来稳定副本数。由于不以任何方式控制负载量,因此最终副本数可能会与此示例不同
# 停止对 php-apache 服务压测,HPA 会自动对 php-apache 这个 deployment 创建的 pod做缩容
[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 2%/50% 1 10 7 27m
# 需要一段时间检测才进行缩容
2.3.5 HPA基于内存实现Pod自动扩容
1)导入镜像
[root@master ~]# docker load -i nginx-1-9-1.tar.gz
2)执行yaml文件
[root@master ~]# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-hpa
spec:selector:matchLabels:app: nginxreplicas: 1template:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.9.1imagePullPolicy: IfNotPresentports:- containerPort: 80name: httpprotocol: TCPresources:requests:cpu: 0.01memory: 25Milimits:cpu: 0.05memory: 60Mi
---
apiVersion: v1
kind: Service
metadata:name: nginxlabels:app: nginx
spec:selector:app: nginxtype: NodePortports:- name: httpprotocol: TCPport: 80targetPort: 80
nginx 的 pod 里需要有如下字段,否则 hpa 会采集不到内存指标
resources:
requests:
cpu: 0.01
memory: 25Mi
limits:
cpu: 0.05
memory: 60Mi
[root@master ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-hpa created
service/nginx created[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.110.32.245 <none> 80:30073/TCP 111s
[root@master manifests]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-hpa-fb74696c-vtgsg 1/1 Running 0 4m40s
#内存使用率超过60%就扩容
[root@master ~]# cat hpa-v1.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:name: nginx-hpa
spec:maxReplicas: 10minReplicas: 1scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: nginx-hpametrics:- type: Resourceresource:name: memorytargetAverageUtilization: 60
[root@master ~]# kubectl apply -f hpa-v1.yaml
horizontalpodautoscaler.autoscaling/nginx-hpa created[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 5%/60% 1 10 1 39s
3)压测nginx-hpa,针对内存使用超过60%就自动扩容
压测nginx-hpa
登录到上面通过 pod 创建的 nginx,并生成一个文件,增加内存
[root@master ~]# kubectl exec -it nginx-hpa-fb74696c-vtgsg -- /bin/sh
# dd if=/dev/zero of=/tmp/a# 在新终端里查看
[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 125%/60% 1 10 3 15m上面的 targets 列可看到 125%/60%,125%表示当前内存使用率,60%表示所有 pod 的内存使用率维持在 60%,现在内存使用率达到 200%,所以 pod 增加到 3个,新增2个
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-hpa-fb74696c-4kmvv 1/1 Running 0 3m21s 10.244.166.156 node1 <none> <none>
nginx-hpa-fb74696c-vtgsg 1/1 Running 0 25m 10.244.166.141 node1 <none> <none>
nginx-hpa-fb74696c-x4wnx 1/1 Running 0 3m21s 10.244.166.155 node1 <none> <none># 当我停止压缩后,hap会对pod自动缩容
如何查看v2版本的hpa如何定义?
[root@master ~]# kubectl get hpa.v2beta2.autoscaling -o yaml > v2.yamlkubectl explain HorizontalPodAutoscaler kubectl explain HorizontalPodAutoscaler.spec
2.3.6 HPA 基于自定义指标自动扩缩容
除了基于 CPU 和内存来进行自动扩缩容之外,还可以根据自定义的监控指标来进行。这个自定义指标就需要使用 Prometheus Adapter
,Prometheus 用于监控应用的负载和集群本身的各种指标,Prometheus Adapter
可以使用 Prometheus 收集的指标并使用它们来制定扩展策略,这些指标都是通过 APIServer 暴露的,而且 HPA 资源对象也可以很轻易的直接使用。
首先部署一个示例应用,在该应用程序上测试 Prometheus 指标自动缩放,资源清单文件如下所示:(hpa-prome-demo.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:name: hpa-prom-demo
spec:selector:matchLabels:app: nginx-servertemplate:metadata:labels:app: nginx-serverspec:containers:- name: nginx-demoimage: cnych/nginx-vts:v1.0resources:limits:cpu: 50mrequests:cpu: 50mports:- containerPort: 80name: http
---
apiVersion: v1
kind: Service
metadata:name: hpa-prom-demoannotations:prometheus.io/scrape: "true"prometheus.io/port: "80"prometheus.io/path: "/status/format/prometheus"
spec:ports:- port: 80targetPort: 80name: httpselector:app: nginx-servertype: NodePort
这里部署的应用是在 80 端口的 /status/format/prometheus
这个端点暴露 nginx-vts 指标的,前面已经在 Prometheus 中配置了 Endpoints 的自动发现,所以直接在 Service 对象的 annotations
中进行配置,这样就可以在 Prometheus 中采集该指标数据了。为了测试方便,这里使用 NodePort 类型的 Service,现在直接创建上面的资源对象即可:
$ kubectl apply -f hpa-prome-demo.yaml
deployment.apps/hpa-prom-demo created
service/hpa-prom-demo created
$ kubectl get pods -l app=nginx-server
NAME READY STATUS RESTARTS AGE
hpa-prom-demo-755bb56f85-lvksr 1/1 Running 0 4m52s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hpa-prom-demo NodePort 10.101.210.158 <none> 80:32408/TCP 5m44s
......
部署完成后可以使用如下命令测试应用是否正常,以及指标数据接口能够正常获取:
$ curl http://k8s.qikqiak.com:32408
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>
$ curl http://k8s.qikqiak.com:32408/status/format/prometheus
# HELP nginx_vts_info Nginx info
# TYPE nginx_vts_info gauge
nginx_vts_info{hostname="hpa-prom-demo-755bb56f85-lvksr",version="1.13.12"} 1
# HELP nginx_vts_start_time_seconds Nginx start time
# TYPE nginx_vts_start_time_seconds gauge
nginx_vts_start_time_seconds 1586240091.623
# HELP nginx_vts_main_connections Nginx connections
# TYPE nginx_vts_main_connections gauge
......
上面的指标数据中,nginx_vts_server_requests_total
这个指标表示请求总数,是一个 Counter
类型的指标,可以使用该指标的值来确定是否需要对应用进行自动扩缩容。
接下来将 Prometheus-Adapter 安装到集群中,并添加一个规则来跟踪 Pod 的请求,可以将 Prometheus 中的任何一个指标都用于 HPA,但是前提是得通过查询语句将它拿到(包括指标名称和其对应的值)。
定义一个如下所示的规则:
rules:
- seriesQuery: 'nginx_vts_server_requests_total'seriesFilters: []resources:overrides:kubernetes_namespace:resource: namespacekubernetes_pod_name:resource: podname:matches: "^(.*)_total"as: "${1}_per_second"metricsQuery: (sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>))
这是一个带参数的 Prometheus 查询,其中:
seriesQuery
:查询 Prometheus 的语句,通过这个查询语句查询到的所有指标都可以用于 HPAseriesFilters
:查询到的指标可能会存在不需要的,可以通过它过滤掉。-
resources
:通过seriesQuery
查询到的只是指标,如果需要查询某个 Pod 的指标,肯定要将它的名称和所在的命名空间作为指标的标签进行查询,resources
就是将指标的标签和 k8s 的资源类型关联起来,最常用的就是 pod 和 namespace。有两种添加标签的方式,一种是overrides
,另一种是template
。
overrides
:它会将指标中的标签和 k8s 资源关联起来。上面示例中就是将指标中的 pod 和 namespace 标签和 k8s 中的 pod 和 namespace 关联起来,因为 pod 和 namespace 都属于核心 api 组,所以不需要指定 api 组。当我们查询某个 pod 的指标时,它会自动将 pod 的名称和名称空间作为标签加入到查询条件中。比如nginx: {group: "apps", resource: "deployment"}
这么写表示的就是将指标中 nginx 这个标签和 apps 这个 api 组中的deployment
资源关联起来;- template:通过 go 模板的形式。比如
template: "kube_<<.Group>>_<<.Resource>>"
这么写表示,假如<<.Group>>
为 apps,<<.Resource>>
为 deployment,那么它就是将指标中kube_apps_deployment
标签和 deployment 资源关联起来。
name
:用来给指标重命名的,之所以要给指标重命名是因为有些指标是只增的,比如以 total 结尾的指标。这些指标拿来做 HPA 是没有意义的,我们一般计算它的速率,以速率作为值,那么此时的名称就不能以 total 结尾了,所以要进行重命名。
matches
:通过正则表达式来匹配指标名,可以进行分组as
:默认值为$1
,也就是第一个分组。as
为空就是使用默认值的意思。
metricsQuery
:这就是 Prometheus 的查询语句了,前面的seriesQuery
查询是获得 HPA 指标。当我们要查某个指标的值时就要通过它指定的查询语句进行了。可以看到查询语句使用了速率和分组,这就是解决上面提到的只增指标的问题。
Series
:表示指标名称LabelMatchers
:附加的标签,目前只有pod
和namespace
两种,因此我们要在之前使用resources
进行关联GroupBy
:就是 pod 名称,同样需要使用resources
进行关联。
接下来我们通过 Helm Chart 来部署 Prometheus Adapter,新建 hpa-prome-adapter-values.yaml
文件覆盖默认的 Values 值,内容如下所示:
rules:default: falsecustom:- seriesQuery: 'nginx_vts_server_requests_total'resources: overrides:kubernetes_namespace:resource: namespacekubernetes_pod_name:resource: podname:matches: "^(.*)_total"as: "${1}_per_second"metricsQuery: (sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>))prometheus:url: http://thanos-querier.kube-mon.svc.cluster.local
这里我们添加了一条 rules 规则,然后指定了 Prometheus 的地址,我们这里是使用了 Thanos 部署的 Promethues 集群,所以用 Querier 的地址。使用下面的命令一键安装:
$ helm install prometheus-adapter stable/prometheus-adapter -n kube-mon -f hpa-prome-adapter-values.yaml
NAME: prometheus-adapter
LAST DEPLOYED: Tue Apr 7 15:26:36 2020
NAMESPACE: kube-mon
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
prometheus-adapter has been deployed.
In a few minutes you should be able to list metrics using the following command(s):kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
等一小会儿,安装完成后,可以使用下面的命令来检测是否生效了:
$ kubectl get pods -n kube-mon -l app=prometheus-adapter
NAME READY STATUS RESTARTS AGE
prometheus-adapter-58b559fc7d-l2j6t 1/1 Running 0 3m21s
$ kubectl get --raw="/apis/custom.metrics.k8s.io/v1beta1" | jq
{"kind": "APIResourceList","apiVersion": "v1","groupVersion": "custom.metrics.k8s.io/v1beta1","resources": [{"name": "namespaces/nginx_vts_server_requests_per_second","singularName": "","namespaced": false,"kind": "MetricValueList","verbs": ["get"]},{"name": "pods/nginx_vts_server_requests_per_second","singularName": "","namespaced": true,"kind": "MetricValueList","verbs": ["get"]}]
}
我们可以看到 nginx_vts_server_requests_per_second
指标可用。 现在,让我们检查该指标的当前值:
$ kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/nginx_vts_server_requests_per_second" | jq .
{"kind": "MetricValueList","apiVersion": "custom.metrics.k8s.io/v1beta1","metadata": {"selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/nginx_vts_server_requests_per_second"},"items": [{"describedObject": {"kind": "Pod","namespace": "default","name": "hpa-prom-demo-755bb56f85-lvksr","apiVersion": "/v1"},"metricName": "nginx_vts_server_requests_per_second","timestamp": "2020-04-07T09:45:45Z","value": "527m","selector": null}]
}
出现类似上面的信息就表明已经配置成功了,接下来我们部署一个针对上面的自定义指标的 HPA资源对象,如下所示:(hpa-prome.yaml)
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:name: nginx-custom-hpa
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: hpa-prom-demominReplicas: 2maxReplicas: 5metrics:- type: Podspods:metricName: nginx_vts_server_requests_per_secondtargetAverageValue: 10
如果请求数超过每秒10个,则将对应用进行扩容。直接创建上面的资源对象:
$ kubectl apply -f hpa-prome.yaml
horizontalpodautoscaler.autoscaling/nginx-custom-hpa created
$ kubectl describe hpa nginx-custom-hpa
Name: nginx-custom-hpa
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"nginx-custom-hpa","namespace":"d...
CreationTimestamp: Tue, 07 Apr 2020 17:54:55 +0800
Reference: Deployment/hpa-prom-demo
Metrics: ( current / target )"nginx_vts_server_requests_per_second" on pods: <unknown> / 10
Min replicas: 2
Max replicas: 5
Deployment pods: 1 current / 2 desired
Conditions:Type Status Reason Message---- ------ ------ -------AbleToScale True SucceededRescale the HPA controller was able to update the target scale to 2
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal SuccessfulRescale 7s horizontal-pod-autoscaler New size: 2; reason: Current number of replicas below Spec.MinReplicas
可以看到 HPA 对象已经生效了,会应用最小的副本数2,所以会新增一个 Pod 副本:
$ kubectl get pods -l app=nginx-server
NAME READY STATUS RESTARTS AGE
hpa-prom-demo-755bb56f85-s5dzf 1/1 Running 0 67s
hpa-prom-demo-755bb56f85-wbpfr 1/1 Running 0 3m30s
接下来我们同样对应用进行压测:
$ while true; do wget -q -O- http://k8s.qikqiak.com:32408; done
打开另外一个终端观察 HPA 对象的变化:
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-custom-hpa Deployment/hpa-prom-demo 14239m/10 2 5 2 4m27s
$ kubectl describe hpa nginx-custom-hpa
Name: nginx-custom-hpa
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"nginx-custom-hpa","namespace":"d...
CreationTimestamp: Tue, 07 Apr 2020 17:54:55 +0800
Reference: Deployment/hpa-prom-demo
Metrics: ( current / target )"nginx_vts_server_requests_per_second" on pods: 14308m / 10
Min replicas: 2
Max replicas: 5
Deployment pods: 3 current / 3 desired
Conditions:Type Status Reason Message---- ------ ------ -------AbleToScale True ReadyForNewScale recommended size matches current sizeScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric nginx_vts_server_requests_per_secondScalingLimited False DesiredWithinRange the desired count is within the acceptable range
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal SuccessfulRescale 5m2s horizontal-pod-autoscaler New size: 2; reason: Current number of replicas below Spec.MinReplicasNormal SuccessfulRescale 61s horizontal-pod-autoscaler New size: 3; reason: pods metric nginx_vts_server_requests_per_second above target
可以看到指标 nginx_vts_server_requests_per_second
的数据已经超过阈值了,触发扩容动作了,副本数变成了3,但是后续很难继续扩容了,这是因为上面我们的 while
命令并不够快,3个副本完全可以满足每秒不超过 10 个请求的阈值。
如果需要更好的进行测试,我们可以使用一些压测工具,比如 ab、fortio 等工具。当我们中断测试后,默认5分钟过后就会自动缩容:
$ kubectl describe hpa nginx-custom-hpa
Name: nginx-custom-hpa
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"nginx-custom-hpa","namespace":"d...
CreationTimestamp: Tue, 07 Apr 2020 17:54:55 +0800
Reference: Deployment/hpa-prom-demo
Metrics: ( current / target )"nginx_vts_server_requests_per_second" on pods: 533m / 10
Min replicas: 2
Max replicas: 5
Deployment pods: 2 current / 2 desired
Conditions:Type Status Reason Message---- ------ ------ -------AbleToScale True ReadyForNewScale recommended size matches current sizeScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric nginx_vts_server_requests_per_secondScalingLimited True TooFewReplicas the desired replica count is less than the minimum replica count
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal SuccessfulRescale 23m horizontal-pod-autoscaler New size: 2; reason: Current number of replicas below Spec.MinReplicasNormal SuccessfulRescale 19m horizontal-pod-autoscaler New size: 3; reason: pods metric nginx_vts_server_requests_per_second above targetNormal SuccessfulRescale 4m2s horizontal-pod-autoscaler New size: 2; reason: All metrics below target
到这里我们就完成了使用自定义的指标对应用进行自动扩缩容的操作。如果 Prometheus 安装在我们的 Kubernetes 集群之外,则只需要确保可以从集群访问到查询的端点,并在 adapter 的部署清单中对其进行更新即可。在更复杂的场景中,可以获取多个指标结合使用来制定扩展策略。
相关文章:

Kubernetes实战(二十七)-HPA实战
1 HPA简介 HPA 全称是 Horizontal Pod Autoscaler,用于POD 水平自动伸缩, HPA 可以 基于 POD CPU 利用率对 deployment 中的 pod 数量进行自动扩缩容(除了 CPU 也可以基于自定义的指标进行自动扩缩容)。pod 自动缩放不适用于无法…...

IDEA 配置以及一些技巧
1. IDEA设置 1.1 设置主题 1.2 设置字体和字体大小 1.3 编辑区的字体用ctrl鼠标滚轮可以控制大小 1.4 自动导包和优化多余的包 1.5 设置编码方式 1.6 配置 maven 1.7 设置方法形参参数提示 1.8 设置控制台的字体和大小 注意:设置控制台字体和大小后需要重启IDEA才会…...

Android 11 访问 Android/data/或者getExternalCacheDir() 非root方式
前言: 需求要求安装三方应用ExternalCacheDir()下载下来的apk文件。 getExternalCacheDir() : /storage/emulated/0/Android/data/com../cache/ 获取访问权限 如果手机安卓版本为Android10的时候,可以在AndroidManifest.xml中添加下列代码 android:requestLegacyExt…...

Eclipse安装配置、卸载教程(Windows版)
Eclipse是一个开放源代码的集成开发环境(IDE),最初由IBM公司开发,现在由Eclipse基金会负责维护。它是一个跨平台的工具,可以用于开发多种编程语言,如Java、C/C、Python、PHP、Rust等。 Eclipse提供了一个可…...

正点原子--STM32基本定时器学习笔记(2)
目录 1. 相关寄存器介绍 1.1 控制寄存器 1(TIMx_CR1)编辑 1.2 DMA/中断使能寄存器(TIMx_DIER) 1.3 状态寄存器(TIMx_SR) 1.4 计数器(TIMx_CNT) 1.5 预分频器(TIMx_PSC) 1.6 自动重装载寄存器(TIMx_ARR) 2. 工程建立 3. 导入tim.c文件 4. 相关HAL库函数介绍 4.1 H…...

学习笔记:正则表达式
正则表达式是文本处理方面功能最强大的工具之一。正则表达式语言用来构造正则表达式,最终构造出来的字符串就称为正则表达式,正则表达式用来完成搜索和替换操作。 本文参考《正则表达式必知必会(修订版)》《Learning Regular Exp…...

03-抓包_封包_协议_APP_小程序_PC应用_WEB应用
抓包_封包_协议_APP_小程序_PC应用_WEB应用 一、参考工具二、演示案例:2.1、WEB应用站点操作数据抓包-浏览器审查查看元素网络监听2.2、APP&小程序&PC抓包HTTP/S数据-Charles&Fiddler&Burpsuite2.3、程序进程&网络接口&其他协议抓包-WireSh…...

C语言笔试题之实现C库函数 strstr()(设置标志位)
实例要求: 1、请你实现C库函数strstr()(stdio.h & string.h),请在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始);2、函数声明:int strStr(char* h…...

什么是IDE,新手用哪个IDE比较好
什么是IDE IDE(Integrated Development Environment,集成开发环境)是一种为程序员提供软件开发所需的代码编辑、构建、调试等功能于一体的应用程序。IDE通常包含了代码编辑器、编译器、调试器和图形用户界面等工具,这些工…...

Flask 入门6:模板继承
1. 一个网站中,大部分网页的模块是重复的,比如顶部的导航栏,底部的备案信息。如果在每个页面中都重复的去写这些代码,会让项目变得臃肿,提高后期的维护成本。比较好的做法是,通过模板继承,把一…...

欢迎来到操作系统的世界
🌞欢迎来到操作系统的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 🙏作者水平很有限,如果发现错误ÿ…...

寒假作业-day5
1>现有无序序列数组为23,24,12,5,33,5347,请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用直接插入排序实现升序排序 函数4:请使用插入排序实现升序排序 代码: #include<stdio.h&g…...

互联网加竞赛 基于深度学的图像修复 图像补全
1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学的图像修复 图像补全 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-se…...

用于制作耳机壳的UV树脂耳机壳UV胶价格高不高?
制作耳机壳的UV树脂价格相对于一些其他材料可能会略高,但具体的价格取决于多个因素,如品牌、型号、质量等。一些高端的UV树脂品牌和型号可能会价格较高,但它们也通常具有更好的性能和更广泛的应用范围。 此外,UV树脂的价格也与购买…...

【开源】JAVA+Vue+SpringBoot实现房屋出售出租系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…...

Golang 并发 生产者消费者模式
Golang 并发 生产者消费者模式 生产者-消费者模式能够带来的好处 生产者消费者模式是一种常见的并发编程模式,用于解决生产者和消费者之间的数据传递和处理问题。在该模式中,生产者负责生成数据(生产),而消费者负责处…...

Win32 SDK Gui编程系列之--ListView自绘OwnerDraw
ListView自绘OwnerDraw 1.ListView自绘OwnerDraw 正在试错是否使用了列表视图,尽量制作出智能的表格编辑器。本页显示了业主抽签的表格数据(二维数组数据)的显示方法。 显示画面和整个程序如下所示。使用ListView_GetSubItemRect宏的话,就不需要getRect函数了。 当nCol的…...

深度学习本科课程 实验5 循环神经网络
循环神经网络实验 任务内容 理解序列数据处理方法,补全面向对象编程中的缺失代码,并使用torch自带数据工具将数据封装为dataloader分别采用手动方式以及调用接口方式实现RNN、LSTM和GRU,并在至少一种数据集上进行实验从训练时间、预测精度、…...

Redis篇之过期淘汰策略
一、数据的过期策略 1.什么是过期策略 Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。 2.过期策略-惰…...

【Kubernetes】kubectl top pod 异常?
目录 前言一、表象二、解决方法1、导入镜像包2、编辑yaml文件3、解决问题 三、优化改造1.修改配置文件2.检查api-server服务是否正常3.测试验证 总结 前言 各位老铁大家好,好久不见,卑微涛目前从事kubernetes相关容器工作,感兴趣的小伙伴相互…...

前后端分离项目:前端的文件夹应该叫什么名字,后端呢
在前后端分离的项目中,为了提高项目的可读性和易管理性,给前端和后端的文件夹选择合适的名字是很重要的。这里提供一些建议,但请记住,最终的命名应该根据你的团队习惯、项目特性以及可能的公司规定来决定。 ### 前端文件夹命名建…...

2024.2.6
1.现有无序序列数组为23,24,12,5,33,5347,请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用快速排序实现升序排序 函数4:请使用插入排序实现升序排序 #include<stdio.h> #include<string.h&g…...

如何在 Microsoft Azure 上部署和管理 Elastic Stack
作者:来自 Elastic Osman Ishaq Elastic 用户可以从 Azure 门户中查找、部署和管理 Elasticsearch。 此集成提供了简化的入门体验,所有这些都使用你已知的 Azure 门户和工具,因此你可以轻松部署 Elastic,而无需注册外部服务或配置…...

在Visual Studio中引用和链接OpenSceneGraph (OSG) 库
在Visual Studio中引用和链接OpenSceneGraph (OSG) 库,按照以下步骤操作: 构建或安装OSG库 下载OpenSceneGraph源代码(如3.0版本)并解压。使用CMake配置项目,为Visual Studio生成解决方案文件。通常您需要设置CMake中的…...

[缓存] - Redis
0.为什么要使用缓存? 用缓存,主要有两个用途:高性能、高并发。 1. 高性能 尽量使用短key 不要存过大的数据 避免使用keys *:使用SCAN,来代替 在存到Redis之前压缩数据 设置 key 有效期 选择回收策略(maxmemory-policy) 减…...

spring boot和spring cloud项目中配置文件application和bootstrap加载顺序
在前面的文章基础上 https://blog.csdn.net/zlpzlpzyd/article/details/136060312 日志配置 logback-spring.xml <?xml version"1.0" encoding"UTF-8"?> <configuration scan"true" scanPeriod"10000000 seconds" debug…...

AdaBoost算法
Boosting是一种集成学习方法,AdaBoost是Boosting算法中的一种具体实现。 Boosting方法的核心思想在于将多个弱分类器组合成一个强分类器。这些弱分类器通常是简单的模型,比如决策树,它们在训练过程中的错误会被后续的弱分类器所修正。Boosti…...

基于 elasticsearch v8 的 CRUD 操作及测试用例
基于 elasticsearch v8 的 CRUD 操作及测试用例 https://github.com/chenshijian73-qq/go-es/tree/main...

深度学习的新进展:解析技术演进与应用前景
深度学习的新进展:解析技术演进与应用前景 深度学习,作为人工智能领域的一颗璀璨明珠,一直以来都在不断刷新我们对技术和未来的认知。随着时间的推移,深度学习不断迎来新的进展,这不仅推动了技术的演进,也…...

【第二届 Runway短视频创作大赛】——截至日期2024年03月01日
短视频创作大赛 关于AI Film Festival竞赛概况参加资格报名期间报名方法 提交要求奖品附录 关于AI Film Festival 2022年成立的AIFF是一个融合了最新AI技术于电影制作中的艺术和艺术家节日,让我们得以一窥新创意时代的风采。从众多参赛作品中…...