在 Exoscale 上部署 Kubernetes Cluster Autoscaler:SKS Nodepool 与 Instance Pool 的自动扩缩容实战指南
2026/9/16 11:09:32 网站建设 项目流程

在 Exoscale 上部署 Kubernetes Cluster Autoscaler:SKS Nodepool 与 Instance Pool 的自动扩缩容实战指南

【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler

Cluster Autoscaler(CA)的 Exoscale 云提供商实现,让运行在 Exoscale SKS(Scalable Kubernetes Service)Nodepool 或 Instance Pool(实例池)中的 Kubernetes 工作节点能够根据集群资源压力自动扩缩容。本文基于仓库内 Exoscale 云提供商 README 展开,结合 云提供商实现源码 与 示例清单,完整讲解 API 凭证配置、IAM 最小权限、--nodes参数约束以及两种部署方式,读完即可在自己的 Exoscale 集群上落地一套可运行的节点自动伸缩方案。

功能概述:CA 如何管理 Exoscale 节点组

从 exoscale_cloud_provider.go 的 BuildExoscale 入口 可以看到,该云提供商自动接管 Kubernetes 集群中所有属于 Instance Pool 的节点NodeGroupForNode通过节点spec.providerID(形如exoscale://<instance-id>,见 util.go 中的前缀定义)反查 Exoscale Compute 实例,再定位其所属的 Instance Pool;只有被instance-pool管理的实例才会进入伸缩流程(exoscale_cloud_provider.go#L287-L318)。非 Instance Pool 成员(例如未受 Exoscale Cloud Controller Manager 管理、且带node-role.kubernetes.io/master污点的主节点)会被直接跳过。

每个节点组在代码中对应两类实现:

  • SKS Nodepool 节点组:由 exoscale_node_group_sks_nodepool.go 实现,用于托管式 SKS 集群,扩容调用ScaleSKSNodepool,缩容调用EvictSKSNodepoolMembers
  • 独立 Instance Pool 节点组:由 exoscale_node_group_instance_pool.go 实现,用于非托管集群,对应ScaleInstancePoolEvictInstancePoolMembers

判断节点属于哪一种类型,依赖实例的Manager字段:当Manager.Type == "sks-nodepool"时按 SKS Nodepool 处理,否则按独立 Instance Pool 处理(exoscale_cloud_provider.go#L84-L185)。

配置:向 Exoscale API 认证

前置条件:以下操作假设你拥有目标 Kubernetes 集群kube-system命名空间下创建资源的权限。

CA 需要通过 Exoscale API 查询实例、池状态并执行伸缩操作,因此必须提供 API 凭证。仓库推荐用 KubernetesSecret保存凭证,再以容器环境变量的方式注入 CA Deployment,并提供了便利脚本 generate-secret.sh 从本地 shell 环境变量一键生成并应用 Secret。

第一步:导出凭证与环境变量

强烈建议通过 Exoscale IAM 服务创建专用的 API 凭证(而非使用组织主密钥),并在 shell 中导出 CA 所需的三个变量,其中EXOSCALE_ZONE必须是目标集群所在的区域:

export EXOSCALE_API_KEY="EXOxxxxxxxxxxxxxxxxxxxxxxxx" export EXOSCALE_API_SECRET="xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" export EXOSCALE_ZONE="ch-gva-2"

第二步:生成并应用 Secret

在同一个 shell 中执行:

./examples/generate-secret.sh

脚本内部用 heredoc 生成一个Opaque类型的 Secret,将三个变量 Base64 编码后分别写入api-keyapi-secretapi-zone三个键(generate-secret.sh#L16-L27):

apiVersion: v1 kind: Secret metadata: name: exoscale-api-credentials namespace: kube-system type: Opaque data: api-key: '<base64(EXOSCALE_API_KEY)>' api-secret: '<base64(EXOSCALE_API_SECRET)>' api-zone: '<base64(EXOSCALE_ZONE)>'

第三步:验证 Secret 创建成功

kubectl get secret --namespace kube-system exoscale-api-credentials

第四步:将凭证注入 CA Deployment

最后,在 CA Deployment 的容器环境中通过secretKeyRef引用该 Secret。示例清单 cluster-autoscaler.yaml 展示了标准写法:

env: - name: EXOSCALE_API_KEY valueFrom: secretKeyRef: key: api-key name: exoscale-api-credentials - name: EXOSCALE_API_SECRET valueFrom: secretKeyRef: key: api-secret name: exoscale-api-credentials - name: EXOSCALE_ZONE valueFrom: secretKeyRef: key: api-zone name: exoscale-api-credentials

这三个环境变量是硬性要求:在 exoscale_manager.go 的 newManager 初始化逻辑 中,只要EXOSCALE_ZONEEXOSCALE_API_KEYEXOSCALE_API_SECRET任一为空,CA 就会直接报错退出,绝无默认值兜底。此外还支持一个可选变量EXOSCALE_API_ENVIRONMENT,用于切换 Exoscale API 端点环境(如内网环境或测试环境),默认值为api

IAM 最小权限原则

你可以把 IAM 密钥的 API 操作权限收缩到最小集:

  • SKS 托管集群场景(Nodepool 由 SKS 管理)下,仅需以下操作:
evict-sks-nodepool-members get-instance get-instance-pool get-operation get-quota list-sks-clusters scale-sks-nodepool
  • 非托管集群场景下,集群节点必须至少属于一个 Instance Pool,此时可收缩为:
evict-instance-pool-members get-instance get-instance-pool get-operation get-quota scale-instance-pool

这两组权限与源码中exoscaleClient接口的方法一一对应:查询类(GetInstanceGetInstancePoolGetQuotaListSKSClusters)与伸缩类(ScaleInstancePoolScaleSKSNodepoolEvictInstancePoolMembersEvictSKSNodepoolMembers),定义见 exoscale_manager.go#L31-L40。如果密钥权限不足,相关 API 调用会直接失败,进而影响节点组发现或伸缩动作。

可选配置:用 --nodes 限制节点组规模

默认情况下,集群中的所有 Nodepool 都会被视为可伸缩对象。若希望对某个特定 Nodepool 设置最小/最大节点数,可以使用--nodes=<min>:<max>:<nodepool-name>标志,例如:

--nodes=1:5:pool-a --nodes=2:10:pool-b

从源码可以看到该标志的完整语义(exoscale_cloud_provider.go#L114-L138):

  • CA 会把--nodes解析为dynamic.NodeGroupSpec(含MinSize/MaxSize),并按 Nodepool 名称(s.Name)与 SKS Nodepool 或 Instance Pool 的名称匹配;
  • 若某个节点组没有对应的--nodes条目,则minSize取默认值1maxSize通过 computeInstanceQuota 查询当前 Exoscale 账户的 Compute 实例配额上限(GetQuota(ctx, zone, "instance")返回的Limit)来兜底;
  • 代码注释明确说明--node-group-auto-discovery在该云提供商中未实现,节点组发现依赖的是对集群内实例池的自动接管。

值得注意的实现细节:scaleToZeroSupported被定义为false(exoscale_node_group_sks_nodepool.go#L31-L33),因此最小节点数不能为 0——instancePoolNodeGroup.MinSize()会强制把<= 0的值钳制为 1(exoscale_node_group_instance_pool.go#L59-L69)。换言之,Exoscale 云提供商目前不支持缩容到零节点,规划最小副本数时要预留至少 1 个节点。

部署方式

方式一:Helm

社区为 Cluster Autoscaler 维护了官方 Helm Chart,本仓库内对应的 Chart 源码位于 charts/cluster-autoscaler,其中 values.yaml 可配置云提供商与凭证引用方式。通过 Helm 部署时,将cloudProvider设为exoscale,并在extraEnv中注入上述三个环境变量即可,具体参数以 Chart 的 values 为准。

方式二:直接应用 Manifest

仓库在 examples 目录 提供了两个可直接使用的清单:

  • cluster-autoscaler-run-on-control-plane.yaml:将 CA Pod 调度到控制平面节点,适合控制平面与工作节点分离、且控制平面负载不高的场景:
kubectl apply -f ./examples/cluster-autoscaler-run-on-control-plane.yaml

该清单在 Deployment 中加入了nodeSelector: node-role.kubernetes.io/control-plane: ''与对应的 NoSchedule 容忍(cluster-autoscaler-run-on-control-plane.yaml#L183-L187)。

  • cluster-autoscaler.yaml:无节点亲和约束,可调度到普通工作节点,同样适用于 SKS 集群场景:
kubectl apply -f ./examples/cluster-autoscaler.yaml

两份清单都包含完整的 RBAC 资源(ServiceAccount、ClusterRole、Role、ClusterRoleBinding、RoleBinding),权限覆盖节点/Pod 的读写、Pod 驱逐、ConfigMap 状态记录等 CA 运行所需的最小集合(cluster-autoscaler.yaml#L11-L120)。Deployment 的核心启动参数为:

command: - /cluster-autoscaler - --cloud-provider=exoscale - --stderrthreshold=info - --cordon-node-before-terminating #- --scale-down-delay-after-add=30s #- --scale-down-unneeded-time=30s #- --unremovable-node-recheck-timeout=30s

其中--cordon-node-before-terminating在节点被驱逐前先将其置为不可调度(cordon),避免缩容过程中新 Pod 被调度到即将删除的节点上;三个被注释的--scale-down-*参数可按业务节奏放开,用于调整缩容的冷却期与触发条件。容器还挂载了宿主机的 CA 证书(/etc/ssl/certs/ca-certificates.crt)用于与 Exoscale API 的 TLS 通信,并暴露了:8085端口的 Prometheus 指标(annotations 中prometheus.io/scrape: 'true')。

重要注意事项

结合 README 的注意事项与源码实现,部署时需牢记以下几点:

  1. 默认 min/max 的行为:未通过--nodes指定的 Nodepool,minSize默认为 1,maxSize默认取当前 Exoscale 账户的 Compute 实例配额上限(exoscale_manager.go#L138-L145)。因此配额偏大的账户,默认 max 会很宽松,生产环境建议始终用--nodes显式声明每个节点组的边界。

  2. 节点组候选判定方式:某个 Instance Pool 是否进入伸缩候选,取决于 Kubernetes 节点所运行的 Compute 实例归属——CA 依据 Kubernetes 调度器发出的资源约束事件(Pod 因资源不足而 Pending)触发扩容决策,再通过节点反查实例池(exoscale_cloud_provider.go#L73-L82)。因此不在 Instance Pool 中的节点永远不会被伸缩

  3. 伸缩动作是异步等待的:无论是扩容(IncreaseSize)还是缩容(DeleteNodes),完成 API 调用后都会通过waitUntilRunning轮询 Instance Pool 状态直到running,轮询由 util.go 的 pollCmd 驱动,每 10 秒探测一次、最长等待 10 分钟,超时即报错。这说明 Exoscale 上的伸缩是"提交目标大小 + 等待池状态收敛"的异步模型,而非同步返回。

  4. 不支持缩容到 0scaleToZeroSupported = falseMinSize()强制至少为 1(exoscale_node_group_instance_pool.go#L59-L69)。此外DecreaseTargetSize是空实现——Exoscale 的 Instance Pool 不支持在不删除成员的前提下单纯下调目标大小(exoscale_node_group_sks_nodepool.go#L151-L155),缩容一律走"驱逐成员"路径。

  5. 节点组缓存刷新:Manager 通过Refresh()维护节点组缓存,默认随 CA 的--scan-interval(默认 10 秒)周期调用;若某个 Instance Pool 已被删除,会将其从缓存中移除,且当集群中不存在任何节点组时,CA 会打印cluster-autoscaler is disabled: no node groups found并停止伸缩(exoscale_manager.go#L113-L136)。

构建与启用云提供商

Exoscale 云提供商通过 build tag 方式接入 CA 主程序:在 router/router_exoscale.go 中,文件头部声明了//go:build exoscale,通过空导入(blank import)将云提供商注册进 builder。这意味着编译 CA 二进制时需要显式传入-tags exoscale,例如:

go build -tags exoscale -o cluster-autoscaler ./cluster-autoscaler/main.go

注册逻辑见 exoscale_cloud_provider.go 的 init 函数:builder.RegisterCloudProvider("exoscale", ...)并将exoscale设为默认云提供商。对应的单元测试位于 exoscale_cloud_provider_test.go,其中通过exoscaleClientMock模拟 Exoscale API 行为,覆盖了节点组发现、配额计算、伸缩调用等关键路径,可作为阅读实现逻辑的辅助参考。

小结

在 Exoscale 上启用 Cluster Autoscaler 的完整链路可归纳为五步:创建 IAM 最小权限 API 密钥 → 用generate-secret.sh生成kube-system/exoscale-api-credentialsSecret → 在 Deployment 中通过secretKeyRef注入EXOSCALE_API_KEY/EXOSCALE_API_SECRET/EXOSCALE_ZONE→ 用--nodes=min:max:name声明每个节点组的边界 → 以 Helm 或 Manifest 方式部署。整个过程只针对 SKS Nodepool 与 Instance Pool 两类节点组生效,且遵循"最小为 1、上限取配额、缩容走驱逐"的实现约束。深入阅读 exoscale_cloud_provider.go、exoscale_manager.go 与两个节点组实现文件,可以进一步理解节点发现、配额兜底与异步等待收敛的底层机制。

【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询