SLA/SLO/SLI 与容量规划
SRE 的核心是量化可靠性。SLA/SLO/SLI 定义了"多可靠算足够可靠",容量规划确保资源满足这些目标。
1. 定义区分
| 缩写 | 全称 | 含义 | 示例 |
|---|---|---|---|
| SLI | Service Level Indicator | 服务质量指标 | 请求延迟 P99 < 200ms |
| SLO | Service Level Objective | 目标值 | 99.9% 的请求延迟 < 200ms |
| SLA | Service Level Agreement | 服务等级协议(对外承诺) | 可用性 < 99.9% 退款 10% |
SLI: 测量什么
↓
SLO: 目标值多少
↓
SLA: 达不到的后果(法务/商务)
2. SLI 选择
Google SRE Book 推荐的 SLI 类型:
四类黄金信号
| 信号 | 说明 | 指标示例 |
|---|---|---|
| 延迟 | 服务响应时间 | P50/P95/P99 延迟 |
| 流量 | 请求量 | QPS、带宽 |
| 错误 | 失败率 | HTTP 5xx 比例 |
| 饱和度 | 资源利用率 | CPU > 80%、磁盘满 |
SLI 制定原则
- 用户视角:测量用户感受到的质量
- 可量化:能够用监控工具持续测量
- 可行动:触发后知道如何改进
- 不过度:选择最关键的几个(3-5 个)
3. SLO 制定方法
可用性 SLO 参考
| SLO | 年停机时间 | 适用场景 |
|---|---|---|
| 99% | 3.65 天 | 内部工具 |
| 99.9% | 8.76 小时 | 核心业务 |
| 99.99% | 52.56 分钟 | 关键支付 |
| 99.999% | 5.26 分钟 | 极少场景 |
更高 SLO ≠ 更好。SLO 提升 10 倍,成本可能提升百倍。
错误预算
错误预算 = 1 - SLO
SLO 99.9% → 年错误预算 = 0.1% × 525600 分钟 = 525.6 分钟
每月可用预算 = 525.6 ÷ 12 ≈ 43.8 分钟
用途:
- 本月已用 30 分钟 → 谨慎发布,加强测试
- 本月已用 50 分钟 → 冻结发布,聚焦稳定性改进
多层级 SLO
组织级 SLO: 99.99%(核心业务总览)
│
├─ 产品级 SLO: 99.95%(具体产品)
│ │
│ └─ 服务级 SLO: 99.9%(单个服务)
│
└─ 基础设施 SLO: 99.999%(K8s 集群)
4. 容量规划
核心公式
所需容量 = 预测峰值 × 冗余系数 × 增长余量
预测峰值: 业务高峰期的资源需求
冗余系数: N+1 或 N+2(通常 1.3-1.5)
增长余量: 未来 3-6 个月增长预期
容量模型
| 步骤 | 方法 |
|---|---|
| 基线测量 | 日常负载下的资源使用 |
| 峰值分析 | 历史流量峰值、周期性规律 |
| 关联建模 | QPS → CPU/内存/带宽的换算关系 |
| 压力测试 | 验证容量模型 |
扩容策略
| 策略 | 触发条件 | 优点 | 缺点 |
|---|---|---|---|
| 垂直扩容 | 资源使用率持续高 | 简单 | 有上限 |
| 水平扩容 | QPS 超过阈值 | 弹性强 | 数据一致性 |
| 预测扩容 | 定时/预期高峰 | 无冷启动 | 资源闲置 |
| 按需扩容 | K8s HPA | 最省成本 | 延迟敏感 |
5. SLO-based 告警体系
传统告警按阈值触发(如 CPU > 80%),容易产生噪音。SRE 推荐基于错误预算消耗速率告警:
错误预算燃烧速率 = 当前周期内实际错误率 / (1 - SLO)
- 燃烧速率 > 1:SLO 在周期内将被耗尽(紧急)
- 燃烧速率 1/2 ~ 1:SLO 面临风险(警告)
- 燃烧速率 < 1/2:正常范围内
多窗口告警策略:
| 窗口 | 燃烧速率阈值 | 响应 SLA |
|---|---|---|
| 1 小时 | 14.4x | 页面(2 分钟响应) |
| 6 小时 | 6x | 页面 |
| 3 天 | 1x | 工单(4 小时响应) |
例如:SLO 99.9%(月错误预算 43.8 分钟),如果 1 小时内burned 超过 43.8/30 ≈ 1.46 分钟,触发 P1 告警。这种机制自动适应业务低峰和高峰,避免非工作时间误报。
6. 容量规划方法论
需求预测技术
| 方法 | 原理 | 适用 | 局限 |
|---|---|---|---|
| 定率法 | 根据业务增长目标(如 DAU × 系数)推算 | 早期、业务指标明确 | 忽略技术非线性 |
| 时间序列 | 基于历史数据(ARIMA / Prophet)预测 | 有历史数据的成熟业务 | 突变事件难预测 |
| 基准换算 | 压测得出的 QPS→资源系数 + 业务增长 | CPU/内存为主的服务 | 需定期重跑基准 |
| 排队论模型 | M/M/c 模型分析并发与延迟关系 | 高并发服务(如 API Gateway) | 假设理想化 |
云资源经济学
容量规划不仅是技术问题,更是成本问题:
| 策略 | 成本节省 | 灵活度 | 适用 |
|---|---|---|---|
| On-Demand | 0% | 最高 | 不可预测负载 |
| Reserved Instances | 40-60% | 低(1-3 年承诺) | 基线容量 |
| Savings Plans | 30-50% | 中(跨实例类型) | 多服务长期承诺 |
| Spot / Preemptible | 60-90% | 极低(可中断) | 无状态批处理 |
| Auto Scaling | 按需 | 高 | 峰谷波动大的服务 |
最佳实践:基线用 Reserved / Savings Plans,峰值用 Auto Scaling,批处理用 Spot,综合降低 30-50% 基础设施成本。
数据库容量专项
数据库扩容比普通服务更复杂,需提前规划:
| 维度 | 监控指标 | 扩容信号 | 方案 |
|---|---|---|---|
| 连接数 | active_connections / max_connections | > 70% | PgBouncer / 读写分离 |
| IOPS | read/write ops | 持续 > 80% 基线 | 升级实例 / SSD |
| 存储 | disk_usage / disk_size | > 80% | 分区归档 / 扩容 |
| 锁竞争 | lock_waits | 持续增长 | 优化查询 / 拆分事务 |
| 复制延迟 | replication_lag | > 1s | 增强从库 / 并行复制 |
7. 自动化容量治理
将容量规划从手工 spreadsheet 升级为数据驱动:
# 伪代码:基于 Prometheus 指标的自动扩缩容决策
# 1. 采集当前 QPS、CPU、内存、延迟
# 2. 根据基准模型计算理论容量上限
# 3. 如果利用率 > 70% 且趋势增长,触发扩容审批工单
# 4. 如果利用率 < 30% 持续 7 天,建议缩容或释放预留
工具链:
- Terraform:基础设施即代码,扩缩容有据可查
- KEDA:基于自定义指标(如 Kafka Lag、消息队列深度)的 Pod 级弹性
- VPA(Vertical Pod Autoscaler):自动调整 Pod 的 request/limit
- FinOps 平台:云成本可视化与优化建议(如 Kubecost、Vantage)
8. 混沌工程验证容量
压测验证了"预期内"的容量,混沌工程验证"异常情况下"的容量表现:
| 故障场景 | 注入方式 | 验证目标 |
|---|---|---|
| 实例级故障 | 随机终止 Pod | 自动恢复时间 < RTO |
| 网络分区 | 模拟 AZ 间网络中断 | 多 AZ 冗余有效性 |
| 级联过载 | 限速器故障 + burst | 熔断降级策略生效 |
| 依赖故障 | mock 下游服务超时 | 降级后 SLO 仍满足 |
Chaos Monkey、Litmus、Gremlin 等工具可自动化注入故障,将容量验证从"单次压测"升级为"持续验证"。
5. 压测方法论
压测类型
┌───────────────────────────────────────────┐
│ 负载测试 (Load Testing) │
│ 目标: 验证系统在正常负载下的表现 │
│ 方法: 逐步加压至目标 QPS │
├───────────────────────────────────────────┤
│ 压力测试 (Stress Testing) │
│ 目标: 找到系统极限、观察恢复过程 │
│ 方法: 加压至系统崩溃 │
├───────────────────────────────────────────┤
│ 稳定性测试 (Soak Testing) │
│ 目标: 长时间运行发现内存/连接泄漏 │
│ 方法: 持续跑 8-24 小时 │
├───────────────────────────────────────────┤
│ 峰值测试 (Spike Testing) │
│ 目标: 突发流量应对能力 │
│ 方法: 瞬间加压数倍 │
└───────────────────────────────────────────┘
压测工具
| 工具 | 特点 | 适用 |
|---|---|---|
| JMeter | GUI 配置、插件丰富 | Web 应用 |
| k6 | 代码即脚本、云原生 | API 压测 |
| Locust | Python 编写、分布式 | 自定义场景 |
| Gatling | Scala、高性能 | 复杂协议 |
| ** vegeta** | 命令行、Go 编写 | 快速测试 |
k6 示例
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // 逐步加压
{ duration: '5m', target: 100 }, // 稳态
{ duration: '2m', target: 200 }, // 继续加压
{ duration: '5m', target: 200 }, // 稳态
{ duration: '2m', target: 0 }, // 减压
],
thresholds: {
http_req_duration: ['p(99)<200'],
http_req_failed: ['rate<0.1'],
},
};
export default function () {
const res = http.get('https://api.example.com/orders');
check(res, {
'status is 200': (r) => r.status === 200,
});
sleep(1);
}
总结
| 维度 | 核心 |
|---|---|
| SLI | 测量什么 |
| SLO | 目标值(平衡可靠性与成本) |
| 错误预算 | 可靠性资源,指导发布策略 |
| 容量规划 | 资源支撑 SLO 的能力 |
| 压测 | 验证容量与极限 |
没有无限可靠性的系统,只有清晰定义"足够可靠"并为之投入的系统。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。