HPA-VPA-KPA实现自动扩容

1、自动(弹性)扩缩容背景分析

背景:

弹性伸缩是根据用户的业务需求和策略,自动“调整”其“弹性资源”的管理服务。通过弹性伸缩功能,用户可设置定时、周期或监控策略,恰到好处地增加或减少“弹性资源”,并完成实例配置,保证业务平稳健康运行

 

在实际工作中,我们常常需要做一些扩容缩容操作,如:电商平台在618和双十一搞秒杀活动;由于资源紧张、工作负载降低等都需要对服务实例数进行扩缩容操作。

 

在k8s中扩缩容分为两种:

 

1、Node层面:

对K8s物理节点扩容和缩容,根据业务规模实现物理节点自动扩缩容

 

2、Pod层面:

我们一般会使用Deployment中的replicas参数,设置多个副本集来保证服务的高可用,但是这是一个固定的值,比如我们设置10个副本,就会启10个pod 同时running来提供服务。如果这个服务平时流量很少的时候,也是10个pod同时在running,而流量突然暴增时,又可能出现10个pod不够用的情况。针对这种情况怎么办?就需要扩容和缩容

2、k8s中自动伸缩的方案

2.1、HPA

Kubernetes HPA(Horizontal Pod Autoscaling):Pod水平自动伸缩

 

通过此功能,只需简单的配置,便可以利用监控指标(cpu使用率、磁盘、自定义的等)自动的扩容或缩容服务中Pod数量,当业务需求增加时,系统将无缝地自动增加适量pod容器,提高系统稳定性。

 

要想实现自动扩缩容,需要先考虑如下几点:

 

1.通过哪些指标决定扩缩容?

HPA v1版本可以根据CPU使用率来进行自动扩缩容:

但是并非所有的系统都可以仅依靠CPU或者Memory指标来扩容,对于大多数 Web 应用的后端来说,基于每秒的请求数量进行弹性伸缩来处理突发流量会更加的靠谱,所以对于一个自动扩缩容系统来说,我们不能局限于CPU、Memory基础监控数据,每秒请求数RPS等自定义指标也是十分重要。

 

HPA v2版本可以根据自定义的指标进行自动扩缩容

 

注意:hpa v1只能基于cpu做扩容所用

      hpa v2可以基于内存和自定义的指标做扩容和缩容

 

 

2.如何采集资源指标?

如果我们的系统默认依赖Prometheus,自定义的Metrics指标则可以从各种数据源或者exporter中获取,基于拉模型的Prometheus会定期从数据源中拉取数据。 也可以基于metrics-server自动获取节点和pod的资源指标

 

3.如何实现自动扩缩容?

K8s的HPA controller已经实现了一套简单的自动扩缩容逻辑,默认情况下,每30s检测一次指标,只要检测到了配置HPA的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在5min内没有重新扩缩容的情况下,才会触发扩缩容。 HPA本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果正处在5min内的HPA稳定期,这个时候根据HPA的策略,会导致无法扩容。

2.2、KPA

KPA(Knative Pod Autoscaler)基于请求数对Pod自动扩缩容,KPA 的主要限制在于它不支持基于 CPU 的自动扩缩容。

 

1、根据并发请求数实现自动扩缩容

2、设置扩缩容边界实现自动扩缩容

 

扩缩容边界指应用程序提供服务的最小和最大Pod数量。通过设置应用程序提供服务的最小和最大Pod数量实现自动扩缩容。

相比HPA,KPA会考虑更多的场景,其中一个比较重要的是流量突发的时候。

2.3、VPA

kubernetes VPA(Vertical Pod Autoscaler),垂直 Pod 自动扩缩容,VPA会基于Pod的资源使用情况自动为集群设置资源占用的限制,从而让集群将Pod调度到有足够资源的最佳节点上。VPA也会保持最初容器定义中资源request和limit的占比。

它会根据容器资源使用率自动设置pod的CPU和内存的requests,从而允许在节点上进行适当的调度,以便为每个 Pod 提供适当的可用的节点。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源不足的容量。

3、利用HPA基于CPU指标实现pod自动扩缩容

HPA全称是Horizontal Pod Autoscaler,翻译成中文是POD水平自动伸缩, HPA可以基于CPU利用率对deployment中的pod数量进行自动扩缩容(除了CPU也可以基于自定义的指标进行自动扩缩容)。pod自动缩放不适用于无法缩放的对象,比如DaemonSets。

HPA由Kubernetes API资源和控制器实现。控制器会周期性的获取平均CPU利用率,并与目标值相比较后调整deployment中的副本数量。

3.1 HPA工作原理

HPA-VPA-KPA实现自动扩容

 

HPA是根据指标来进行自动伸缩的,目前HPA有两个版本–v1和v2beta

 

HPA的API有三个版本,通过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:

1、Metrics server是K8S集群资源使用情况的聚合器

2、从1.8版本开始,Metrics server可以通过yaml文件的方式进行部署

3、Metrics server收集所有node节点的metrics信息

 

HPA如何运作?

 

