3. etcd 压测工具选型与部署:benchmark、etcdctl check perf、ghz 与自定义脚本
在跨集群调度沙盘中,etcd 作为 Kubernetes 控制面的状态存储核心,其性能直接决定调度延迟与集群稳定性。本章聚焦四类压测工具的选型逻辑、部署配置与适用场景,帮助你在沙盘环境中精准评估 etcd 的读写吞吐、延迟分布与限速行为。
选型原则: 优先使用官方工具建立基线,再用 gRPC 级工具模拟真实 workload,最后用自定义脚本覆盖边界场景。不要在生产集群直接运行压测,始终在沙盘隔离环境中执行。
3.1 工具对比与选型矩阵
| 工具 | 协议层 | 核心能力 | 输出指标 | 推荐场景 |
|---|---|---|---|---|
| benchmark | etcd v3 gRPC | PUT/GET 吞吐、延迟分布、连接数控制 | Ops/sec, P99/P999 延迟 | 快速基线测试、限速验证 |
| etcdctl check perf | etcd v3 API | 端到端健康检查、延迟直方图 | 平均延迟、通过/失败状态 | 日常巡检、部署后验证 |
| ghz | gRPC 原生 | 自定义 protobuf 请求、并发模型、元数据注入 | RPS, 延迟分布, 错误码 | 模拟真实客户端、watch 场景 |
| 自定义脚本 (Python/Go) | etcd clientv3 | 事务、租约、watch、多 key 模式 | 自定义指标、业务级延迟 | 复杂工作负载、压力模型复现 |
3.2 benchmark 工具部署与配置
benchmark 是 etcd 官方提供的压测二进制,位于 etcd 仓库的 tools/benchmark 目录。推荐在沙盘的控制节点上直接编译或使用预编译镜像。
3.2.1 编译与部署
# 在沙盘控制节点编译
git clone https://github.com/etcd-io/etcd.git --branch v3.5.15
cd etcd/tools/benchmark
go build -o benchmark .
# 验证部署
./benchmark --help
3.2.2 典型压测命令
# 10 并发、10000 请求的 PUT 压测
./benchmark put \
--endpoints=https://10.0.1.10:2379,https://10.0.1.11:2379 \
--conns=10 \
--clients=10 \
--total=10000 \
--key-size=64 \
--val-size=256 \
--cert=/etc/etcd/pki/etcd.pem \
--key=/etc/etcd/pki/etcd-key.pem \
--cacert=/etc/etcd/pki/ca.pem
# 输出示例
# 10000 requests finished in 2.345s
# Average: 0.234ms
# P99: 1.023ms
# P999: 2.456ms
关键参数说明:
--conns:底层 gRPC 连接数,建议与 etcd 节点数一致或略高。--clients:并发客户端数,模拟实际 apiserver 行为。--key-size / --val-size:模拟真实 Kubernetes 资源对象大小(如 Pod 约 2KB)。- 沙盘中建议先以
--total=5000做预热,再执行正式压测。
3.3 etcdctl check perf 部署与配置
etcdctl check perf 是 etcdctl 内置的子命令,无需额外安装,适合快速验证集群健康状态。
3.3.1 基本用法
# 默认 60 秒压测
etcdctl check perf \
--endpoints=https://10.0.1.10:2379 \
--cert=/etc/etcd/pki/etcd.pem \
--key=/etc/etcd/pki/etcd-key.pem \
--cacert=/etc/etcd/pki/ca.pem
# 输出示例
# 60.0s: Average: 0.45ms | P99: 2.1ms | Throughput: 12500 ops/s
# FAIL: P99 latency 2.1ms exceeds threshold 1.0ms
3.3.2 自定义阈值与时长
# 设置 P99 阈值为 5ms,压测时长 120 秒
etcdctl check perf \
--endpoints=https://10.0.1.10:2379 \
--duration=120s \
--p99-threshold=5ms \
--cert=/etc/etcd/pki/etcd.pem \
--key=/etc/etcd/pki/etcd-key.pem \
--cacert=/etc/etcd/pki/ca.pem
注意:
etcdctl check perf 会创建大量临时 key(前缀为 check-perf-),压测后需手动清理。沙盘中建议在独立租约空间运行,避免干扰业务数据。
3.4 ghz(gRPC 压测)部署与配置
ghz 是通用的 gRPC 压测工具,支持自定义 protobuf 消息、元数据注入和并发模型。对于 etcd 的 watch、事务等复杂操作,ghz 比 benchmark 更灵活。
3.4.1 部署方式
# 方式一:Go 安装
go install github.com/bojand/ghz/cmd/ghz@latest
# 方式二:Docker 运行(推荐沙盘使用)
docker run --rm -v $(pwd):/data ghzio/ghz:0.120.0 \
--config /data/etcd-put.json
3.4.2 配置文件示例(etcd-put.json)
{
"proto": "/data/etcd.proto",
"call": "etcdserverpb.KV.Put",
"total": 5000,
"concurrency": 20,
"metadata": {
"authorization": "Bearer <>"
},
"data": {
"key": "aW5jcmVtZW50YWw=",
"value": "dGVzdF92YWx1ZQ=="
},
"insecure": false,
"cacert": "/data/ca.pem",
"cert": "/data/client.pem",
"key": "/data/client-key.pem"
}
3.4.3 运行与输出
ghz --config /data/etcd-put.json \
--endpoints https://10.0.1.10:2379
# 输出摘要
# Summary:
# Count: 5000
# Total: 3.12 s
# Slowest: 45.23 ms
# Fastest: 0.12 ms
# Average: 1.56 ms
# Requests/sec: 1602.56
# Error Distribution:
# [4] Unavailable: 2
ghz 优势: 支持
--data-file 传入 CSV/JSON 数据源,可模拟不同 key 分布;支持 --stream 模式测试 watch 流,适合评估 etcd 的推送能力。
3.5 自定义压测脚本(Python/Go)
当标准工具无法覆盖业务级场景(如事务、租约续期、多 key 原子操作)时,需要编写自定义脚本。以下给出 Python 和 Go 的典型模板。
3.5.1 Python 脚本(使用 etcd3gw)
import etcd3gw
import time
import threading
endpoints = ["https://10.0.1.10:2379"]
client = etcd3gw.client(
host=endpoints[0],
cert=("/etc/etcd/pki/client.pem", "/etc/etcd/pki/client-key.pem"),
ca_cert="/etc/etcd/pki/ca.pem"
)
def put_worker(worker_id, count):
for i in range(count):
key = f"/test/worker-{worker_id}/key-{i}"
value = f"value-{i}" * 32 # 模拟 256B 值
start = time.time()
client.put(key, value)
elapsed = time.time() - start
if elapsed > 0.1: # 记录超过 100ms 的慢请求
print(f"SLOW: worker={worker_id}, key={key}, latency={elapsed:.3f}s")
threads = []
for w in range(10): # 10 个并发 worker
t = threading.Thread(target=put_worker, args=(w, 1000))
threads.append(t)
t.start()
for t in threads:
t.join()
print("Custom Python benchmark completed.")
3.5.2 Go 脚本(使用 clientv3)
package main
import (
"context"
"fmt"
"sync"
"time"
clientv3 "go.etcd.io/etcd/client/v3"
)
func main() {
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"https://10.0.1.10:2379"},
DialTimeout: 5 * time.Second,
TLS: loadTLSConfig(),
})
if err != nil {
panic(err)
}
defer cli.Close()
var wg sync.WaitGroup
totalOps := 10000
concurrency := 20
opsPerWorker := totalOps / concurrency
for w := 0; w < concurrency; w++ {
wg.Add(1)
go func(workerID int) {
defer wg.Done()
for i := 0; i < opsPerWorker; i++ {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
key := fmt.Sprintf("/bench/go-%d/key-%d", workerID, i)
_, err := cli.Put(ctx, key, "bench-value")
cancel()
if err != nil {
fmt.Printf("ERROR: worker=%d, key=%s, err=%v\n", workerID, key, err)
}
}
}(w)
}
wg.Wait()
fmt.Println("Go benchmark completed.")
}
自定义脚本最佳实践:
- 始终设置
context.WithTimeout,避免 goroutine 泄漏。 - 记录每个请求的延迟分布,输出 P50/P90/P99 直方图。
- 在沙盘中先运行小规模(1000 ops)验证脚本正确性,再放大到生产级压力。
- 使用
sync.WaitGroup或asyncio控制并发,避免无限制创建协程。
3.6 工具部署架构总览
下图展示了四种压测工具在沙盘环境中的部署位置与数据流关系。所有压测客户端均运行在沙盘控制节点或独立压测 Pod 中,通过 TLS 与 etcd 集群通信。
3.7 压测执行流程与注意事项
- 环境准备: 确认沙盘 etcd 集群健康(
etcdctl endpoint health),记录基线延迟。 - 基线测试: 使用
benchmark执行 1000 次 PUT/GET,记录 P99 延迟与吞吐。 - 压力递增: 以 10、50、100、200 并发逐步增加负载,观察延迟拐点。
- 混合场景: 使用 ghz 或自定义脚本模拟 70% PUT + 20% GET + 10% 事务的混合 workload。
- 限速验证: 在沙盘中配置
--max-request-bytes或--quota-backend-bytes,验证限速行为。 - 数据清理: 压测后删除测试 key(如
etcdctl del /test --prefix),恢复沙盘状态。
沙盘安全红线:
- 禁止在沙盘 etcd 的
--data-dir目录直接写入或删除文件。 - 压测并发数不要超过沙盘 CPU 核心数的 4 倍,避免宿主机 OOM。
- 每次压测前记录 etcd 的
--quota-backend-bytes当前值,防止磁盘空间写满。
3.8 工具选型决策树
根据压测目标快速选择工具:
| 压测目标 | 推荐工具 | 理由 |
|---|---|---|
| 快速验证集群健康 | etcdctl check perf | 零配置,内置阈值判断 |
| 吞吐量基线测试 | benchmark | 官方优化,输出标准指标 |
| gRPC 协议级压测 | ghz | 支持自定义 protobuf 和元数据 |
| 复杂业务场景复现 | 自定义脚本 (Go) | 完全控制请求逻辑与并发模型 |
| watch 流性能评估 | ghz + 自定义脚本 | ghz 支持 stream,脚本可定制事件处理 |