
本文基于Knative 0.7.0版本代码,解读KPA的工作原理。
PA reconcile
创建PA时,PA controller会开始reconcile过程。
这里KPA可以通过annotationautoscaling.knative.dev/class=kpa.autoscaling.knative.dev
或者hpa.autoscaling.knative.dev
来指定背后是kpa还是hpa。如果是hpa,那么reconcile过程则是直接创建一个简单的kubernetes hpa,目前仅支持resource类型的CPU,和Object类型的concurrency,即服务的同步处理请求数,同样通过annotation指定autoscaling.knative.dev/metric=cpu
或者concurrency
.
后面假设是kpa模式。
reconcile过程分为两步:同步各类资源和反馈desiredReplicas。
同步各类资源
reconcile的过程开始,会分别去reconcile以下几个资源,如果不存在,则会去创建:
metricService,他就是kubernetes的service,背后暴露了Pod上metrics sidecar的访问方式,其创建是通过deployment的selector选择pod,并暴露9090
和9091
端口,target port则分别是port name=queue-metrics
和port name=user-metrics
的端口配置
serverlessService,就是knative的自己的service资源
decider,也是knative自己的资源,他保存了针对当前服务autoScaling的一些配置信息,他是内存态的,并没有在etcd落盘。并且desiredReplicas也是通过他的status反馈回来的。reconcile在创建decider的时候会去MultiScaler上注册它,以启动autoScaler,后面会讲到。
metric,knative的crd,为metricCollector记录了metricService的信息,以及stable和panic窗口的大小。reconciler在创建metric时,会去MetricCollector上注册,以开始收集metric,后面会讲到。
stableWindow
大小通过pa上的annotation"autoscaling.knative.dev/window"指定,如"60s"。否则就会使用全局的配置。
panicWindow
大小通过<panic-window-percentage> * stable-window / 100 得到,可以通过PA上的annotation"autoscaling.knative.dev/panicWindowPercentage"指定,如“50.0”即50%,不能大于100.0或小于1.0,否则被设为0。如果没提供,也是0,即disable panic window。
反馈DesiredReplicas
最后会从decider.status里拿到目前的desiredScale,然后去尝试更新对用deployment的replicas,当然,这里的更新过程会考虑desiredScale是否合法,比如是否在最大最小的replicas范围内。
各组件工作原理
MultiScaler
顾名思义,MultiScaler会维护一个scaler的集合。
每次根据一个decider创建一个scaler后,multiScaler都会为它单独起一个goroutine。这个goroutine会定时去计算desiredScale,并把它更新到decider的statue上。“定时”是通过decider上的spec.tickInterval字段给出,此值是从configMap的全局配置中得到,默认是2秒。
这个计算desiredScale的过程是调用uniScaler接口的Scale方法。
UniScaler
在uniScale的Scale实现方法中,它会通过MetricClient分别拿到stableWindow和panicWindow聚合出的所有pod的总concurrency值observedStableConcurrency, observedPanicConcurrency。而这里的stableWindow和panicWindow则是通过metric资源拿到。
之后会根据拿到的concurrency值判断当前是stable mode还是panic mode。如果observedPanicConcurrency / readyPodsCount >= panicThreshold则进入panic mode。panicThreshold通过target * panicThresholdPercentage得到。target有三个来源,具体参考代码。panicThresholdPercentage通过PA的annotation"autoscaling.knative.dev/panicThresholdPercentage"得到,最小值110.0,比这小的话则被设为0。如果进入panic mode则replicas只增不减。
MetricClient (MetricCollector)
reconcile每次创建Metric资源的时候,都会去MetricCollector上注册metric,以开始收集对应服务的metric。在注册时会为每个metric创建一个对应collection,以及启动一个goroutine。collection是与某个服务对应的metric集合的实体,而goroutine则会定时(hardcode 1秒)通过ServiceScraper去访问metricService拿取metric。而访问metric的url正是从Metric.spec.ScrapeTarget生成的,这里ScrapeTarget的值就是metricService.name。(url格式:http://<svc-name>.<ns-name>:9090/metrics)。collection在scrape metric时,会计算一个取样量,比如pod数小于或等于3,则取样量为3,否则为pod总数的一个比例值。根据取样量n,会n次访问上面说的url,经由metric service(普通的k8s service)从随机的pod的sidecar中拿到当前的concurrency总量并取平均,得到当前的pod平均concurrency,作为当前时间的指标。
Stable mode & Panic mode
stable mode窗口为60秒,默认计算频率为2秒,autoScaler会聚合60秒内的concurrency数据来计算每个pod的平均concurrency,并调整deployment的replicas。(此处pod的数量来自于metrics server,而不是deployment的replicas,因为metrics server才是准确的)
同时,autoScaler也会去聚合一个panic window时间内的指标(默认6秒),如果panic window内,pod平均concurrency就达或超过了panic阈值(默认为目标concurrency的2倍),则进入panic mode
panic mode时,autoScaler也是每2秒就计算一次,并调整deployment的replicas,但是他只增加,不减少。当最后一次增加pod事件发生后,经过stable-window秒(默认stable-window是60秒),则自动恢复stable mode。
全局配置
autoScaling相关的配置可以通过PA的annotation指定,如果没有则会使用configMap提供的默认配置。
参考:https://github.com/knative/serving/blob/v0.7.0/pkg/autoscaler/config.go#L56
网友评论