HPA

Posted LI-XY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HPA相关的知识,希望对你有一定的参考价值。

HPA介绍

HPA:全称Horizontal Pod Autoscaler ,对应中文叫Pod的自动水平伸缩;

  • Pod的水平伸缩是水平方向增加/减少Pod的数量;
  • Pod的垂直伸缩则是垂直方向上控制Pod的硬件,比如增加/缩减CPU、内存等资源;
  • Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。
  • Pod 水平自动扩缩特性由 Kubernetes API 资源和控制器实现。资源决定了控制器的行为。
  • 控制器会周期性的调整副本控制器或 Deployment 中的副本数量,以使得 Pod 的平均 CPU 利用率与用户所设定的目标值匹配

k8s的HPA一般会根据一个具体的指标来做,比如常见CPU、内存的负载;也可以根据web服务的吞吐量、单位时间内的传输字节数等;另外还可以根据自定义的指标,比如RabbitMQ的队列数量、Webhook等。

HPA原理

Pod 水平自动扩缩器的实现是一个控制回路,由控制器管理器的 --horizontal-pod-autoscaler-sync-period 参数指定周期(默认值为 15 秒)。

每个周期内,控制器管理器根据每个 HorizontalPodAutoscaler 定义中指定的指标查询资源利用率。 控制器管理器可以从资源度量指标 API(按 Pod 统计的资源用量)和自定义度量指标 API(其他指标)获取度量值。

  • 对于按 Pod 统计的资源指标(如 CPU), 控制器从资源指标 API 中获取每一个 HorizontalPodAutoscaler 指定的 Pod 的度量值,如果设置了目标使用率, 控制器获取每个 Pod 中的容器资源使用情况,并计算资源使用率。 如果设置了 target 值,将直接使用原始数据(不再计算百分比)。 接下来,控制器根据平均的资源使用率或原始值计算出扩缩的比例,进而计算出目标副本数。

  • 需要注意的是,如果 Pod 某些容器不支持资源采集,那么控制器将不会使用该 Pod 的 CPU 使用率。

  • 如果 Pod 使用自定义指示,控制器机制与资源指标类似,区别在于自定义指标只使用 原始值,而不是使用率。

  • 如果 Pod 使用对象指标和外部指标(每个指标描述一个对象信息)。 这个指标将直接根据目标设定值相比较,并生成一个上面提到的扩缩比例。 在 autoscaling/v2beta2 版本 API 中,这个指标也可以根据 Pod 数量平分后再计算。

通常情况下,控制器将从一系列的聚合 API(metrics.k8s.io、custom.metrics.k8s.io 和 external.metrics.k8s.io)中获取度量值。 metrics.k8s.io API 通常由 Metrics 服务器(需要额外启动)提供。

安装metrics-server

官方代码仓库地址:https://github.com/kubernetes-sigs/metrics-server

下载yaml
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml

修改arg:
添加- --kubelet-insecure-tlskubelet 的10250端口使用的是https协议,连接需要验证tls证书,--kubelet-insecure-tls不验证客户端证书。

修改镜像地址:
registry.k8s.io/metrics-server/metrics-server:v0.6.3
修改为
docker.io/dyrnq/metrics-server:v0.6.3

    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls
        image: docker.io/dyrnq/metrics-server:v0.6.3
        imagePullPolicy: IfNotPresent

安装

[root@master hpa]# kubectl apply -f components.yaml 
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
[root@master hpa]# kubectl get pods -n kube-system |grep metrics-server
metrics-server-7b8f8cb648-pkbpt   1/1     Running   0          2m8s
[root@master hpa]# kubectl top nodes
NAME     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master   94m          4%     849Mi           45%       
node1    45m          2%     398Mi           21%       
node2    39m          1%     398Mi           21% 

HPA API对象

[root@master hpa]# kubectl api-versions | grep autoscal
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
API名称 描述
autoscaling/v1 只支持基于CPU指标的缩放
autoscaling/v2beta1 支持Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)的缩放
autoscaling/v2beta2 支持Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)和ExternalMetrics(额外指标)的缩放