HPA的实现是一个控制循环,由controller manager的--horizontal-pod-autoscaler-sync-period参数指定周期(默认值为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

 

流程:

  • 1、创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数
  • 2、收集一组中(PodSelector)每个Pod最近一分钟内的CPU使用率,并计算平均值
  • 3、读取HPA中设定的CPU使用限额
  • 4、计算:平均值之和/限额,求出目标调整的实例个数
  • 5、目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数
  • 6、回到2,不断循环

 

自定义指标:

1.PA V2版本已经支持custom Metrics自定义指标。 Custom Metrics其实只是一个Kubernetes的接口,实际Metrics数据的提供,需要额外的扩展实现,可以自己写一个(参考:https://github.com/kubernetes-sigs/custom-Metrics-apiserver)或者使用开源的Prometheus adapter。如果自己实现custom-Metrics,可以自定义各种Metrics指标,使用Prometheus adapter则可以使用Prometheus中现有的一些指标数据。

2. 如何采集Metrics数据 如果我们的系统默认依赖Prometheus,自定义的Metrics指标则可以从各种数据源或者exporter中获取,基于拉模型的Prometheus会定期从数据源中拉取数据。 假设我们优先采用RPS指标作为系统的默认Metrics数据,可以考虑从网关采集或者使用注入Envoy sidecar等方式获取工作负载的流量指标。

3. 如何自动扩缩容 K8s的HPA controller已经实现了一套简单的自动扩缩容逻辑,默认情况下,每30s检测一次指标,只要检测到了配置HPA的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在5min内没有重新扩缩容的情况下,才会触发扩缩容。 不过,HPA本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果正处在5min内的HPA稳定期,这个时候根据HPA的策略,会导致无法扩容。 另外,在一些Serverless场景下,有缩容到0然后冷启动的需求,但HPA默认不支持。

关于HPA支持缩容至0的讨论,可以参考issues(https://github.com/kubernetes/kubernetes/issues/69687),该PR(https://github.com/kubernetes/kubernetes/pull/74526)已经被merge,后面的版本可以通过featureGate设置开启,不过该功能是否应该由K8s本身去实现,社区仍然存在一些争议。

如果我们的系统要实现支持缩容至0和冷启动的功能,并在生产环境真正可用的话,则需要考虑更多的细节。例如HPA是定时拉取Metrics数据再决定是否扩容,但这个时间间隔即使改成1s的话,对于冷启动来说还是太长,需要类似推送的机制才能避免延迟。

总结一下,如果基于现有的HPA来实现一套Serverless自动扩缩容系统,并且默认使用流量作为扩缩容指标,大致需要:

  1. 考虑使用网关等流量入口来实现流量Metrics的指标检测,并暴露出接口,供Prometheus或者自研组件来采集。
  2. 使用Prometheus adapter或者自研Custom Metrics的K8s接口实现,使得HPA controller可以获取到具体的Metrics数据。

这样便可以直接使用HPA的功能,实现了一个最简单的自动扩缩容系统。但是,仍然存在一些问题,比较棘手的是:

    • HPA无法缩容至0,也无法实现工作负载的冷启动。
    • HPA的扩容算法不一定适用流量突发场景,存在一定的隐患。

 http://dockerone.com/article/1943252 https://blog.51cto.com/u_15077560/2584796

3.2 安装数据采集组件metrics-server

metrics-server是一个集群范围内的资源数据集和工具,同样的,metrics-server也只是显示数据,并不提供数据存储服务,主要关注的是资源度量API的实现,比如CPU、文件描述符、内存、请求延时等指标,metric-server收集数据给k8s集群内使用,如kubectl,hpa,scheduler等

1.部署metrics-server组件

#通过离线方式获取镜像
需要的镜像是:k8s.gcr.io/metrics-server-amd64:v0.3.6和k8s.gcr.io/addon-resizer:1.8.4
镜像所在地址在课件,可自行下载,如果大家机器不能访问外部网络,可以把镜像上传到k8s的各个节点,按如下方法手动解压:
docker load -i metrics-server-amd64-0-3-6.tar.gz
docker load -i addon.tar.gz
#部署metrics-server服务
#在/etc/kubernetes/manifests里面改一下apiserver的配置
注意:这个是k8s在1.7的新特性,如果是1.16版本的可以不用添加,1.17以后要添加。这个参数的作用是Aggregation允许在不修改Kubernetes核心代码的同时扩展Kubernetes API。
#二进制安装master节点需要部署kubelet服务 ,能够访问到metrics-service pod-ip。
[root@xianchaomaster1 ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
增加如下内容:
- --enable-aggregator-routing=true

HPA-VPA-KPA实现自动扩容

重新更新apiserver配置:
[root@xianchaomaster1 ~]# kubectl apply -f  /etc/kubernetes/manifests/kube-apiserver.yaml
[root@xianchaomaster1 ~]# kubectl apply -f metrics.yaml     
#验证metrics-server是否部署成功
[root@xianchaomaster1 ~]# kubectl get pods -n kube-system | grep metrics
metrics-server-6595f875d6-ml5pc            2/2     Running            0
#测试kubectl top命令
[root@xianchaomaster1 ~]# kubectl top nodes
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%         
xianchaomaster1   673m         11%    2518Mi          44%       
xianchaonode1   286m         4%     1305Mi          22%

[root@xianchaomaster1 ~]# kubectl top pods -n kube-system
NAME                                       CPU(cores)   MEMORY(bytes)   
calico-kube-controllers-6949477b58-xbt82   3m           13Mi            
calico-node-4t7bs                          118m         55Mi            
calico-node-hbx75                          105m         88Mi            

3.3 创建php-apache服务,利用HPA进行自动扩缩容。

#基于dockerfile构建一个PHP-apache项目
1)创建并运行一个php-apache服务
使用dockerfile构建一个新的镜像,在k8s的xianchaomaster1节点构建
[root@xianchaomaster1 ~]# mkdir php
[root@xianchaomaster1 ~]# cd php/
[root@xianchaomaster1 ~]# docker load -i php.tar.gz
[root@xianchaomaster1 php]# cat dockerfile 
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php
[root@xianchaomaster1 php]# cat index.php 
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000;$i++) {
$x += sqrt($x);
  }
 echo "OK!";
?>
#构建镜像
[root@xianchaomaster1 php]# docker build -t xianchao/hpa-example:v1 .
#打包镜像
[root@xianchaomaster1 php]# docker save -o hpa-example.tar.gz xianchao/hpa-example:v1
[root@xianchaomaster1 php]# scp hpa-example.tar.gz xianchaonode1:/root/

#解压镜像
可以把镜像传到k8s的各个工作节点,通过docker load -i hpa-example.tar.gz进行解压:
[root@xianchaonode1 ~]# docker load -i hpa-example.tar.gz

#通过deployment部署一个php-apache服务

[root@xianchaomaster1 ~]# cat php-apache.yaml 
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: xianchao/hpa-example:v1
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
    name: php-apache
    labels:
      run: php-apache
spec:
  ports:
  - port: 80
  selector:
   run: php-apache
#更新资源清单文件
[root@xianchaomaster1 ~]# kubectl apply -f php-apache.yaml 
deployment.apps/php-apache created
service/php-apache created
#验证php是否部署成功
[root@xianchaomaster1 ~]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
php-apache-7d8fdb687c-bq8c7   1/1     Running    0            31s

3.4 创建HPA

php-apache服务正在运行,使用kubectl autoscale创建自动缩放器,实现对php-apache这个deployment创建的pod自动扩缩容,下面的命令将会创建一个HPA,HPA将会根据CPU,内存等资源指标增加或减少副本数,创建一个可以实现如下目的的hpa:

1)让副本数维持在1-10个之间(这里副本数指的是通过deployment部署的pod的副本数)

2)将所有Pod的平均CPU使用率维持在50%(通过kubectl top看到的每个pod如果是200毫核,这意味着平均CPU利用率为100毫核)

