k8s学习笔记-HPA控制器

Horizontal Pod Autoscaling,简称HPA,是Kubernetes中实现POD水平自动伸缩的功能。为什么要水平而不叫垂直, 那是因为自动扩展主要分为两种:

水平扩展(scale out),针对于实例数目的增减
垂直扩展(scal up),即单个实例可以使用的资源的增减, 比如增加cpu和增大内存
而HPA属于前者。它可以根据CPU使用率或应用自定义metrics自动扩展Pod数量(支持 replication controller、deployment 和 replica set)

对于Kubernetes中的POD集群来说,HPA就是实现这种水平伸缩的控制器, 它能在当POD中业务负载上升的时候,创建新的POD来保证业务系统稳定运行,当POD中业务负载下降的时候,可以销毁POD来提高资源利用率。

自动伸缩是一种根据资源使用情况自动伸缩工作负载的方法。
自动伸缩在Kubernetes中有两个维度:cluster Autoscaler处理节点扩容操作和Horizontal Pod Autoscaler自动缩放rs或rc中的pod。
cluster Autoscaler和Horizontal Pod Autoscaler一起可用于动态调整的计算能力以及并行性的水平,你的系统需要满足sla。
虽然cluster Autoscaler高度依赖于托管集群的云提供商的底层功能,但是HPA可以独立于您的IaaS/PaaS提供商进行操作。

在Kubernetes v1.1中首次引入了hpa特性,自那时起已经有了很大的发展。
hpa第一个版本基于观察到的CPU利用率,后续版本支持基于内存使用。
在Kubernetes 1.6中引入了一个新的API自定义指标API,它允许HPA访问任意指标。
Kubernetes 1.7引入了聚合层,允许第三方应用程序通过注册为API附加组件来扩展Kubernetes API。
自定义指标API以及聚合层使得像Prometheus这样的监控系统可以向HPA控制器公开特定于应用程序的指标。

如下图:

HPA 实现了一个控制环,可以周期性的从资源指标API查询特定应用的CPU/MEM信息。

HPA自身是一个控制循环,周期由 controller-manager的 --horizontal-pod-autoscaler-sync-period选项定义,默认为30s

获取metrics的两种方式:

Heapster: heapster提供metrics服务, 但是在v1(autoscaling/v1)版本中仅支持以CPU作为扩展度量指标, 而其他比如:内存, 网络流量, qps等目前处于beta阶段(autoscaling/v2beta1)
Cousom: 同样处于beta阶段(autoscaling/v2beta1), 但是涉及到自定义的REST API的开发, 复杂度会大一些, 并且当需要从自定义的监控中获取数据时,只能设置绝对值,无法设置使用率

工作流程:

1.创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数, 一定要设置Pod的资源限制参数: request, 否则HPA不会工作。
2.控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
3.然后与创建时设定的值和指标做对比(平均值之和/限额),求出目标调整的实例个数
4.目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数
然后就是重复2-4步
自动伸缩算法:
HPA Controller会通过调整副本数量使得CPU使用率尽量向期望值靠近,而且不是完全相等.另外,官方考虑到自动扩展的决策可能需要一段时间才会生效:例如当pod所需要的CPU负荷过大,从而在创建一个新pod的过程中,系统的CPU使用量可能会同样在有一个攀升的过程。所以,在每一次作出决策后的一段时间内,将不再进行扩展决策。对于扩容而言,这个时间段为3分钟,缩容为5分钟(可以通过--horizontal-pod-autoscaler-downscale-delay, --horizontal-pod-autoscaler-upscale-delay进行调整)。

HPA Controller中有一个tolerance(容忍力)的概念,它允许一定范围内的使用量的不稳定,现在默认为0.1,这也是出于维护系统稳定性的考虑。例如,设定HPA调度策略为cpu使用率高于50%触发扩容,那么只有当使用率大于55%或者小于45%才会触发伸缩活动,HPA会尽力把Pod的使用率控制在这个范围之间。
具体的每次扩容或者缩容的多少Pod的算法为:

Ceil(前采集到的使用率 / 用户自定义的使用率) * Pod数量)
每次最大扩容pod数量不会超过当前副本数量的2倍

