利用阿里云ACK(容器服务Kubernetes版)与ESS(弹性伸缩服务)实现Kubernetes节点自动扩缩容,其核心是借助ACK集成的Cluster Autoscaler(CA)组件,联动ESS伸缩组,实现基于Pod调度需求和资源利用率的节点自动化弹性伸缩。
一、 核心原理与架构
该方案采用两层自动伸缩架构,分别为工作负载层和节点层,以实现资源的精细化弹性管理。
| 组件/层级 | 作用 | 触发条件 | 响应时间 | 管理对象 |
|---|---|---|---|---|
| Cluster Autoscaler (CA) | 节点层伸缩的大脑,监控集群资源状态并决策节点的增删。 | 1. 存在因资源不足而无法调度的Pending Pod。 2. 节点资源利用率过低且其上Pod可迁移至其他节点。 |
扩容约3-5分钟,缩容取决于配置。 | ECS实例(通过ESS伸缩组) |
| 弹性伸缩服务 (ESS) | 基础设施层服务,负责根据CA的指令,在伸缩组内增删ECS实例。 | 接收CA通过云API发起的伸缩请求。 | 取决于ECS启动或释放时间。 | ECS实例伸缩组 |
| 节点池 (Node Pool) | ACK的核心概念,将具有相同配置(如规格、镜像、标签)的节点作为一个逻辑单元进行管理。一个节点池对应一个ESS伸缩组。 | CA以节点池为单位进行扩缩容决策。 | 无 | Kubernetes节点组 |
自动扩缩容工作流程如下:
- 扩容流程 :当用户创建或工作负载(如HPA)增加Pod副本时,如果集群现有节点资源不足,Pod将进入
Pending状态。CA组件检测到PendingPod后,会模拟调度,判断如果为某个节点池增加节点是否能调度成功。若模拟成功,CA即通过云API调用与该节点池绑定的ESS伸缩组,执行扩容操作。新创建的ECS实例会自动运行ACK维护的cloud-init脚本,完成Kubernetes Node的初始化并加入集群,最终Pod被调度到新节点上运行。 - 缩容流程 :CA会定期(默认每10秒)扫描所有节点。当某个节点满足所有Pod都可以被调度到其他节点(考虑Pod Disruption Budget),且该节点的资源利用率持续低于设定阈值(默认50%)一段时间后,CA会将其标记为可移除。CA首先安全驱逐(
cordon和drain)该节点上的Pod,待Pod迁移完成后,再通知ESS伸缩组释放对应的ECS实例。
二、 详细配置步骤
以下配置流程分为两步:首先为集群全局开启节点伸缩功能,然后为特定节点池配置自动扩缩容策略。
步骤一:为ACK集群开启节点自动伸缩功能
这是节点池自动伸缩策略生效的前提。
- 登录容器服务管理控制台。
- 在集群列表页面,单击目标集群名称,进入集群详情页。
- 在左侧导航栏,选择节点管理 > 节点池。
- 在节点池 页面顶部,找到节点伸缩 状态,单击其后的去配置按钮。
- 在弹窗中,确认并启用节点自动伸缩功能。此操作会在集群中部署或激活Cluster Autoscaler组件。
步骤二:创建或配置支持自动伸缩的节点池
可以新建一个节点池,也可以修改已有节点池的配置。
- 在节点池 页面,单击创建节点池 或目标节点池右侧的编辑。
- 在配置页面中,完成基础配置(如节点数量、实例规格、系统盘、登录方式等)。
- 关键步骤在于伸缩配置 部分:
- 扩缩容模式 :选择自动模式(部分界面描述为"启用自动伸缩")。
- 伸缩组配置 :
- 最小实例数 :设置该节点池在任何情况下都应保留的最少节点数量,用于保障基础服务。例如设置为
1。 - 最大实例数 :设置该节点池允许扩容到的最大节点数量,用于控制成本和规模上限。例如设置为
10。
- 最小实例数 :设置该节点池在任何情况下都应保留的最少节点数量,用于保障基础服务。例如设置为
- 扩缩容策略 (可选):
- 优先级策略:缩容时,优先移除最新创建的实例。
- 均衡分布策略:缩容时,系统会先筛选ECS实例的可用区,再选择最新创建的实例进行移除,以保持各可用区节点数量大致均衡。
- 完成其他配置(如节点标签、污点),并单击确认配置。
步骤三:部署测试应用验证伸缩效果
创建一个资源请求超出集群现有容量的Pod,触发自动扩容。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: resource-stress-test
spec:
replicas: 5 # 启动5个副本
selector:
matchLabels:
app: stress-test
template:
metadata:
labels:
app: stress-test
spec:
containers:
- name: busybox
image: busybox:latest
# 为每个Pod请求2核CPU和4Gi内存,快速耗尽集群资源
resources:
requests:
cpu: "2000m"
memory: "4Gi"
command: ["sh", "-c", "sleep 86400"]
部署上述YAML后,部分Pod将因资源不足而处于Pending状态。随后,可以执行以下命令或在控制台观察节点变化:
bash
# 观察Pod状态变化
kubectl get pods -w
# 观察节点数量和状态
kubectl get nodes -w
# 查看Cluster Autoscaler日志(ACK托管的CA通常在kube-system命名空间)
kubectl logs -f deployment/cluster-autoscaler -n kube-system
当Pod成功调度到新扩容的节点后,再删除测试Deployment。等待一段时间(默认配置下约10分钟后),CA会开始评估并执行缩容,释放空闲节点。
三、 最佳实践与关键注意事项
-
节点池设计与隔离 :根据业务特性(如计算密集型、内存密集型、GPU任务)创建不同的节点池,并为节点池打上对应的标签(
node-label)或设置污点(taint)。在部署Pod时,使用nodeSelector或affinity将Pod调度到指定节点池,实现资源池的精细化管理与弹性伸缩。 -
结合工作负载层弹性(HPA):实现完整的弹性链条。建议配置HPA(Horizontal Pod Autoscaler),使其基于应用指标(如CPU利用率)自动调整Pod副本数。当Pod因副本数增加而无法调度时,再由CA触发节点扩容。这种"HPA + CA"的组合是应对流量波动的标准方案。
-
配置缩容保护与延迟 :为防止频繁伸缩,尤其是短时间波动造成的抖动,应合理配置CA的缩容参数。例如,可以编辑
cluster-autoscaler的Deployment,增加--scale-down-unneeded-time(节点空闲多长时间后才考虑缩容)和--scale-down-delay-after-add(扩容后多久才开始评估缩容)参数。yaml# 示例:修改CA启动参数(具体操作请参考ACK文档) spec: containers: - command: - ./cluster-autoscaler - --scale-down-enabled=true - --scale-down-unneeded-time=10m # 节点连续空闲10分钟才考虑缩容 - --scale-down-delay-after-add=10m # 扩容后,至少等10分钟再评估缩容 - --scale-down-utilization-threshold=0.5 # 节点利用率低于50%视为"空闲" -
系统组件保护 :确保核心系统组件(如CoreDNS、Metrics Server、Ingress Controller)不会被驱逐导致服务中断。一方面,可以为这些Pod配置合适的
PodDisruptionBudget;另一方面,更推荐的做法是将其部署在不开启自动伸缩的专用节点池或虚拟节点(Virtual Node)上 。例如,可以配置如下节点亲和性,将ack-node-local-dns-admission-controller等组件固定在非弹性节点上:yamlnodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "k8s.aliyun.com" # 假设此标签标识弹性节点池 operator: "NotIn" values: ["true"] -
成本与配额控制 :
- 设置合理的伸缩边界:通过节点池的"最小/最大实例数"严格控制弹性范围,防止因配置错误或程序Bug导致成本失控。
- 关注ECS配额 :确保账号在目标地域拥有足够的ECS实例配额(
vCPU和数量),特别是计划扩容到的最大规模。 - 利用混合计费实例:在伸缩组配置中混合使用按量付费实例和抢占式实例,可以在保障弹性的同时显著降低成本。
-
监控与告警 :务必配置对节点池伸缩活动的监控告警。
- 监控ESS伸缩组的"伸缩活动"状态,关注扩容失败或异常终止的事件。
- 在云监控中设置告警规则,例如当节点池节点数量达到最大值的80%时发出告警,提醒可能需要调整配额或排查应用资源使用是否异常。