#给上面php-apache这个deployment创建HPA

[root@xianchaomaster1 ~]# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
kubectl autoscale deployment php-apache (php-apache表示deployment的名字) --cpu-percent=50(表示cpu使用率不超过50%) --min=1(最少一个pod) 
--max=10(最多10个pod)

#验证HPA是否创建成功

[root@xianchaomaster1 ~]# kubectl get hpa     

HPA-VPA-KPA实现自动扩容

 

 

 

注:由于我们没有向服务器发送任何请求,因此当前CPU消耗为0%(TARGET列显示了由相应的deployment控制的所有Pod的平均值)。

3.5 压测php-apache服务,只是针对CPU做压测

#把busybox.tar.gz和nginx-1-9-1.tar.gz上传到xianchaonode1上,手动解压:
docker load -i busybox.tar.gz
docker load -i nginx-1-9-1.tar.gz
启动一个容器,并将无限查询循环发送到php-apache服务(复制k8s的master节点的终端,也就是打开一个新的终端窗口):
[root@xianchaomaster1]# kubectl run v1 -it --image=busybox --image-pull-policy=IfNotPresent /bin/sh

登录到容器之后,执行如下命令
/# while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
在一分钟左右的时间内,我们通过执行以下命令来看到更高的CPU负载
kubectl get hpa
显示如下:
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   
php-apache   Deployment/php-apache   231%/50%    1        10           4          
上面可以看到,CPU消耗已经达到256%,每个pod的目标cpu使用率是50%,所以,php-apache这个deployment创建的pod副本数将调整为5个副本,为什么是5个副 本,因为256/50=5
kubectl get pod
显示如下:
NAME                          READY   STATUS    RESTARTS   AGE
php-apache-5694767d56-b2kd7   1/1     Running   0          18s
php-apache-5694767d56-f9vzm   1/1     Running   0          2s
php-apache-5694767d56-hpgb5   1/1     Running   0          18s
php-apache-5694767d56-mmr88   1/1     Running   0          4h13m
php-apache-5694767d56-zljkd      1/1     Running   0          18s

kubectl get deployment php-apache
显示如下:
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   5/5     5            5           2h1m

注意:可能需要几分钟来稳定副本数。由于不以任何方式控制负载量,因此最终副本数可能会与此示例不同。

停止对php-apache服务压测,HPA会自动对php-apache这个deployment创建的pod做缩容

停止向php-apache这个服务发送查询请求,在busybox镜像创建容器的终端中,通过<Ctrl>+ C把刚才while请求停止,然后,我们将验证结果状态(大约一分钟后):

kubectl get hpa

显示如下:

HPA-VPA-KPA实现自动扩容

kubectl get deployment php-apache

显示如下:

php-apache        1/1     1            1           5s

通过上面可以看到,CPU利用率下降到0,因此HPA自动将副本数缩减到1。

注意:自动缩放副本可能需要几分钟。默认五分钟

4、利用HPA基于内存指标实现pod自动扩缩容

1、创建一个nginx的pod
[root@xianchaomaster1 ~]# cat nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hpa
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        resources:
          requests:
            cpu: 0.01
            memory: 25Mi
          limits:
            cpu: 0.05
            memory: 60Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