Kubernetes Metrics Server是一个集群范围的资源使用数据聚合器,是Heapster的继承者。
metrics服务器通过从kubernet.summary_api收集数据收集节点和pod的CPU和内存使用情况。
summary API是一个内存有效的API,用于将数据从Kubelet/cAdvisor传递到metrics server。

HPA,Horizontal Pod Autoscaler,两个版本,HPA仅支持CPU指标;HPAv2支持资源指标API和自定义指标API
CA,Cluster Autoscaler,集群规模自动弹性伸缩,能自动增减节点数量,用于云环境
VPA,Vertical Pod Autoscaler,Pod应用垂直伸缩工具,调整Pod对象的CPU和内存资源需求量完成扩展或收缩
AR,Addon Resizer,简化版本的Pod应用垂直伸缩工具,基于集群中节点数量调整附加组件的资源需求量


对于未定义资源需求量的Pod对象,HPA控制器无法定义容器CPU利用率,且不会为该指标采取任何操作
对于每个Pod的自定义指标,HPA仅能处理原始值而非利用率

默认缩容延迟时长为5min,扩容延迟时长为3min,目的是防止出现抖动

HPA获取指标的方式:Heapster和REST客户端
Heapster要事先部署于集群上并在kube-system名称空间运行
事先部署好资源指标API及其API Server,必要时,还要部署好自定义指标API及其相关的API Server

参考的文章:

https://www.codercto.com/a/29478.html

下面演示HPA 的两个版本

autoscaling/v1           HPA

HPA(v1)控制器:

1.创建 deployment及service

kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=2 --requests='cpu=50m,memory=256Mi' --limits='cpu=50m,memory=256Mi' --labels='app=myapp' --expose --port=80

2.创建hpa控制器

kubectl autoscale -h
kubectl autoscale deployment myapp --min=2 --max=8 --cpu-percent=60
[root@k8s-master k8s]# kubectl get hpa|egep myapp
myapp Deployment/myapp 0%/60% 2 8 2 35s

3.开放服务端口
kubectl patch svc myapp -p '{"spec":{"type":"NodePort"}}'

4.客户端压力测试
Mac@~ $ab -c 100 -n 500000 http://10.211.55.11:30127/

5.看到扩容了3个POD
[root@k8s-master ~]# kubectl get hpa
NAME            REFERENCE             TARGETS                     MINPODS    MAXPODS         REPLICAS      AGE
myapp            Deployment/myapp    102%/60%                      2                 8                      4            4m54s

6.查看Pod

[root@k8s-master ~]# kubectl get pods |egrep myapp
myapp-64bf6764c5-b2kmr 1/1 Running 0 7m51s
myapp-64bf6764c5-b59nw 1/1 Running 0 19s
myapp-64bf6764c5-cbjfw 1/1 Running 0 19s
myapp-64bf6764c5-mhc9d 1/1 Running 0 79s

7.查看详细的信息
[root@k8s-master ~]# kubectl describe hpa

........
resource cpu on pods (as a percentage of request): 13% (6m) / 60%
Min replicas: 1
Max replicas: 8
Deployment pods: 4 current / 4 desired

.........

8.可以查看时时的yaml 文件

kubectl get hpa -o yaml --export

 

autoscaling/v2beta1  HPAv2

HPA(v2)控制器
HPA(v2)支持从metrics-server中请求核心指标;从k8s-prometheus-adapter一类自定义API中获取自定义指标数据
多个指标计算时,结果中数值较大的胜出

1.删除之前的hpa
kubectl delete hpa myapp

2.配置核心API 的HPA

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
    name: myapp-hpa-v1
spec:
   scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: myapp
   minReplicas: 2
   maxReplicas: 10
   metrics:
   -  type: Resource
       resource:
          name: cpu
          targetAverageUtilization: 55
  -  type: Resource
      resource:
         name: memory
         targetAverageValue: 100Mi

scaleTargetRef: 要缩放的目标资源

metrics:计算所需Pod副本数量的指标列表,每个指标单独计算,取所有计算结果的最大值作为最终副本数量
- external,引用非附属于任何对象的全局指标,可以是集群之外的组件的指标数据,如消息队列长度
- object,引用描述集群中某单一对象的特定指标,如Ingress对象上的hits-per-second等
- pods,引用当前被弹性伸缩的Pod对象的特定指标
- resource,引用资源指标,即当前被弹性伸缩的Pod对象中容器的requests和limits中定义的指标
- type,指标源的类型,可为Objects、Pods、Resource

