自动扩缩容:3 种策略的适用场景

发布时间:2026/7/5 2:13:06
自动扩缩容:3 种策略的适用场景 为什么需要自动扩缩容API 服务的流量不是恒定的:工作日 vs 周末(白天高、夜间低)营销活动(突发 5-10 倍)日常波动(±20%)固定容量的问题:容量过小:流量高峰打爆,服务不可用容量过大:闲时浪费,白付钱自动扩缩容:跟着流量走,既不爆也不浪费。3 种策略策略 1:反应式扩缩容 (Reactive)按当前指标(CPU / 内存 / QPS)决定扩缩容。Kubernetes HPA 默认就是这种。apiVersion:autoscaling/v2kind:HorizontalPodAutoscalermetadata:name:api-server-hpaspec:scaleTargetRef:apiVersion:apps/v1kind:Deploymentname:api-serverminReplicas:2maxReplicas:20metrics:-type:Resourceresource:name:cputarget:type:UtilizationaverageUtilization:70优点:实现简单,K8s 原生支持。缺点:有延迟。流量突增 → CPU 涨 → 触发扩容 → 新 pod 启动(30-60s)→ 接流量。这 30-60s 内服务可能已经被打爆。适用:流量波动可预测、扩缩容时间窗口够用的场景(日常波动)。策略 2:预测式扩缩容 (Predictive)按历史数据预测未来流量,提前扩。K8s 1.18 支持(基于 historical metrics)。# 伪代码defpredict_traffic(history):基于过去 7 天的同时段流量,预测未来 1 小时now_hourdatetime.now().hour same_hour_last_week[hforhinhistoryifh[ts].hournow_hour]returnmax(same_hour_last_week)*1.2# 加 20% buffer优点:提前扩,避免反应式的延迟。缺点:预测不一定准。营销活动 / 突发新闻等反常流量预测不到。适用:有规律的业务(电商、新闻、SaaS)。策略 3:主动式扩缩容 (Scheduled)按已知时间表(calendar)提前扩。比如每周一早上 9 点开会,8:55 触发扩容。apiVersion:k8s.alibabacloud.com/v1alpha1kind:CronHPAmetadata:name:cron-hpaspec:scaleTargetRef:apiVersion:apps/v1kind:Deploymentname:api-serverjobs:-name:scale-up-for-monday-meetingschedule:0 8 * * 1# 每周一 8:00targetSize:10-name:scale-down-after-meetingschedule:30 9 * * 1# 每周一 9:30targetSize:2优点:完全可控,适合已知规律。缺点:维护 calendar 麻烦,临时活动要手动加。适用:明确的业务规律(发布会、营销日、周会)。混合策略(实战)实际生产环境一般三种结合:基础容量(Scheduled): 工作日 9-18: 10 个 pod 周末 / 夜间: 2 个 pod ↓ 触发条件:流量超阈值 ↓ 弹性容量(Reactive): CPU 70% → 自动加 pod CPU 30% → 自动减 pod ↓ 触发条件:历史预测异常 ↓ 预测预警(Predictive): 检测到 7 天同时段流量比当前高 50% → 提前扩容效果:既不浪费(基础容量合理),也不爆(弹性扩容 预测预警)。5 个常见坑1. 冷启动延迟新 pod 启动 → 加载配置 → 建连接池 → 接流量,通常 30-60s。这段时间流量已经来了,pod 没准备好。对策:Pre-pod 预热:启动时就建好连接池(不等到第一个请求)Pod 启动探针:不要等到ready才接流量,改成启动就接HPA 提前扩容:CPU 到 50% 就开始扩,留 buffer2. 缩容过激CPU 突然从 80% 掉到 10% → HPA 立刻缩到 2 个 pod → 流量又涨回来 → 又要扩。反复横跳。对策:缩容冷却时间(K8s 默认 5 分钟,调大到 15 分钟)平滑缩容(每次只缩 1-2 个 pod,不要一次缩一半)3. 资源请求设错resources.requests设小了 → K8s 调度时给的资源少 → pod 实际用更多 → 被限流。对策:压测定 request(不是估,是用 loadtest 测出来)留 30% buffer 给突发4. 单 region 单可用区所有 pod 都在一个可用区 → AZ 挂了全挂。对策:podAntiAffinity 强制多 AZ 分布多 region 部署(主 region 灾备 region)5. 数据库扛不住K8s pod 扩到 50 个,但数据库 max_connections 151。50 个 pod × 10 个连接 500 个连接,数据库直接拒。对策:用 PgBouncer / 连接池(100 个 pod 共享 200 个 DB 连接)数据库是瓶颈时,pod 扩再多也没用,要先解决 DB我们的做法做 SERP API 时,3 种都用了:Scheduled:工作日 9-22 / 周末 10-18 设 4-6 个 podReactive:CPU 70% 加 pod, 30% 减 pod,缩容冷却 10 分钟Predictive:每天 18:00 检查明天同时段历史,异常高就提前扩效果:全年 SLA 99.95%(预算 99.9%),月度成本比固定 6 pod 方案低 25%。监控指标指标含义告警阈值pod_count当前 pod 数接近 maxReplicascpu_util平均 CPU持续 80% 5 分钟pending_pods等待调度的 pod 0 持续 1 分钟scale_events_per_hour扩缩容频率 5 次/小时(横跳)cold_start_latency新 pod 首请求耗时P99 2s小结自动扩缩容没有银弹,3 种策略各有适用场景。生产环境几乎都是混合用:Scheduled 管规律Reactive 管波动Predictive 管趋势冷启动 缩容过激 数据库瓶颈是 3 个最常见的坑,提前预防比事后救火好。SerpBase 实践SerpBase K8s deployment 混合扩缩容:Scheduled:工作日 4-6 pod,周末 2-3 podReactive:CPU 70% 加 pod, 30% 减 podPredictive:每天 18:00 检查明天同时段历史效果:全年 SLA 99.95%,月度成本比固定 6 pod 方案低 25%。*本文来自 SerpBase 工程团队。