必威体育Betway必威体育官网
当前位置:首页 > IT技术

如何利用kubernetes实现应用的水平扩展(HPA)

时间:2019-06-11 09:45:21来源:IT技术作者:seo实验室小编阅读:53次「手机版」
 

hpa

云计算具有水平弹性的特性,这个是云计算区别于传统IT技术架构的主要特性。对于Kubernetes中的POD集群来说,HPA就是实现这种水平伸缩的控制器, 它能在当POD中业务负载上升的时候,创建新的POD来保证业务系统稳定运行,当POD中业务负载下降的时候,可以销毁POD来提高资源利用率。

HPA介绍

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

  • 水平扩展(scale out),针对于实例数目的增减
  • 垂直扩展(scal up),即单个实例可以使用的资源的增减, 比如增加cpu和增大内存

    而HPA属于前者。它可以根据CPU使用率或应用自定义metrics自动扩展Pod数量(支持 replication controller、deployment 和 replica set)

架构介绍

获取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倍

依赖部署

这是kuberntes整个系列的第四篇, 该篇依赖Heapster服务成功安装, 如果未安装请参考:

  • 企业级Docker镜像仓库harbor的部署和使用
  • kubernetes 1.8.7 离线部署手册(一)
  • kubernetes 1.8.7 离线部署手册(二)

因为基于HeapsterHPA仅支持CPU为维度的自动伸缩, 因此写了个计算100位π的HTTP服务, 该程序已打包放于百度网盘下, 下载hpa-test-app.tar 导入然后推到自己私有仓库, 等待后续测试(放心该镜像仅有5M多点)

源代码如下:

package main

import (
    "fmt"
    "log"
    "net/http"
    "strconv"
    "strings"
)