3.压力测试

Mac@~ $ab -c 100 -n 500000 http://10.211.55.11:30127/

4.查看HPA的信息
[root@k8s-master k8s]# kubectl get hpa
[root@k8s-master ~]# kubectl describe hpa

[root@k8s-master ~]#kubectl get hpa -o yaml --export
5.配置自定义api需要的环境

apiVersion: apps/v1

kind: Deployment
metadata:
  labels:
    app: metrics-app
  name: metrics-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: metrics-app
  template:
    metadata:
      labels:
        app: metrics-app
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
        prometheus.io/path: "/metrics"
    spec:
      containers:
      - image: ikubernetes/metrics-app
        name: metrics-app
        ports:
        - name: web
          containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: metrics-app
  labels:
    app: metrics-app
spec:
  ports:
  - name: web
    port: 80
    targetPort: 80
  selector:
    app: metrics-app
  type: NodePort

 1.ikubernetes/metrics-app 运行时会通过 /metrics路径输出 http_requests_total 和 http_requests_per_second 两个指标
 2.注释 prometheus.io/scrape:"true" 使Pod对象能够被 Promethues采集相关指标 

 3.Prometheus通过服务发现机制发现新创建的Pod对象,根据注释提供的配置信息识别指标并纳入采集对象,而后由k8s-prometheus-adapter将这些指标注册到自定义API中,提供给HPA(v2)控制器和调度器等作为调度评估参数使用

[root@k8s-master ~]# kubectl get pods |egrep metrics
metrics-app-6695bdf47b-gvtzf 1/1 Running 0 4h22m
metrics-app-6695bdf47b-rlng4 1/1 Running 0 4h22m

6.测试自定义的这个API 信息

[root@k8s-master ~]# kubectl get svc |egrep metrics
metrics-app NodePort 10.104.193.140 <none> 80:32556/TCP 4h25m

 

7.配置自定义api的HPA(添加自定义指标 http_requests_per_second)

apiVersion: autoscaling/v2beta1

kind: HorizontalPodAutoscaler
metadata:
  name: metrics-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: metrics-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metricName: http_requests_per_second
      targetAverageValue: 800m # 400m 即0.4个/秒

8.添加规则: 

将prometheus指标升级为k8s自定义指标,需要定义规则

vim k8s-prometheus-adapter/deploy/manifests/custom-metrics-config-map.yaml 
 - seriesQuery: 'http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}'

      resources:
        overrides:
          kubernetes_namespace: {resource: "namespace"}
          kubernetes_pod_name: {resource: "pod"}
      name:
        matches: "^(.*)_total"
        as: "${1}_per_second"
      metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
自定义规则参考文档:
1.https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/config-walkthrough.md
2.https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/walkthrough.md
注意:修改config-map后,不删除Pod,不会生效
9.压力测试
这是一个大家在OpenStack测试非常喜欢使用的镜像,小于15M,测试起来非常方便
kubectl run client -it --image=cirros --rm -- /bin/sh
#while true; do curl http://metrics-app; let i++; sleep 0.$RANDOM; done   # 模拟压力
$RANDOM 系统变量,随机生成一个数字
测试需要达到数分钟后才能看到自动扩容,原因是:默认缩容延迟时长为5min,扩容延迟时长为3min
10.查看相关的HPA和扩容状态
[root@k8s-master k8s]# kubectl get pods -w

kubectl  get hpa

 

 [root@k8s-master k8s]# kubectl  get hpa -o yaml 

 

还可以参考下面文章做相应的测试

https://www.jianshu.com/p/9abb697cd833

总结

不是所有的系统都可以依靠CPU/内存使用指标单独满足SLA,大多数Web和移动后端需要以每秒请求处理任何突发流量进行自动缩放。
对于ETL应用程序,可能会由于作业队列长度超过某个阈值而触发自动缩放,等等。
通过prometheus检测你应用程序的正确指标,并为自动伸缩提供正确指标,您可以微调您的应用程序更好地处理突发和确保高可用性。

 

posted @ 2019-05-27 17:23  屌丝的IT  阅读(1794)  评论(0)    收藏  举报