[root@xianchaomaster1 ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-hpa created
service/nginx created
2、验证nginx是否运行
[root@xianchaomaster1 ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
nginx-hpa-fb74696c-6m6st      1/1     Running   0          28s
注意:
nginx的pod里需要有如下字段,否则hpa会采集不到内存指标
 resources:
    requests:
      cpu: 0.01
      memory: 25Mi
    limits:
       cpu: 0.05
       memory: 60Mi

创建一个hpa

[root@xianchaomaster1 ~]# cat hpa-v1.yaml 
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
    maxReplicas: 10
    minReplicas: 1
    scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: nginx-hpa
    metrics:
    - type: Resource
      resource:
        name: memory
        targetAverageUtilization: 60

更新资源清单文件

[root@xianchaomaster1 ~]# kubectl apply -f hpa-v1.yaml
horizontalpodautoscaler.autoscaling/nginx-hpa created
#查看创建的hpa
[root@xianchaomaster1 ~]# kubectl get hpa
NAME         REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS   
nginx-hpa    Deployment/nginx-hpa    5%/60%    1         10        1    

压测nginx的内存,hpa会对pod自动扩缩容

登录到上面通过pod创建的nginx,并生成一个文件,增加内存
[root@xianchaomaster1]#kubectl exec -it nginx-hpa-fb74696c-6m6st  -- /bin/sh
#压测
# dd if=/dev/zero of=/tmp/a

#打开新的终端
[root@xianchaomaster1 ~]# kubectl get hpa
NAME         REFERENCE     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa    Deployment/nginx-hpa    200%/60%    1         10        1         

上面的targets列可看到200%/60%,200%表示当前内存使用率,60%表示所有pod的内存使用率维持在60%,现在内存使用率达到200%,所以pod增加到4个

[root@xianchaomaster1 ~]# kubectl get deployment
显示如下:
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-hpa    4/4     4            4           25m
[root@xianchaomaster1 ~]# kubectl get pods
显示如下:
NAME                          READY   STATUS    RESTARTS   AGE
nginx-hpa-bb598885d-j4kcp     1/1     Running   0          25m
nginx-hpa-bb598885d-rj5hk     1/1     Running   0          63s
nginx-hpa-bb598885d-twv9c     1/1     Running   0          18s
nginx-hpa-bb598885d-v9ft5     1/1     Running   0          63s

5、取消对nginx内存的压测,hpa会对pod自动缩容
[root@xianchaomaster1 ~]# kubectl exec -it nginx-hpa-fb74696c-6m6st  -- /bin/sh 
删除/tmp/a这个文件
# rm -rf /tmp/a 
[root@xianchaomaster1 ~]# kubectl get hpa
显示如下,可看到内存使用率已经降到5%:
NAME        REFERENCE              TARGETS   MINPODS   MAXPODS   REPLICAS   AGEnginx-hpa   Deployment/nginx-hpa   5%/60%    1         10        1          26m
[root@xianchaomaster1 ~]# kubectl get deployment
显示如下,deployment的pod又恢复到1个了:
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-hpa    1/1     1            1           38m

扩展:查看v2版本的hpa如何定义?

[root@xianchaomaster1 ~]# kubectl get hpa.v2beta2.autoscaling -o yaml > 1.yaml

VPA实现Pod自动扩缩容

Vertical Pod Autoscaler(VPA):垂直Pod自动扩缩容,用户无需为其pods中的容器设置最新的资源request。配置后,它将根据使用情况自动设置request,从而允许在节点上进行适当的调度,以便为每个pod提供适当的资源量。

安装vpa

[root@xianchaonode1 ~]# docker load -i vpa-admission-controller_0_8_0.tar.gz 
Loaded image: scofield/vpa-admission-controller:0.8.0
[root@xianchaonode1 ~]# docker load -i vpa-recommender_0_8_0.tar.gz 
Loaded image: scofield/vpa-recommender:0.8.0
[root@xianchaonode1 ~]# docker load -i vpa-updater_0_8_0.tar.gz 
Loaded image: scofield/vpa-updater:0.8.0

[root@xianchaomaster1~]#unzip autoscaler-vertical-pod-autoscaler-0.8.0.zip [root@xianchaomaster1 ~]#cd  /root/autoscaler-vertical-pod-autoscaler-0.8.0/vertical-pod-autoscaler/deploy

修改admission-controller-deployment.yaml里的image:

image:  scofield/vpa-admission-controller:0.8.0
imagePullPolicy: IfNotPresent

修改recommender-deployment.yaml里的image:
image: scofield/vpa-recommender:0.8.0
imagePullPolicy: IfNotPresent

修改updater-deployment.yaml文件里的image:
image: scofield/vpa-updater:0.8.0
imagePullPolicy: IfNotPresent

[root@xianchaomaster1]# cd /root/autoscaler-vertical-pod-autoscaler-0.8.0/vertical-pod-autoscaler/hack
[root@xianchaomaster1 hack]# ./vpa-up.sh

验证vpa是否部署成功

[root@xianchaomaster1]# kubectl get pods -n kube-system | grep vpa
vpa-admission-controller-777694497b-6rrd4   1/1     Running   0          86s
vpa-recommender-64f6765bd9-ckmvf         1/1     Running   0          86s
vpa-updater-c5474f4c7-vq82f                 1/1     Running   0         86s

测试VPA实现pod自动扩缩容

updateMode: "Off"

1、部署一个nginx服务,部署到namespace: vpa名称空间下:
[root@xianchaomaster1 ~]# mkdir vpa
[root@xianchaomaster1 ~]# cd vpa/
[root@xianchaomaster1 vpa]# kubectl create ns vpa
[root@xianchaomaster1 vpa]# cat vpa-1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: vpa
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 200m
            memory: 300Mi
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-1.yaml
[root@xianchaomaster1 vpa]# kubectl get pods -n vpa
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5f598bd784-fknwq   1/1     Running   0          6s
nginx-5f598bd784-ljq75    1/1     Running   0          6s

在nginx管理的pod前端创建四层代理Service

[root@xianchaomaster1 vpa]# cat vpa-service-1.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: vpa
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
  selector:
app: nginx

[root@xianchaomaster1 vpa]# kubectl apply -f vpa-service-1.yaml
[root@xianchaomaster1 vpa]# kubectl get svc -n vpa
NAME    TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.109.35.41   <none>        80:31957/TCP   3m28s
[root@xianchaomaster1 vpa]# curl -I 192.168.40.180:31957
HTTP/1.1 200 OK
#显示200说明代理没问题

创建VPA

先使用updateMode: "Off"模式,这种模式仅获取资源推荐值,但是不更新Pod

[root@xianchaomaster1 vpa]# cat vpa-nginx.yaml 
apiVersion: autoscaling.k8s.io/v1beta2
kind: VerticalPodAutoscaler
metadata:
  name: nginx-vpa
  namespace: vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: nginx
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
    - containerName: "nginx"
      minAllowed:
        cpu: "500m"
        memory: "100Mi"
      maxAllowed:
        cpu: "2000m"
        memory: "2600Mi"
HPA-VPA-KPA实现自动扩容
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-nginx.yaml
[root@xianchaomaster1 vpa]# kubectl get vpa -n vpa
NAME        AGE
nginx-vpa   6s

查看vpa详细信息:
[root@xianchaomaster1 vpa]#  kubectl  describe  vpa nginx-vpa   -n vpa
Name:         nginx-vpa
Namespace:    vpa
Labels:       <none>
Annotations:  <none>
API Version:  autoscaling.k8s.io/v1
Kind:         VerticalPodAutoscaler
Metadata:
  Creation Timestamp:  2021-07-15T04:40:48Z
  Generation:          2
  Managed Fields:
    API Version:  autoscaling.k8s.io/v1beta2
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
      f:spec:
        .:
        f:resourcePolicy:
          .:
          f:containerPolicies:
        f:targetRef:
          .:
          f:apiVersion:
          f:kind:
          f:name:
        f:updatePolicy:
          .:
          f:updateMode:
    Manager:      kubectl-client-side-apply
    Operation:    Update
    Time:         2021-07-15T04:40:48Z
    API Version:  autoscaling.k8s.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:status:
        .:
        f:conditions:
        f:recommendation:
          .:
          f:containerRecommendations:
    Manager:         recommender
    Operation:       Update
    Time:            2021-07-15T04:41:34Z
  Resource Version:  385606
  Self Link:         /apis/autoscaling.k8s.io/v1/namespaces/vpa/verticalpodautoscalers/nginx-vpa
  UID:               fe00ca65-7dd3-495f-bcba-b1e602f01fb3
Spec:
  Resource Policy:
    Container Policies:
      Container Name:  nginx
      Max Allowed:
        Cpu:     2000m
        Memory:  2600Mi
      Min Allowed:
        Cpu:     500m
        Memory:  100Mi
  Target Ref:
    API Version:  apps/v1
    Kind:         Deployment
    Name:         nginx
  Update Policy:
    Update Mode:  Off
Status:
  Conditions:
    Last Transition Time:  2021-07-15T04:41:34Z
    Status:                True
    Type:                  RecommendationProvided
  Recommendation:
    Container Recommendations:
      Container Name:  nginx
      Lower Bound:
        Cpu:     500m
        Memory:  262144k
      Target:
        Cpu:     500m
        Memory:  262144k
      Uncapped Target:
        Cpu:     25m
        Memory:  262144k
      Upper Bound:
        Cpu:     1349m
        Memory:  1410936619
Events:          <none>
查看vpa详细信息
  1. Lower Bound:           下限值
  2. Target:                推荐值
  3. Upper Bound:           上限值
  4. Uncapped Target:       如果没有为VPA提供最小或最大边界,则表示目标利用率

 上面结果表示,推荐的 Pod 的 CPU 请求为 500m,推荐的内存请求为 262144k 字节。

 

#压测nginx

[root@xianchaomaster1 vpa]# yum -y install httpd-tools ab
[root@xianchaomaster1 vpa]#  ab -c 100 -n 10000000 http://192.168.40.180:31957/


#过几分钟后观察VPA Recommendation变化

[root@xianchaomaster1 vpa]#  kubectl  describe  vpa nginx-vpa   -n vpa
Recommendation:
    Container Recommendations:
      Container Name:  nginx
      Lower Bound:
        Cpu:     500m
        Memory:  262144k
      Target:
        Cpu:     763m
        Memory:  262144k
      Uncapped Target:
        Cpu:     763m
        Memory:  262144k
      Upper Bound:
        Cpu:     2
        Memory:  934920074
Events:          <none>

从以上信息可以看出,VPA对Pod给出了推荐值:Cpu: 763m,因为我们这里设置了updateMode: "Off",所以不会更新Pod

[root@xianchaomaster1 vpa]# kubectl get pods -n vpa
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5f598bd784-fknwq   1/1     Running   0          79m
nginx-5f598bd784-ljq75   1/1     Running   0          79m

updateMode: "On"

1、现在我把updateMode: "Auto",看看VPA会有什么动作
这里我把resources改为:memory: 50Mi,cpu: 100m
[root@xianchaomaster1 vpa]# cat vpa-nginx-1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: vpa
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: nginx
        resources:
          requests:
            cpu: 100m
            memory: 50Mi
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-nginx-1.yaml
[root@xianchaomaster1 vpa]# kubectl get pods -n vpa
NAME                    READY   STATUS    RESTARTS   AGE
nginx-b75478445-jxp5d   1/1     Running   0          30s
nginx-b75478445-psh2j   1/1     Running   0          30s

再次部署vpa

[root@xianchaomaster1 vpa]# cat vpa-nginx.yaml 
apiVersion: autoscaling.k8s.io/v1beta2
kind: VerticalPodAutoscaler
metadata:
  name: nginx-vpa-2
  namespace: vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: nginx
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: "nginx"
      minAllowed:
        cpu: "500m"
        memory: "100Mi"
      maxAllowed:
        cpu: "2000m"
        memory: "2600Mi"
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-nginx.yaml 
verticalpodautoscaler.autoscaling.k8s.io/nginx-vpa-2 created
[root@xianchaomaster1 vpa]# kubectl get vpa -n vpa
NAME          MODE   CPU    MEM       PROVIDED   AGE
nginx-vpa     Off    500m   262144k   True       72m
nginx-vpa-2   Auto                               9s

再次压测

[root@xianchaomaster1 vpa]#  ab -c 100 -n 10000000 http://192.168.40.180:31957/

几分钟后,使用describe查看vpa详情,只关注Container Recommendations
[root@xianchaomaster1 ~]#  kubectl  describe  vpa nginx-vpa   -n vpa |tail -n 20

Target变成了Cpu: 656m ,Memory: 262144k

来看下event事件

[root@xianchaomaster1 ~]# kubectl get event -n vpa

HPA-VPA-KPA实现自动扩容

从输出信息可以看到,vpa执行了EvictedByVPA,自动停掉了nginx,然后使用 VPA推荐的资源启动了新的nginx
,我们查看下nginx的pod可以得到确认

[root@xianchaomaster1 ~]# kubectl get pods -n vpa
NAME                    READY   STATUS    RESTARTS   AGE
nginx-b75478445-9sd46   1/1     Running   0          15h
[root@xianchaomaster1 ~]# kubectl describe  pods nginx-b75478445-9sd46 -n vpa

Name:         nginx-b75478445-9sd46
Namespace:    vpa
Priority:     0
Node:         xianchaonode1/192.168.40.181
Start Time:   Thu, 15 Jul 2021 14:13:34 +0800
Labels:       app=nginx
              pod-template-hash=b75478445
Annotations:  cni.projectcalico.org/podIP: 10.244.121.28/32
              cni.projectcalico.org/podIPs: 10.244.121.28/32
Status:       Running
IP:           10.244.121.28
IPs:
  IP:           10.244.121.28
Controlled By:  ReplicaSet/nginx-b75478445
Containers:
  nginx:
    Container ID:   docker://f9d7ac11769acef2801c7d9a1090f4ece4ebe22e1eb4f128659617b1467a069d
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:353c20f74d9b6aee359f30e8e4f69c3d7eaea2f610681c4a95849a2fd7c497f9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Thu, 15 Jul 2021 14:13:35 +0800
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        656m
      memory:    262144k

再回头看看部署文件

HPA-VPA-KPA实现自动扩容

 

 

 

现在可以知道VPA做了哪些事了吧。当然,随着服务的负载的变化,VPA的推荐值也会不断变化。当目前运行的pod的资源达不到VPA的推荐值,就会执行pod驱逐,重新部署新的足够资源的服务。

 

VPA使用限制:

不能与HPA(Horizontal Pod Autoscaler )一起使用

Pod比如使用副本控制器,例如属于Deployment或者StatefulSet

 

VPA有啥好处:

Pod 资源用其所需,所以集群节点使用效率高。

Pod 会被安排到具有适当可用资源的节点上。

不必运行基准测试任务来确定 CPU 和内存请求的合适值。

VPA 可以随时调整 CPU 和内存请求,无需人为操作,因此可以减少维护时间。

 VPA是Kubernetes比较新的功能,还没有在生产环境大规模实践过,不建议在线上环境使用自动更新模式,但是使用推荐模式你可以更好了解服务的资源使用情况。

 

kubernetes cluster-autoscaler

1、什么是 cluster-autoscaler

Cluster Autoscaler (CA)是一个独立程序,是用来弹性伸缩kubernetes集群的。它可以自动根据部署应用所请求的资源量来动态的伸缩集群。当集群容量不足时,它会自动去 Cloud Provider (支持 GCE、GKE 和 AWS)创建新的 Node,而在 Node 长时间资源利用率很低时自动将其删除以节省开支。

项目地址:https://github.com/kubernetes/autoscaler

2、Cluster Autoscaler 什么时候伸缩集群?

在以下情况下,集群自动扩容或者缩放:

扩容:由于资源不足,某些Pod无法在任何当前节点上进行调度

 

缩容: Node节点资源利用率较低时,且此node节点上存在的pod都能被重新调度到其他node节点上运行

3、什么时候集群节点不会被 CA 删除?

1)节点上有pod被 PodDisruptionBudget 控制器限制。

2)节点上有命名空间是 kube-system 的pods。

