本文目录导读:

弹性伸缩(Auto Scaling)是一个系统根据预先设定的规则(如CPU、内存、请求量等指标),自动增加或减少计算资源(通常是服务器实例)的能力,它通常不是一个单一的功能,而是一整套基础设施的配合。
下面是实现弹性伸缩的核心原理、关键步骤以及不同技术栈的最佳实践。
核心原理:循环的三个步骤
- 监控:采集系统负载指标(CPU、内存、网络IO、请求队列长度、自定义业务指标)。
- 决策:根据监控数据与预设阈值进行比较(
CPU > 75% 持续5分钟)。 - 执行:调用API增加或减少资源,并进行相应的配置(如加入/移出负载均衡器)。
关键准备:你需要先做好的4件事
在配置自动伸缩之前,必须打好以下基础,否则伸缩会导致服务故障:
- 无状态化(最重要):
- 问题:如果服务器上存了Session、用户上传的文件(本地磁盘),新的服务器启动后无法处理请求,旧服务器被销毁后数据丢失。
- 解决:Session集中到Redis/数据库;文件存储到S3/OSS等对象存储;日志统一发送到中心化日志服务。
- 基础设施即代码:
使用配置管理工具(Ansible, Chef, Puppet)或容器化打包,确保新启动的实例是“金丝雀”般的标准环境。
- 健康检查:
负载均衡(如Nginx, AWS ALB,Kubernetes Service)必须配置HTTP/TCP健康检查,确保只将流量发给“就绪”的新实例。
- 启动配置:
准备好自定义的AMI(机器镜像)、Docker镜像或启动脚本(User Data/Cloud-init),让新机器启动后自动完成注册到ELB、挂载配置中心等动作。
不同场景的实施方案
使用云服务商的托管服务(最推荐,SRE/运维首选)
云厂商提供了最成熟、最省心的方案,以 AWS 为例,其他云(阿里云、腾讯云、Azure)概念类似。
-
组件:
- 启动模板:定义AMI类型、实例大小、安全组、密钥对。
- Auto Scaling Group (ASG):
- 指定最小/最大/期望实例数。
- 关联负载均衡器(ELB)。
- 伸缩策略:
- 动态伸缩:基于CloudWatch指标(如CPU>70%加1台,CPU<30%减1台)。
- 计划伸缩:电商大促前1小时自动扩容50台,活动结束后自动缩容到10台。
- 预测伸缩:基于历史流量机器学习模型提前扩容。
-
示例(AWS CLI/控制台):
# 1. 创建启动模板 aws ec2 create-launch-template --launch-template-name my-web-template --region us-east-1 --launch-template-data '{"ImageId":"ami-0abcdef1234567890","InstanceType":"t3.medium","SecurityGroupIds":["sg-xxxxxxxxx"]}' # 2. 创建伸缩组 aws autoscaling create-auto-scaling-group --auto-scaling-group-name my-web-asg --launch-template "LaunchTemplateName=my-web-template,Version=1" --min-size 2 --max-size 10 --desired-capacity 2 --vpc-zone-identifier "subnet-xxx,subnet-yyy" --target-group-arns "arn:aws:elasticloadbalancing:...:targetgroup/my-tg/xxx" # 3. 创建基于CPU的动态伸缩策略 aws autoscaling put-scaling-policy --auto-scaling-group-name my-web-asg --policy-name cpu-scale-out --scaling-adjustment 1 --adjustment-type ChangeInCapacity --cooldown 300 aws autoscaling put-scaling-policy --auto-scaling-group-name my-web-asg --policy-name cpu-scale-in --scaling-adjustment -1 --adjustment-type ChangeInCapacity --cooldown 300 -
优势:与云服务深度集成,运维成本最低。
基于 Kubernetes(K8s)的弹性伸缩(微服务首选)
K8s 原生提供了非常强大且多层次的弹性伸缩机制。
-
HPA (Horizontal Pod Autoscaler,水平Pod自动伸缩):根据CPU、内存或自定义指标(如QPS、连接数)自动调整Pod的数量。
-
VPA (Vertical Pod Autoscaler,垂直Pod自动伸缩):自动调整Pod的CPU/内存请求和限制(适用于有状态应用)。
-
Cluster Autoscaler (CA,集群节点自动伸缩):当Pod因为资源不足而无法调度时,自动增加集群中的节点(虚拟机/物理机);当节点利用率低时,移除节点。
-
示例(HPA YAML):
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-service-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-service minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Pods pods: metric: name: requests-per-second # 自定义指标 target: type: AverageValue averageValue: 1000 -
优势:粒度细(Pod级别)、资源利用率极高、适合微服务架构。
自建机房 / 裸金属(传统运维 / 私有云)
如果没有云API,需要自己构建控制逻辑。
- 方案:
- 监控:Prometheus + Grafana / Zabbix。
- 自动化工具:Ansible + CMDB(配置管理数据库) + 虚拟化平台API(如OpenStack, vCenter)。
- 工作流:
Prometheus告警 -> Webhook -> 自研脚本/Ansible Tower -> 调用vCenter API克隆VM -> 配置IP -> 加入Nginx upstream。
- 缺点:开发工作量大,对硬件准备周期有要求(通常需要预留热备机器),不推荐小团队尝试。
常见问题与最佳实践
- 冷启动延迟:
- 问题:新实例启动需要1-3分钟,流量高峰可能已经结束了。
- 解决:
- 缓冲池:维持一个很小的“热身”实例池(如比最小值多1-2台)。
- 弹性缓冲:使用队列缓冲请求(如SQS+Kafka),伸缩的是消费者数量。
- 预测伸缩:基于历史流量提前扩容,而不是等CPU高了再扩。
- 缩容保护(优雅关闭):
- 问题:突然销毁实例会导致正在处理的请求中断。
- 解决:
- 配置连接耗尽:负载均衡器停止向该实例发送新请求,但保持已有连接直到请求完成(通常设置超时时间如300秒)。
- 生命周期钩子:在实例被销毁前,执行一段自定义脚本(如通知注册中心下架、drain连接)。
- 防止抖动(Thrashing):
- 问题:频繁增删实例导致系统不稳定。
- 解决:设置冷却时间(Cooldown/Stabilization Window,通常300-600秒),扩容后一段时间内不允许再次扩容或缩容。
- 有状态服务怎么伸缩?
- 数据库、Redis、Kafka等通常使用垂直伸缩(升级规格)或分片,如果必须水平伸缩,需要使用StatefulSet(K8s)配合持久化存储和高效的集群分片/灾备方案(通常非常复杂)。
最佳实践路线图
- 应用层:确保无状态,用外部数据库、缓存、对象存储替代本地存储。
- 基础设施层:
- 小项目/单体应用:使用云厂商的 Auto Scaling Group + 启动模板 + 计划/动态策略。
- 微服务/容器化:使用 Kubernetes (HPA + Cluster Autoscaler)。
- Serverless:如果能接受冷启动,直接使用 AWS Lambda / Azure Functions,预留并发,伸缩完全由云平台管理。
- 监控与告警:设置好高水位(扩容触发)、低水位(缩容触发)和紧急水位(强制扩容)。
- 测试:一定要做压测,验证伸缩是否真的能扛住流量,以及缩容后服务是否正常。
一句话总结:弹性伸缩不是“能自动加机器”就行,它要求你的整个架构(应用、网络、存储)都必须是为“随时创建和销毁”而设计的。