HPA 案例演示

基于cpu测试

https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

创建测试镜像

[root@master hpa-example]# cat index.php 
<?php
  $x = 0.0001;
  for ($i = 0; $i <= 1000000; $i++) 
    $x += sqrt($x);
  
  echo "OK!";
?>
[root@master hpa-example]# cat Dockerfile 
FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php
[root@master hpa-example]# docker build -f Dockerfile -t 10.0.0.80:5000/hpa-example:v1 .
[root@master hpa-example]# docker push 10.0.0.80:5000/hpa-example:v1 

部署deployment

[root@master1 ~]# vim php-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      app: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        app: php-apache
    spec:
      containers:
      - name: php-apache
        image: 10.0.0.80:5000/hpa-example:v1 
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
[root@master hpa-example]# kubectl create -f php-apache.yaml
deployment.apps/php-apache created
[root@master hpa-example]# kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   1/1     1            1           47s
[root@master hpa-example]# kubectl get pods  -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
php-apache-fc47b9cd7-khgvt   1/1     Running   0          22m     10.244.1.33   node1   <none>           <none>

创建HPA

方式一:文件创建

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  maxReplicas: 3
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  targetCPUUtilizationPercentage: 50

maxReplicas:pod的最大个数
minReplicas:pod的最少个数
scaleTargetRef:目标作用对象,可以是Deployment、ReplicationController或ReplicaSet。
targetCPUUtilizationPercentage:表示所有Pod的平均CPU使用率维持在50%,超过就要扩容

方式二:命令行创建

[root@master hpa-example]# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=3
[root@master hpa-example]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         3        1          39s

压测

对pod发起请求

while true; do wget -q -O- http://10.244.1.33; done

查看hpa和deploy

[root@master ~]# kubectl get hpa
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   250%/50%   1         3         3          7m31s
[root@master ~]# kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   3/3     3            3           24m

停止压测后,等几分钟后查看hpa和deploy

[root@master hpa]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         3         1          19m
[root@master hpa]# kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   1/1     1            1           36m

基于内存测试

部署deployment

[root@master hpa]# vim nginx-hpa.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hpa
spec:
  selector:
    matchLabels:
      app: nginx-hpa
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-hpa
    spec:
      containers:
      - name: nginx
        image: nginx:1.15-alpine
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        resources:
          requests:
            cpu: 0.01
            memory: 25Mi
          limits:
            cpu: 0.05
            memory: 60Mi
[root@master hpa]# kubectl create -f nginx-hpa.yaml
deployment.apps/nginx-hpa created
[root@master hpa]# kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-hpa    1/1     1            1           37s
php-apache   1/1     1            1           33m
[root@master hpa]# kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
nginx-hpa-b9fb96f5c-qw8sb    1/1     Running   0          63s     10.244.1.36   node1   <none>           <none>
php-apache-fc47b9cd7-khgvt   1/1     Running   0          33m     10.244.1.33   node1   <none>           <none>

创建HPA

[root@master hpa]# vim hpa-mem.yaml 
apiVersion: autoscaling/v2beta1                         # v2beta1版本
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  maxReplicas: 3
  minReplicas: 1       # 1-3个pod范围内扩容与裁剪
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-hpa
  metrics:
  - type: Resource
    resource:
      name: memory
      targetAverageUtilization: 50    # 50%内存利用
[root@master hpa]# kubectl create -f hpa-mem.yaml
horizontalpodautoscaler.autoscaling/nginx-hpa created
[root@master hpa]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa    Deployment/nginx-hpa    12%/50%   1         3        1          95s
php-apache   Deployment/php-apache   0%/50%    1         3         1          19m

压测

进入pod使用dd命令测试

[root@master hpa]# kubectl exec -it nginx-hpa-b9fb96f5c-qw8sb /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # dd if=/dev/zero of=/tmp/file1