3)节点上的pod不是被控制器创建,例如不是被deployment, replica set, job, stateful set创建。

4)节点上有pod使用了本地存储

5)节点上pod驱逐后无处可去,即没有其他node能调度这个pod

6)节点有注解:"cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"(在CA 1.0.3或更高版本中受支持)

 

扩展:什么是PodDisruptionBudget?

通过PodDisruptionBudget控制器可以设置应用POD集群处于运行状态最低个数,也可以设置应用POD集群处于运行状态的最低百分比,这样可以保证在主动销毁应用POD的时候,不会一次性销毁太多的应用POD,从而保证业务不中断

 

4、Horizontal Pod Autoscaler 如何与 Cluster Autoscaler 一起使用?

Horizontal Pod Autoscaler 会根据当前CPU负载更改部署或副本集的副本数。如果负载增加,则HPA将创建新的副本,集群中可能有足够的空间,也可能没有足够的空间。如果没有足够的资源,CA将尝试启动一些节点,以便HPA创建的Pod可以运行。如果负载减少,则HPA将停止某些副本。结果,某些节点可能变得利用率过低或完全为空,然后CA将终止这些不需要的节点。

扩展:如何防止节点被CA删除?

节点可以打上以下标签:

"cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"

 

 

可以使用 kubectl 将其添加到节点(或从节点删除):

