前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >优化 Kubernetes 横向扩缩容 HPA

优化 Kubernetes 横向扩缩容 HPA

作者头像
我是阳明
发布2021-06-25 16:56:20
2.2K0
发布2021-06-25 16:56:20
举报
文章被收录于专栏:k8s技术圈

图片来源: instagram.com/febin_raj

Pod水平自动扩缩(Horizontal Pod Autoscaler, 简称HPA)可以基于 CPU/MEM 利用率自动扩缩Deployment、StatefulSet 中的 Pod 数量,同时也可以基于其他应程序提供的自定义度量指标来执行自动扩缩。默认HPA可以满足一些简单场景,对于生产环境并不一定适合,本文主要分析HPA的不足与优化方式。

HPA Resource类型不足

默认HPA提供了Resource类型,通过CPU/MEM使用率指标(由metrics-server提供原始指标)来扩缩应用。

使用率计算方式

在Resource类型中,使用率计算是通过request而不是limit,源码如下:

代码语言:javascript
复制
// 获取Pod resource request
func calculatePodRequests(pods []*v1.Pod, resource v1.ResourceName) (map[string]int64, error) {
 requests := make(map[string]int64, len(pods))
 for _, pod := range pods {
  podSum := int64(0)
  for _, container := range pod.Spec.Containers {
   if containerRequest, ok := container.Resources.Requests[resource]; ok {
    podSum += containerRequest.MilliValue()
   } else {
    return nil, fmt.Errorf("missing request for %s", resource)
   }
  }
  requests[pod.Name] = podSum
 }
 return requests, nil
}
// 计算使用率
func GetResourceUtilizationRatio(metrics PodMetricsInfo, requests map[string]int64, targetUtilization int32) (utilizationRatio float64, currentUtilization int32, rawAverageValue int64, err error) {
 metricsTotal := int64(0)
 requestsTotal := int64(0)
 numEntries := 0

 for podName, metric := range metrics {
  request, hasRequest := requests[podName]
  if !hasRequest {
   // we check for missing requests elsewhere, so assuming missing requests == extraneous metrics
   continue
  }

  metricsTotal += metric.Value
  requestsTotal += request
  numEntries++
 }


 currentUtilization = int32((metricsTotal * 100) / requestsTotal)

 return float64(currentUtilization) / float64(targetUtilization), currentUtilization, metricsTotal / int64(numEntries), nil
}

通常在Paas平台中会对资源进行超配,limit即用户请求资源,request即实际分配资源,如果按照request来计算使用率(会超过100%)是不符合预期的。相关issue见72811,目前还存在争论。可以修改源码,或者使用自定义指标来代替。

多容器Pod使用率问题

默认提供的Resource类型的HPA,通过上述方式计算资源使用率,核心方式如下:

代码语言:javascript
复制
metricsTotal = sum(pod.container.metricValue)
requestsTotal = sum(pod.container.Request)
currentUtilization = int32((metricsTotal * 100) / requestsTotal)

计算出所有container的资源使用量再比总的申请量,对于单容器Pod这没影响。但对于多容器Pod,比如Pod包含多个容器con1、con2(request都为1cpu),con1使用率10%,con2使用率100%,HPA目标使用率60%,按照目前方式得到使用率为55%不会进行扩容,但实际con2已经达到资源瓶颈,势必会影响服务质量。当前系统中,多容器Pod通常都是1个主容器与多个sidecar,依赖主容器的指标更合适点。

好在1.20版本中已经支持了ContainerResource可以配置基于某个容器的资源使用率来进行扩缩,如果是之前的版本建议使用自定义指标替换。

性能问题

单线程架构

默认的hpa-controller是单个Goroutine执行的,随着集群规模的增多,势必会成为性能瓶颈,目前默认hpa资源同步周期会15s,假设每个metric请求延时为100ms,当前架构只能支持150个HPA资源(保证在15s内同步一次)

代码语言:javascript
复制
func (a *HorizontalController) Run(stopCh <-chan struct{}) {
  // ...
 // start a single worker (we may wish to start more in the future)
 go wait.Until(a.worker, time.Second, stopCh)

 <-stopCh
}

可以通过调整worker数量来横向扩展,已提交PR。

调用链路

hpa controller中一次hpa资源同步,需要调用多次apiserver接口,主要链路如下

  1. 通过scaleForResourceMappings得到scale资源
  2. 调用computeReplicasForMetrics获取metrics value
  3. 调用Scales().Update更新计算出的副本数

尤其在获取metrics value时,需要先调用apiserver,apiserver调用metrics-server/custom-metrics-server,当集群内存在大量hpa时可能会对apiserver性能产生一定影响。

其他

对于自定义指标用户需要实现custom.metrics.k8s.ioexternal.metrics.k8s.io,目前已经有部分开源实现见custom-metrics-api。

另外,hpa核心的扩缩算法根据当前指标和期望指标来计算扩缩比例,并不适合所有场景,只使用线性增长的指标。

代码语言:javascript
复制
期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]

watermarkpodautoscaler提供了更灵活的扩缩算法,比如平均值、水位线等,可以作为参考。

总结

Kubernetes提供原生的HPA只能满足一部分场景,如果要上生产环境,必须对其做一些优化,本文总结了当前HPA存在的不足,例如在性能、使用率计算方面,并提供了解决思路。

❝本文链接: https://qingwave.github.io/k8s-hpa-enchance/ ❞

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 k8s技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HPA Resource类型不足
    • 使用率计算方式
      • 多容器Pod使用率问题
      • 性能问题
        • 单线程架构
          • 调用链路
          • 其他
          • 总结
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档