查看hpa和deploy

[root@master hpa-example]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa    Deployment/nginx-hpa    63%/50%   1         3         3          12m
php-apache   Deployment/php-apache   0%/50%    1         3         1          30m
[root@master hpa-example]# kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-hpa    3/3     3            3           14m
php-apache   1/1     1            1           46m

停止压测后,等几分钟后查看hpa和deploy

[root@master hpa-example]# kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-hpa    1/1     1            1           16m
php-apache   1/1     1            1           48m
[root@master hpa-example]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa    Deployment/nginx-hpa    12%/50%   1         3         1          14m
php-apache   Deployment/php-apache   0%/50%    1         3         1          32m

为啥 Kubernetes HPA 转换自定义指标?

【中文标题】为啥 Kubernetes HPA 转换自定义指标?【英文标题】:Why Kubernetes HPA convert custom metric?为什么 Kubernetes HPA 转换自定义指标? 【发布时间】:2019-08-16 16:52:37 【问题描述】:

Kubernetes Horisontal Pod Autoscaling (HPA) 修改了我的自定义指标:StackDriver 显示正确的指标,但 HPA 显示另一个数字。 例如,StackDrives 值为 118K,但 HPA 显示 1656144。 我知道 HPA 对浮点数使用了一些对话,但我的指标是整数:单位:数字种类:量规值类型:Int64。

在 GKE 1.11.7 中运行。

有什么想法吗?

【问题讨论】:

嗨@Vitaly,你能分享你的HPA清单吗?默认 HPA 实现为 控制循环,由控制器管理器的 --horizo​​ntal-pod-autoscaler-sync-period 标志控制。这些指标可能取决于对 HPA 算法 有影响的某些字段,例如 targetAverageValuetargetAverageUtilization。这是一般信息kubernetes.io/docs/tasks/run-application/… 请上传您的 HPA 清单。 当然:apiVersion:autoscaling/v2beta1 种类:Horizo​​ntalPodAutoscaler 元数据:名称:myhpa 命名空间:默认规范:scaleTargetRef:apiVersion:apps/v1beta1 种类:部署名称:mydeploy minReplicas:1 maxReplicas:10 指标:-类型:外部外部:metricName:custom.googleapis.com|rabbit_q_size targetValue:10000 【参考方案1】:

如果您指定targetValue,它将是一个整数,因此不会缩小 pod。 如果您使用targetAverageValue,它将根据创建的 pod 数量进行计算。

【讨论】:

【参考方案2】:

在您的 HPA 清单中,您没有指定 --horizontal-pod-autoscaler-sync-period 标志的值。默认情况下,它设置为 15 秒。

在您的情况下,这意味着 HPA 值在过去 15 秒内占整个部署队列的数量。更多信息可以在HPA Documentation 中找到。

正如您在 StackDriver 中提到的,您使用 GAUGE 指标来衡量特定时间点的值 - Stackdriver

简而言之,StackDriver 显示准确时间的当前值,HPA 值是最近 15 秒的量。

【讨论】:

>HPA 值是最后 15 秒的量我不确定我是否理解你。 您的 HPA 从整个部署中收集信息。由于 TargetValue 为 10000,当 RabbitMQ 队列达到此值时,HPA 将创建另一个 pod。 HPA 的值将是过去 15 秒内收到的所有 pod 的所有消息的总和。这就是为什么 StackDriver 在您检查值的那一刻有 118k 条消息,而 HPA 有 160 万条消息,因为它是过去 15 秒内所有部署消息的总和。 我不这么认为。在我的例子中,我使用了来自独立 RabbitMQ 服务器的自定义指标。

以上是关于HPA的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Kubernetes HPA 转换自定义指标?

云原生之kubernetes实战kubernetes集群的HPA弹性伸缩

K8S集群基于heapster的HPA测试

用heapster实现HPA

HPA

Kubernetes(k8s)之HPA