$ kubectl annotate node <nodename>  cluster-autoscaler.kubernetes.io/scale-down-disabled=true

 

5、Cluster Autoscaler 支持那些云厂商?

GCE https://kubernetes.io/docs/concepts/cluster-administration/cluster-management/

Google云服务商

 

GKE https://cloud.google.com/container-engine/docs/cluster-autoscaler

Google kubernetes服务

 

AWS(亚马逊) https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md

 

Azure(微软) https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md

 

Alibaba Cloud https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/alicloud/README.md

 

OpenStack Magnum https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/magnum/README.md

 

DigitalOcean https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/digitalocean/README.md

 

CloudStack https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/cloudstack/README.md

 

Exoscale https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md

 

Packet https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/packet/README.md

 

OVHcloud https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/ovhcloud/README.md

 

Linode https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/linode/README.md

 

Hetzner https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/hetzner/README.md

 

Cluster API  https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md

 

 

Knative的自动扩缩容实现

Knative相关组件

这里我们只关心数据面的组件: Queue-proxy 针对每个业务容器Knative都会自动注入一个sidecar容器,本质上是一个基于Golang的反向代理服务,主要功能是检测流量,暴露出RPS和concurrency数据供Autoscaler组件采集。另外,如果用户配置containerConcurrency,还会限制单个容器的并发请求数,超过并发数的请求,会被缓存下来放入队列,这也是Queue-proxy名称的含义。