func main() {
    http.HandleFunc("/", compPiHandler)
    log.Println("Server work at :8080 ...")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func compPiHandler(w http.ResponseWriter, r *http.Request) {
    var (
        lenI int
        err  error
    )

    lenS := r.URL.Query().Get("length")
    if lenS != "" {
        lenI, err = strconv.Atoi(lenS)
        if err != nil {
            lenI = 100
        }
    } else {
        lenI = 100
    }

    fmt.Fprintf(w, compPi(lenI))
}

func compPi(L int) string {
    var Pi []string

    N := (L)/4 + 1

    s := make([]int, N+3)
    w := make([]int, N+3)
    v := make([]int, N+3)
    q := make([]int, N+3)
    n := (int)(float32(L)/1.39793 + 1)

    w[0] = 16 * 5
    v[0] = 4 * 239

    for k := 1; k <= n; k++ {
        p(w, 25, w, N)
        p(v, 57121, v, N)
        sub(w, v, q, N)
        p(q, 2*k-1, q, N)
        if k%2 != 0 {
            add(s, q, s, N)
        } else {
            sub(s, q, s, N)
        }
    }

    Pi = append(Pi, fmt.Sprintf("%d.", s[0]))

    for k := 1; k < N; k++ {
        Pi = append(Pi, fmt.Sprintf("%04d", s[k]))
    }

    return strings.Join(Pi, "")
}

func add(a []int, b []int, c []int, N int) {
    i, carry := 0, 0
    for i = N + 1; i >= 0; i-- {
        c[i] = a[i] + b[i] + carry
        if c[i] < 10000 {
            carry = 0
        } else {
            c[i] = c[i] - 10000
            carry = 1
        }
    }
}

func sub(a []int, b []int, c []int, N int) {
    i, borrow := 0, 0
    for i = N + 1; i >= 0; i-- {
        c[i] = a[i] - b[i] - borrow
        if c[i] >= 0 {
            borrow = 0
        } else {
            c[i] = c[i] + 10000
            borrow = 1
        }
    }
}

func p(a []int, b int, c []int, N int) {
    i, tmp, remain := 0, 0, 0
    for i = 0; i <= N+1; i++ {
        tmp = a[i] + remain
        c[i] = tmp / b
        remain = (tmp % b) * 10000
    }
}

服务测试

基于上面提供的hpa-test-app镜像, 我们创建一个hpa-test-app service, 然后为该service添加HPA机制。

注意事项:

  • 当Pod没有设置request时,HPA不会工作。

创建Deployment

注意根据需要修改自己的镜像地址

cat << EOF > hpa-test-app-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hpa-test-app-deploy
  labels:
    app: hpa
    version: v0.0.1
spec:
  replicas: 1
  selector:
    matchLabels:
      name: hpa-test-app-deploy
      app: hpa
      version: v0.0.1
  template:
    metadata:
      labels:
        name: hpa-test-app-deploy
        app: hpa
        version: v0.0.1
    spec:
      containers:
      - name: hpa-test-app-deploy
        image: 192.168.204.15/kubernetes/hpa-test-app:v0.0.1
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        resources:
          requests:
            cpu: 0.006
            memory: 32Mi
          limits:
            cpu: 0.06
            memory: 128Mi
EOF
kubectl create -f hpa-test-app-deploy.yaml

创建service

cat << EOF > hpa-test-app-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: hpa-test-app-svc
  labels:
    app: hpa
    version: v0.0.1
spec:
  selector:
    name: hpa-test-app-deploy
    app: hpa
    version: v0.0.1
  ports:
  - name: http
    port: 8080
    protocol: TCP
EOF
kubectl create -f hpa-test-app-svc.yaml

创建HPA

cat << EOF > hpa-test-app-hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-test-app-hpa
  labels:
    app: hpa
    version: v0.0.1
spec:
  scaleTargetRef:
    apiVersion: v1
    kind: Deployment
    name: hpa-test-app-deploy
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70
EOF
kubectl create -f hpa-test-app-hpa.yaml

检查服务

[root@k8s-apiserver01 hpa-test]# kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
hpa-test-app-deploy-69dbc4cf84-5jvb6   1/1       Running   0          23s
[root@k8s-apiserver01 hpa-test]# kubectl logs hpa-test-app-deploy-69dbc4cf84-5jvb6
2018/02/05 05:13:14 Server work at :8080 ...
[root@k8s-apiserver01 hpa-test]# kubectl get hpa
NAME               REFERENCE                        TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
hpa-test-app-hpa   Deployment/hpa-test-app-deploy   0% / 70%   1         10        1          38s

增压和减压测试

首先我们启动一个busybox的pod, 用来对hap-test-app服务进行压力测试

cat << EOF > pod-busybox.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
EOF
kubectl create -f pod-busybox.yaml

然后我们找到hpa-test-app服务的clusterIP:

[root@k8s-apiserver01 apps]# kubectl get svc hpa-test-app-svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
hpa-test-app-svc   ClusterIP   10.254.155.132   <none>        8080/TCP   1m

应用扩张

进入容器, 持续访问hpa-test-app的API(默认计算100位的π, 如果想加大计算可以通过query string: ?length=1000来增大单个请求对cpu的压力),

kubectl exec -it busybox /bin/sh
/ # while true; do wget -q -O-  10.254.155.132:8080; done

然后我们持续关系HPA的扩张

[root@k8s-apiserver01 ~]# kubectl get hpa
NAME               REFERENCE                        TARGETS      MINPODS   MAXPODS   REPLICAS   AGE
hpa-test-app-hpa   Deployment/hpa-test-app-deploy   345% / 70%   1         10        4          52m
[root@k8s-apiserver01 ~]# kubectl get hpa
NAME               REFERENCE                        TARGETS      MINPODS   MAXPODS   REPLICAS   AGE
hpa-test-app-hpa   Deployment/hpa-test-app-deploy   287% / 70%   1         10        8          56m
[root@k8s-apiserver01 ~]# kubectl get hpa
NAME               REFERENCE                        TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
hpa-test-app-hpa   Deployment/hpa-test-app-deploy   0% / 70%   1         10        10         1h

pod数量的变化情况 1–>2–>4–>8–>10, 最终达到最大的扩展上线而停止.

应用收缩

中断对app的访问, 会发现容器又收缩为原来的1个:

[root@k8s-apiserver01 ~]# kubectl get hpa
NAME               REFERENCE                        TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
hpa-test-app-hpa   Deployment/hpa-test-app-deploy   0% / 70%   1         10        1          1h
[root@k8s-apiserver01 ~]# kubectl describe  hpa hpa-test-app-hpa
Name:                                                  hpa-test-app-hpa
Namespace:                                             default
Labels:                                                app=hpa
                                                       version=v0.0.1
Annotations:                                           <none>
CreationTimestamp:                                     Mon, 05 Feb 2018 00:47:31 -0500
Reference:                                             Deployment/hpa-test-app-deploy
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  0% (0) / 70%
Min replicas:                                          1
Max replicas:                                          10
Conditions:
  Type            Status  Reason            Message
  ----            ------  ------            -------
  AbleToScale     True    ReadyForNewScale  the last scale time was sufficiently old as to warrant a new scale
  ScalingActive   True    ValidMetricFound  the HPA was able to succesfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  True    TooFewReplicas    the desired replica count was less than the minimum replica count
Events:
  Type     Reason                   Age                From                       Message
  ----     ------                   ----               ----                       -------
  Warning  FailedGetResourceMetric  46m (x57 over 1h)  horizontal-pod-autoscaler  missing request for cpu on container hpa-test-app-deploy in pod default/hpa-test-app-deploy-75b4fd6cf6-sf78p
  Normal   SuccessfulRescale        41m (x2 over 1h)   horizontal-pod-autoscaler  New size: 4; reason: cpu resource utilization (percentage of request) above target
  Normal   SuccessfulRescale        33m                horizontal-pod-autoscaler  New size: 10; reason: cpu resource utilization (percentage of request) above target
  Normal   SuccessfulRescale        28m                horizontal-pod-autoscaler  New size: 1; reason: All metrics below target

总结

本文主要介绍了HPA的相关原理和使用方法,此功能可以能对服务的容器数量做自动伸缩,对于服务的稳定性是一个很好的提升。但是当前稳定版本中只有cpu使用率这一个指标,是一个很大的弊端。但是kubernetes中关于HPA的架子已经成熟, 期待v2进入stable, 到时候HPA才能爆发它正在的魅力。

参考

  • Kubernetes Horizontal Pod Autoscaler
  • Kubernetes 中Pod弹性伸缩详解与使用

相关阅读

查找——平衡二叉树的实现(代码超详细注释)

既然你搜索到了这篇文章,那么平衡二叉树的作用想必心中已经清楚了,我们接下来就直接来谈谈代码... 目录 知识准备   进阶讲解 

CNN应用之SPP(基于空间金字塔池化的卷积神经网络物体检

基于空间金字塔池化的卷积神经网络物体检测原文地址:http://blog.csdn.net/hjimce/article/details/50187655作者:hjimce一、相关理

jeesite应用实战(数据增删改查),认真读完后10分钟就能开

原文地址: https://blog.csdn.net/qing_gee/article/details/76223064jeesite配置指南(官方文档有坑,我把坑填了!)这篇文章里,我主要

touchpad

来谈一谈有关touchpad的问题吧~这断时间触摸板总是无法用热键启用和关闭,之前一直忙别的事情(其实就是懒。。。)放着没管,但是触版启

显示文件扩展名

分享到:

栏目导航

推荐阅读

热门阅读