
Autoscaler 项目实战在 Hetzner Cloud 上部署与配置 Cluster Autoscaler 完整指南【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscalerCluster Autoscaler 是 Kubernetes 官方 autoscaler 仓库当前项目autoscaler中的核心组件它根据集群中待调度 Pod 的资源需求自动扩缩工作节点。Hetzner Cloud 是该仓库cluster-autoscaler/cloudprovider/hetzner目录下正式支持的云提供商实现之一负责直接通过 Hetzner Cloud API 创建、删除云服务器从而把无服务器可调度与服务器过剩两种状态自动翻译为真实的机器增删。本文以 cluster-autoscaler/cloudprovider/hetzner/README.md 为主线结合仓库源码与示例完整讲解其环境变量配置、--nodes节点组定义、新旧两套配置格式、部署清单、开发构建与调试方法帮助你在一小时内把该云提供商接入自己的 Hetzner 集群。Hetzner Cloud 云提供商做了什么cluster-autoscaler/cloudprovider/hetzner目录下的实现下文统称 Hetzner Provider以官方hcloud-goSDK 为底层客户端代码 vendor 在cluster-autoscaler/cloudprovider/hetzner/hcloud-go/hcloud下承担两项核心职责扩缩决策的数据来源通过 hetzner_servers_cache.go 定期拉取项目内全部服务器并按节点组标签过滤为 Cluster Autoscaler 提供每个节点组的真实实例列表扩缩动作的执行者通过 hetzner_node_group.go 中IncreaseSize/DeleteNodes完成服务器创建与删除直接调用 Hetzner API。值得注意的是Hetzner Cloud 没有托管节点组概念因此该实现采用标签归组策略每台服务器创建时都会被强制打上内部标签hcloud/node-group源码常量nodeGroupLabel见 hetzner_cloud_provider.goCluster Autoscaler 靠该标签识别某台服务器属于哪个节点组。这也是后续配置中--nodes名称、nodeConfigs键名与serverLabels必须互相匹配的底层原因。配置概览必需与可选环境变量Hetzner Provider 的所有配置都通过环境变量注入这是它与其他云提供商如 GCE/AWS 使用配置文件或实例元数据最大的不同。核心配置项完整清单如下对应 hetzner_manager.go 中的解析逻辑环境变量必需默认值说明HCLOUD_TOKEN是无Hetzner Cloud API TokennewManager中为空即报错退出源码 hetzner_manager.goHCLOUD_CLOUD_INIT视情况*无Base64 编码的 Cloud Init YAML用于新服务器加入集群HCLOUD_IMAGE否ubuntu-20.04镜像名 / 镜像 ID / 标签选择器见镜像选择一节HCLOUD_CLUSTER_CONFIG视情况*无新格式 Base64 编码 JSON取代上述两个变量HCLOUD_CLUSTER_CONFIG_FILE视情况*无新格式的 JSON 文件路径不要求 Base64 编码适合节点池很多的场景避免环境变量过长HCLOUD_NETWORK否空集群所用私有网络的 ID 或名称HCLOUD_FIREWALL否空集群级防火墙的 ID 或名称HCLOUD_SSH_KEY否空允许访问新服务器的 SSH Key 的 ID 或名称HCLOUD_PUBLIC_IPV4否true是否创建公网 IPv4 地址HCLOUD_PUBLIC_IPV6否true是否创建公网 IPv6 地址HCLOUD_SERVER_CREATION_TIMEOUT否5分钟单台服务器创建超时0时使用默认值源码 hetzner_manager.go默认常量serverCreateTimeoutDefaultHCLOUD_ENDPOINT否官方 API 地址自定义 API Endpoint多用于测试环境源码 hetzner_manager.go* 关于视情况HCLOUD_CLOUD_INIT旧格式与HCLOUD_CLUSTER_CONFIG/HCLOUD_CLUSTER_CONFIG_FILE新格式三选一必填。源码中明确校验三者皆空时直接报错neither HCLOUD_CLUSTER_CONFIG, HCLOUD_CLOUD_INIT nor HCLOUD_CLUSTER_CONFIG_FILE is specified见 hetzner_manager.go。旧格式HCLOUD_CLOUD_INITHCLOUD_IMAGE这是最直接的配置方式对应源码中的LegacyConfig结构体hetzner_manager.goHCLOUD_TOKENyour-token HCLOUD_CLOUD_INIT$(base64 -w0 cloud-init.txt) # 读取文本并 Base64 编码 HCLOUD_IMAGEubuntu-20.04其中HCLOUD_IMAGE支持三种取值源码 hetzner_node_group.go 的findImage处理镜像名称如ubuntu-20.04镜像 ID如15512617标签选择器如customized_ubuntutrue此时会筛选该项目下打了该标签的自定义快照Snapshot并取创建时间最新的一张排序参数created:desc。新格式HCLOUD_CLUSTER_CONFIG/HCLOUD_CLUSTER_CONFIG_FILE新格式用一个 JSON 统一描述所有节点池取代旧格式中的HCLOUD_CLOUD_INIT与HCLOUD_IMAGE两个变量是官方推荐的配置方式。其完整结构如下文档原文字段注释与源码ClusterConfig/NodeConfig结构体一一对应见 hetzner_manager.go{ imagesForArch: { arm64: , amd64: }, defaultSubnetIPRange: 10.0.0.0/16, nodeConfigs: { pool1: { cloudInit: , labels: { node.kubernetes.io/role: autoscaler-node }, serverLabels: { my-label: my-value }, taints: [ { key: node.kubernetes.io/role, value: autoscaler-node, effect: NoExecute } ], subnetIPRange: 10.0.0.0/24, firewalls: [my-pool1-firewall] } } }各字段含义与注意点imagesForArch按架构arm64/amd64指定镜像格式与HCLOUD_IMAGE相同镜像名 / ID / 标签选择器用于支持 ARM 与 x86 混合节点池。defaultSubnetIPRange可选全局默认子网 CIDR。仅对私有网络生效必须保证该子网已存在于你的私有网络中且使用 CIDR 记法。未设置时使用 Hetzner Cloud 默认值。nodeConfigs以节点池名必须与--nodes中的 name 段一致为键的映射每个池都必须有对应配置否则启动时直接Fatal见 hetzner_cloud_provider.go。cloudInit该池专用的 Cloud Init注意不要重复 Base64 编码JSON 本身已经是明文文本labels模拟的 Kubernetes 节点标签用于影响 Autoscaler 的调度决策见下节serverLabels创建服务器时直接通过 Hetzner API 打到云服务器上的标签会与内部强制标签cluster.autoscaler.nodeGroupLabel合并后再发给 API源码 hetzner_node_group.go。这些标签可见于 Hetzner Cloud Console可用于 API 过滤或满足依赖服务器标签鉴权的集群引导工具如 kops的需求taints该池节点的污点列表key / value / effect 三元组用于把该池节点标记为不可随意调度subnetIPRange可选该池专属子网 CIDR覆盖全局defaultSubnetIPRange同样必须是私有网络中已存在的子网firewalls可选该池额外附加的防火墙 ID 或名称列表与集群级HCLOUD_FIREWALL合并按 ID 去重使特定池可以附加额外规则而不放松整个集群的防火墙仅新格式可用见 hetzner_cloud_provider.go 的buildServerCreateFirewalls。HCLOUD_CLUSTER_CONFIG_FILE与HCLOUD_CLUSTER_CONFIG内容等价区别仅是前者读文件、后者解 Base64源码 hetzner_manager.go。当节点池很多导致环境变量过长时应改用文件方式。镜像选择优先级新格式下镜像解析顺序有严格优先级文档原文源码实现见 hetzner_node_group.go若某个节点池有自己的imagesForArch该池使用自己的镜像若节点池未配置imagesForArch回退使用全局imagesForArch若两者都未配置即使用旧格式使用旧环境变量HCLOUD_IMAGE。最终再根据服务器架构ArchitectureARM/ArchitectureX86从ImageList中挑选对应的Arm64/Amd64字段。该优先级逻辑在测试文件 hetzner_node_group_test.go 中有完整用例覆盖包括池级配置优先缺失回退全局显式 nil 回退全局三种场景。子网 IP 范围与网络校验defaultSubnetIPRange全局与subnetIPRange池级可覆盖前者用于把节点放入指定的私有网络 IP 段。两个强制约束由源码保证配置的 CIDR 必须实际存在于所绑定的私有网络中启动时通过isIpRangeInNetwork校验源码 hetzner_cloud_provider.go不匹配直接Fatal退出绑定子网的场景下服务器创建流程会调整为先以不启动的方式创建服务器 → 通过Server.AttachToNetwork附加到指定 IP 段 → 再Poweron开机源码 hetzner_node_group.go。未配置子网时服务器随网络直接创建并启动。定义节点组--nodes命令行参数节点组Node Group是 Autoscaler 扩缩容的最小单元。Hetzner Provider 要求通过--nodesmin-servers:max-servers:instance-type:region:name格式定义每个 flag 创建一个节点池可重复指定多个。源码解析在 hetzner_cloud_provider.go 的createNodePoolSpec按:切分为 5 段前三段分别是实例类型、区域、池名前两段必须可解析为整数否则报错expected format min-servers:max-servers:machine-type:region:name。文档给出的多池示例--nodes1:10:CPX51:FSN1:pool1 --nodes1:10:CPX51:NBG1:pool2 --nodes1:10:CX41:NBG1:pool3含义是pool1在 FSN1 区域用 CPX51pool2在 NBG1 区域用 CPX51pool3在 NBG1 区域用 CX41三个池的最小 1 台、最大 10 台。以下几点需要特别注意实例类型与区域均会被转成小写源码 hetzner_cloud_provider.go因此fsn1、FSN1写法等价池名有正则约束必须匹配^[a-z0-9A-Z][a-z0-9A-Z\-\.\_]*[a-z0-9A-Z]$|^[a-z0-9A-Z]{1}$源码 hetzner_cloud_provider.go即只允许字母、数字、连字符、点、下划线新格式下每个池名必须在nodeConfigs中有对应键否则进程Fatal退出池名同时也是服务器标签hcloud/node-group的值Cluster Autoscaler 靠它在 hetzner_servers_cache.go 中按节点组过滤服务器并据此初始化targetSize。部署到集群RBAC 与 Deployment 示例仓库提供了可直接落地的部署清单 examples/cluster-autoscaler-run-on-master.yaml内含 ServiceAccount、ClusterRole、Role、ClusterRoleBinding、RoleBinding 以及 Deployment 六段资源。其中 Deployment 的关键设计镜像registry.k8s.io/autoscaling/cluster-autoscaler:latest可替换为自定义镜像命令参数--cloud-providerhetzner、--stderrthresholdinfo、--nodes1:10:CPX11:FSN1:pool1环境变量HCLOUD_TOKEN从名为hcloud的 Secret键token中读取HCLOUD_CLOUD_INIT直接以your-cloud-init-data-base64-encoded占位需替换为实际 Base64 数据HCLOUD_SSH_KEY、HCLOUD_NETWORK以注释形式给出可选示例调度策略通过 Tolerationnode-role.kubernetes.io/control-plane:NoSchedule与 Node Affinity强制调度到控制平面节点把 Autoscaler 钉在 master 上注释明确说明这允许集群在需要时把工作节点缩容到 0监控注解prometheus.io/scrape: true与prometheus.io/port: 8085配合 hetzner_metrics.go 注册的hcloud_api_requests_total、hcloud_api_request_duration_seconds、hcloud_api_in_flight_requests三组指标做 API 可观测性。Cloud Init 示例解读examples/cloud-init.txt 是配套的节点引导脚本示例面向 Kubernetes 1.20.1安装kubelet/kubeadm/kubectl1.20.1 并apt-mark hold锁版本配置 kubelet 的--cloud-providerexternal配置 Docker 以systemd作为 cgroup 驱动、overlay2存储驱动、日志上限 100m最后一行kubeadm join master-ip --token token --discovery-token-ca-cert-hash sha256:hash是加入集群的占位命令必须替换为你集群实际输出的 join 参数。实际使用时请先base64 -w0 cloud-init.txt得到编码结果再填入 Deployment 的HCLOUD_CLOUD_INIT或放入新格式 JSON 的cloudInit字段注意不要二次编码。请务必核对示例中的 Kubernetes / Docker 版本与你的集群版本匹配示例文件面向 1.20.1当前仓库仅将其作为引导流程范本。核心实现剖析Autoscaler 如何驱动 Hetzner 云服务器启动初始化链路进程启动时BuildHetznerhetzner_cloud_provider.go按以下顺序完成初始化newManager()校验 Token、解析三种配置来源、初始化 hcloud 客户端带 2 倍指数退避的轮询参数与 debug writer若使用新格式且nodeConfigs为空 → 直接Fatal解析全局defaultSubnetIPRange并校验其属于所绑定的网络遍历所有--nodesspec逐个创建hetznerNodeGroup新格式下读取该池的 Placement Group、防火墙列表、子网配置校验放置组总量不超过maxPlacementGroupSize 10汇总放置组总容量若同一放置组被多个池共享且总maxSize超过 10启动即失败Hetzner 放置组硬限制。扩缩容动作的并发处理Hetzner 没有服务器组概念扩容需逐台创建。IncreaseSizehetzner_node_group.go的实现要点先校验delta 0、目标大小不超过maxSize通过serverTypeAvailable检查该实例类型在目标区域是否有定价即可用性不可用则报错对每台服务器并发调用createServersync.WaitGroup error channel部分创建失败时收集错误并回退actualDelta用errors.Join汇总返回让 Autoscaler 可尝试其他节点组结束后重建服务器缓存并基于真实服务器数重置targetSize。缩容的DeleteNodeshetzner_node_group.go对称实现校验不低于minSize并发按节点删除对应服务器deleteByNode通过节点 ProviderID 或名称在缓存中反查服务器再调用 API 删除同样聚合错误并刷新缓存。服务器缓存与状态映射为避免每个扩缩循环都打满 API服务器列表以 1 分钟 TTL 缓存hetzner_servers_cache.go且过期检查带 560 秒随机抖动jitter防止多副本同时失效打爆 API。节点状态到 Cloud Provider 实例状态的映射见toInstanceStatushetzner_node_group.gorunning→ 运行中starting/initializing→ 创建中deleting/stopping→ 删除中其余状态标记为错误实例。混合集群兼容serverForNodehetzner_manager.go只认hcloud://前缀的 ProviderID其他前缀如 Hetzner Robot 或其他云直接返回无此服务器从而允许 Hetzner Cloud 与 Robot 等混合部署的集群中Autoscaler 只管理自己的节点而不误删他人机器。开发与构建本地编译与镜像发布文档给出的开发流程需在cluster-autoscaler根目录执行# 1. 编译 cluster-autoscaler 二进制 make build-in-docker # 2. 构建镜像 docker build -t hetzner/cluster-autoscaler:dev . # 3. 推送到 Docker Hub docker push hetzner/cluster-autoscaler:dev更新 vendored hcloud-go该实现将官方hcloud-goSDK 以 vendor 形式内嵌在cluster-autoscaler/cloudprovider/hetzner/hcloud-go下。升级方式由 hack/update-vendor.sh 脚本完成cd cluster-autoscaler/cloudprovider/hetzner UPSTREAM_REFv2.0.0 hack/update-vendor.sh git add hcloud-go/脚本逻辑为按UPSTREAM_REF默认main浅克隆上游仓库 → 删除非.go/LICENSE文件与测试文件 → 用sed把模块路径从github.com/hetznercloud/hcloud-go/v2/整体改写为仓库内的k8s.io/autoscaler/cluster-autoscaler/cloudprovider/hetzner/hcloud-go/保证编译期内不依赖外部网络。调试打开 Hetzner API 请求日志排查问题时把 Autoscaler 日志级别提到 5 或以上./cluster-autoscaler --cloud-providerhetzner ... --v5此时两处日志会开启完整 API 请求/响应含请求头与响应体——由 hetzner_debug_writer.go 实现所有写入内容以klog.V(5)输出配合 hetzner_manager.go 中hcloud.WithDebugWriter(debugWriter{})注入服务器缓存拉取动作——servers()在每次真正请求 Hetzner API 时打印Fetching servers from Hetzner API警告日志hetzner_servers_cache.go用于判断缓存是否反复失效。结合上一节提到的 Prometheus 指标可以在扩缩异常时同时确认决策是否正确与API 调用是否成功/限流两个层面。小结Hetzner Cloud 云提供商把 Kubernetes Cluster Autoscaler 与 Hetzner 的无节点组云模型优雅地连接起来通过--nodes定义池、通过环境变量注入凭证与引导配置、通过hcloud/node-group标签归组识别服务器、通过并发 API 调用完成扩缩。建议生产环境优先采用HCLOUD_CLUSTER_CONFIG_FILE新格式管理多个节点池并配合--v5与hcloud_api_*指标做日常巡检。更多云提供商实现可对比参考仓库内 cluster-autoscaler/cloudprovider 目录下的其他 provider了解 autoscaler 云提供商抽象的统一接口设计。【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考