Autoscaler Autoscaler是自动扩缩容的核心控制组件,主要功能是采集Queue-proxy的Metrics数据,然后对比配置的数据,计算出预期的副本数,最后进行扩缩容操作。

Activator Activator的引入,最开始的目的是在冷启动的时候,由于服务副本数为0,需要有一个组件来保持住请求,通知Autoscaler扩容对应的服务,然后再将请求发送至运行后的服务。除此之外,还承担了当流量瞬间突增的时候,缓存请求,等扩容完成后再代理发送至后端服务的功能。

有哪些Metrics数据?

HPA的Metrics来源一般是Pod的CPU或者Memory,当然也支持自定义的Metrics数据,不过对于大部分在线业务来说,并非CPU密集型,而是IO密集型,这意味着单纯依赖CPU来自动扩缩容往往并不满足实际需求,可能工作负载接收的流量已经很大了,延迟已经很高了,但是HPA还没有帮我们扩容服务。 为了更好的满足这种情况,Knative KPA自动扩缩容则设计支持了请求并发(concurrency)和RPS(request-per-second)两种Metrics数据,相比CPU数据,这两者更贴近负载的load,更适合描述在线业务。数据源来自Activator组件和每个工作负载Pod,当然工作负载的Pod数据由Queue-proxy sidecar暴露出Metrics接口。 RPS比较好理解,在一个采集周期内(默认1s),来一次http request,计数加1即可,比如1s内检测到来了100个请求,那么RPS就是100。 Concurrency可以理解为一个采集周期内正在处理http request的数量,比如1s内有50个请求正在被处理则Concurrency为50。实际上Knative会记录request来的时刻和返回的时刻,如果1s内只有一个请求,并且处理了500ms即返回,则Concurrency为0.5。

Metrics是如何被采集的?

我们都知道Prometheus为pull拉模型,即服务本身提供Metrics接口,供Prometheus去拉取监控数据。 对于工作负载Pod而言,Queue-proxy sidecar承担了检测请求流量的职责,Autoscaler会从中拉取concurrency和RPS数据。 但是Activator则不同,Activator通过和Autoscaler组件建立websocket连接,使用push的方式将Metrics数据定时推到Autoscaler组件中。 如果Activator检测到流量是请求到一个副本数为0的负载,则会推送一个带有poke标记的Metrics数据到Autoscaler,Autoscaler会马上扩容负载,相比拉模式,这种推送push的方式会减少冷启动延迟。这也是Knative设计者在Activator这里采用push的方式的一个重要原因。 整体数据链路图如下所示:

 

 

 

 HPA-VPA-KPA实现自动扩容

 

 

KPA算法

虽然Knative本身也支持HPA,但这里我们还是只关心默认使用的KPA,我们可以简单的把KPA认为是区别于HPA的Knative自动扩缩容的方式。

Autoscaler的KPA算法本质上就是计算出多少个Pod可以满足现在的流量需求,计算逻辑便是在一个无限循环中,每隔2s触发一次,最核心的逻辑如下所示:

desiredPodCount = metricInSystem / targetPerPod

例如,检测到一共有100个并发请求,我们目标是每个Pod处理5个并发,那么期望的Pod数为100/5=20个。 当然实际的处理逻辑不会这么简单粗暴,还需要考虑不能超过配置的Pod最大副本数等等。 另外,KPA还设计了Stable和Panic模式,主要是为了区分和解决正常情况和流量突发的场景,避免流量突发时扩容不及时。 默认Stable为60s(可配置)的时间窗口,Panic时间窗口默认为10%即6s。 正常情况下,Autoscaler使用Stable时间窗口去聚合Metrics数据并计算期望的Pod个数。在一个60s的窗口周期内计算平均值,可以避免Pod过于频繁的扩缩容。 但是如果突发流量,6s内检测到的指标超过目前能处理的200%(可配置),则会进入Panic模式,在更短的时间内快速扩容Pod副本数。是否进入Panic模式可参考如下公式:

