如何自己部署autoscaler实现节点的自动扩缩容(一):本地debug运行autoscaler

原创 吴就业 172 0 2024-05-06

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/c89cd852479a43e8b26145275518ef1d

作者:吴就业
链接:https://wujiuye.com/article/c89cd852479a43e8b26145275518ef1d
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

先了解几个google cloud的概念:

背景

在google cloud上使用gke集群,gke已经集成autoscaler,通过在控制台创建节点池点击开启自动扩缩容就可以,那么为什么还要自己部署呢?

目前我们在做云原生项目的过程中发现以下问题:

  1. 自定义的调度器无法触发node扩容,原因是autoscaler在扩容之前,会调用一遍默认调度器的过滤插件,如果默认调度器的过滤插件选不出node才会真的扩容。但我们使用自己的调度器,而gke不提供配置支持让autoscaler使用我们自定义的过滤插件。
  2. gke提供的节点扩容,在缩容方面,耗时太长,总耗时需要11分钟,开源的autoscaler支持通过scale-down-unneeded-time配置将时间减少到1分钟,同样gke上没有一个地方可以配置。

总结就是,gke开放的autoscaler能力太过简单,并不能满足我们的需求。

本地Debug运行autoscaler

不管创建gke集群的时候,以及创建节点池的时候,有没有开启自动扩缩功能,gke都会部署autoscaler。autoscaler应该是部署在控制面的,没在集群中,看不到相关的pod。但是选举用的leases资源和状态配置文件都在集群中。因此自动部署autoscaler需要修改代码中leases的资源名称,以及配置不同的启动参数status-config-map-name,这样才能运行起来。

main方法中修改leases资源名称:

func defaultLeaderElectionConfiguration() componentbaseconfig.LeaderElectionConfiguration {
    return componentbaseconfig.LeaderElectionConfiguration{
       LeaderElect:   false,
       LeaseDuration: metav1.Duration{Duration: defaultLeaseDuration},
       RenewDeadline: metav1.Duration{Duration: defaultRenewDeadline},
       RetryPeriod:   metav1.Duration{Duration: defaultRetryPeriod},
       ResourceLock:  resourcelock.LeasesResourceLock,
       ResourceName:  "cluster-autoscaler-wujiuye",
    }
}

最少启动参数,要运行起来以下参数是必须的:

--kubeconfig=/Users/wujiuye/.kube/gcp_autoscaler_cluster
--cloud-config=/Users/wujiuye/cloud_native/autoscaler/cluster-autoscaler/cloudprovider/gce/testdata/gce.conf
--status-config-map-name=cluster-autoscaler-status-wujiuye
--nodes=0:3:https://www.googleapis.com/compute/projects/wujiuye-410808/zones/us-central1-c/instanceGroups/gke-autoscaler-cluster-test-group-9cb4eb39-grp

还有一个环境变量:

GOOGLE_APPLICATION_CREDENTIALS=/Users/wujiuye/cloud_native/wujiuye-410808-070a1c193e73.json

GOOGLE_APPLICATION_CREDENTIALS环境变量用于配置密钥文件的路径,这相当于使用AWS或者Aliyun等平台需要配置的ACCESS_KEY_ID、SECRET_ACCESS_KEY。

其中的gce.conf配置文件是用于配置project-id(项目id)和local-zone(区域)的,内容如下:

[global]
project-id=wujiuye-410808
local-zone=us-central1-c

做完以上操作autoscaler就可以本地debug运行起来了。

编写验证扩容案例,使用默认调度器。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-web-demo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-web-demo
  template:
    metadata:
      name: go-web-demo
      namespace: default
      labels:
        app: go-web-demo 
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: scheduler.wujiuye.com/node-class
                operator: In
                values:
                - user-server 
      containers:
        - name: go-web-demo
          image: us-central1-docker.pkg.dev/wujiuye-410808/web-demo:v1.0.0
          imagePullPolicy: Always
          resources:
            limits:
              cpu: 500m
              memory: 1024Mi
            requests:
              cpu: 500m
              memory: 1024Mi
      restartPolicy: Always
      terminationGracePeriodSeconds: 30

Demo 通过配置节点亲和性,让pod能够调度到动态扩容的节点池上,从而触发扩容验证。

第一次扩容失败,原因是节点池没加标签。

img

给节点池添加标签:

截屏2024-05-06 10.22.14

加完标签后,自动扩容成功:

截屏2024-05-06 10.22.25

并且autoscaler控制台会输出扩容日记。

截屏2024-05-06 10.36.19

其中的错误日志应该是创建节点过程中发生的,实际节点确实扩容出来了。使用gce平台,autoscaler创建出来的节点,node.Spec.ProviderId的格式是“gce://<project-id>/<zone>/<name>”,通过查看Node资源,确认格式没有错误,而且后续也没再报错。

node-provider_id

#云原生

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

如何自己部署autoscaler实现节点的自动扩缩容(四):低负载自动缩容与重调度

低负载自动缩容节点的这个特性还是非常有必要的,能够避免资源的过渡浪费。因为随着时间的推移,集群中势必会出现非常多的弹性节点利用率很低的情况。

如何自己部署autoscaler实现节点的自动扩缩容(三):验证修改缩容节点时长

autoscaler,想要缩短空闲节点被回收的时间,需要同时考虑三个启动参数的配置:scale-down-unneeded-time、unremovable-node-recheck-timeout、scale-down-delay-after-add。

如何自己部署autoscaler实现节点的自动扩缩容(二):支持自定义调度器触发的扩容

想要让autoscaler支持自定义调度器触发节点扩展,有两种方案。一是autoscaler支持自定义调度器的过滤器插件,二是autoscaler取消check逻辑。

Helm chart在values文件中声明为字符串的变量,部署替换占位符后却变成了数字类型

helm在获取values.yaml文件中配置的值时,由于没有对应一个结构体来反序列化yaml,只能使用map来接收,例如map[string]interface{}。可能是将interface{}尝试转成数字,能够转换成功helm就误以为我们需要的是数字了。

kubebuilder如何Watch由Pod产生的Event的创建,触发控制器Reconcile方法的执行

自定义资源的Controller创建出来的子资源,子资源创建的子资源(子子资源),如何Watch子子资源的事件?我们以MyDeployment->创建Pod->创建Event,想要watch Pod创建的Event的Create事件为例。

Kubebuilder控制器配置Owns然而监听到事件却不触发Reconcile方法

我们在CreateFunc、DeleteFunc、UpdateFunc方法中添加日记,发现这些方法被调用了,但却没有触发控制器的Reconcile方法执行。