isPanic = metricInSystempanic / (readyPods * targetPerPod) >= panicThreshold

例如,检测到系统有100个并发请求(metricInSystempanic=100),目前有5个正在运行的Pod(readyPods=5)并且目标是每个Pod处理10个并发(targetPerPod=10),默认配置的进入Panic模式阈值为200%(panicThreshold=2),则根据如上公式:

100 / (5 * 10) >= 2

即会进入Panic模式。

突发流量

相比HPA,Knative会考虑更多的场景,其中一个比较重要的是流量突发的时候。 除了Autoscaler会进入Panic模式更快的去扩容外,上面也提到过Activator和Queue-proxy本身也带有缓存请求的功能,这个功能的目的也是为了在请求流量突发来不及处理时,进行缓存再转发。但是非冷启动情况下的请求缓存,会被视为一种迫不得已的兜底行为,同时会带来一定的请求时延。 Knative中会有很多的配置,可以调整用于突发流量的场景。下面为常见的配置项:

  • container concurrency:容器并发度,如果设置为0,则视为不限制容器并发。
  • target utilization:目标使用率,达到该使用率后会被视为达到容器的并发度,会触发扩容。
  • target burst capacity (TBC) :可容忍的请求爆发容量,这个参数比较关键而且不太好理解。

举一个例子,假设我们的容器container concurrency被设置为50,目标使用率target utilization为80%,即每个容器目标是接收50*80%=40的并发请求,TBC设置为100。当有180的并发请求进来后,我们很容易算出最终会被扩容为5个副本(这里会按照目标请求40来计算),但实际上5个副本的最大容量为5*50=250个并发请求,则实际剩余可容忍的爆发为250-180=70个并发。 当剩余可容忍的并发小于TBC时,Knative会让流量经过Activator,而不是直接发送到后端服务,那么在这个例子中,由于70<TBC=100,此时相当于Knative认为剩余的爆发请求容量不足以支撑目标的可容忍容量(TBC),所以流量全部都会走到Activator再进行负载均衡转发,因为Activator可以感知到哪些容器目前接收的请求已经达到极限,哪些容器却还能继续接收更多请求。 同时,如果在示例的场景中,再突然进来了100个请求,在扩容来不及的情况下,Activator会代理70个请求到后端服务,同时缓存30个请求,等后端服务有更多容量时再转发处理。 由此可见,Activator缓存请求并非只是在冷启动时,在突发流量场景下,Activator也会起到相同的作用,而冷启动其实只是后端服务副本为0的一种特殊场景而已。 从上面的分析可以看出,TBC参数十分重要,会影响到什么时候请求流量会经过Activator,什么时候则直接从网关到后端。但是,如果在非冷启动的时候,流量也经过Activator,增加了一层链路,对于延迟敏感的服务,有点得不偿失。 那TBC应该设置成多少呢?这对于很多人来说,也是一个头疼的问题。 这里给出一些参考:

  1. 对于非CPU密集型的服务,例如常规的web应用、静态资源服务等,建议直接将TBC设置为0,同时container concurrency也设置为0,即不限制容器的请求并发。 当TBC=0时,系统剩余的可爆发请求容量会永远大于TBC,也意味着除了冷启动的时候,请求流量永远不会走到Activator,同时我建议设置Knative Service的最小保留副本数为1,这样Activator组件其实都不会被用到,也减少了一层链路。 其实,我们使用Serverless的时候,很多的服务都是常规的在线业务,使用如上的配置,可以最小化请求延迟,增大RPS。
  2. 对于非常CPU密集型的服务、单线程等极端场景的服务,需要严格限制单个容器的请求并发,一般都需要设置container concurrency<5,此时建议设置TBC=-1,因为这种场景下往往扩容等不及请求流量的突增。 当TBC=-1,也意味着所有的请求,都会走到Activator,Activator会重新转发请求或者缓存超额的请求,这个时候的Activator组件在非冷启动情况下就有存在的价值。
  3. 对于除了上述两种情况,还需要限制一些并发请求的场景,此时一般container concurrency>5,建议设置TBC为一个预期的值,例如100,至于这个值具体设置多少,需要系统管理员根据实际的场景去评估。

思考

根据上述的分析,为什么Knative要抛弃HPA现有的实现,重新设计一个自动扩缩容系统呢? 大概主要有以下的原因:

  1. HPA本身扩缩容算法实现简单,不一定能满足所有需求,所以Knative提供了Autoscaler组件,提供了更加自定义的扩容算法。
  2. HPA默认不支持缩容至0和冷启动,这也是Activator的主要能力。

但是,Knative的现状就是合适和最理想的吗?这个值得我们更多的思考。 首先,KPA完全是定制化的,虽然HPA可以支持自定义指标的扩缩容,但HPA无法采用KPA的Metrics数据,二者比较割裂。如下图所示:

HPA-VPA-KPA实现自动扩容

 

并且,KPA也只能支持PRS和Concurrency两种指标,无法接入用户自定义的其他指标。另外,虽然KPA可配置自动扩缩容算法的很多参数,但仍然缺乏可扩展性和可定制性。

不过,社区也意识到了这些问题,并在一步步的优化和改进。毕竟相比K8s,Knative还很年轻,相信随着时间推移,Knative会越来越完善和强大,成为Serverless领域的事实标准或许就在不远的前方。

 

HPA-VPA-KPA实现自动扩容

上一篇:Excel综合分析多指标问题


下一篇:3D线上展厅-打造全新环保企业展馆体现