痛点
你的 Kubernetes 集群扛住了日常流量,但大促或突发高峰时 Pod 频繁 OOMKill、响应延迟飙升。传统压测工具(JMeter、Locust)要么笨重难以容器化,要么产出的报告和云原生监控体系割裂——压测结果在 JMeter GUI 里,而真实指标在 Grafana 里,排查时两头切换效率极低。
核心矛盾: 压测工具与可观测性体系脱节,无法在同一视角下同时看到「施压曲线」和「服务响应指标」。
方案
Grafana k6 — 用 JavaScript 编写压测脚本,原生支持将指标输出到 Prometheus/Grafana,天然融入云原生可观测性栈。核心优势:
- 单二进制,无 JVM 依赖,容器镜像仅 ~40MB
- 脚本即代码,可 Git 管理、CI/CD 集成
- 原生 Prometheus Remote Write,压测指标直接进 Grafana 大盘
- 支持阈值断言(Thresholds),CI 中自动 pass/fail
实操步骤
第 1 步:安装 k6
# Linux (amd64)
curl -sSL https://github.com/grafana/k6/releases/download/v0.56.0/k6-v0.56.0-linux-amd64.tar.gz | tar xz
sudo mv k6-v0.56.0-linux-amd64/k6 /usr/local/bin/
# 验证
k6 version
容器化方式:
docker run --rm -i grafana/k6:0.56.0 run - < script.js
第 2 步:编写压测脚本
创建 load-test.js:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 }, // 30s 内爬升到 50 VU
{ duration: '1m', target: 200 }, // 1min 内爬升到 200 VU
{ duration: '30s', target: 0 }, // 30s 内降至 0
],
thresholds: {
http_req_duration: ['p(95)<500'], // P95 延迟 < 500ms
http_req_failed: ['rate<0.01'], // 错误率 < 1%
},
};
export default function () {
const res = http.get('http://your-service.default.svc.cluster.local/api/health');
check(res, {
'status is 200': (r) => r.status === 200,
'latency < 300ms': (r) => r.timings.duration < 300,
});
sleep(1);
}
第 3 步:对接 Prometheus + Grafana
启动 k6 时开启 Prometheus Remote Write 输出:
K6_PROMETHEUS_RW_SERVER_URL=http://prometheus:9090/api/v1/write \
K6_PROMETHEUS_RW_TREND_AS_NATIVE_HISTOGRAM=true \
k6 run --out experimental-prometheus-rw load-test.js
指标会自动写入 Prometheus,在 Grafana 中导入官方 Dashboard(ID: 18030)即可实时查看:
- VU 并发数曲线
- 请求速率(req/s)
- P50 / P95 / P99 延迟分布
- 错误率变化
第 4 步:集成到 CI/CD Pipeline
GitLab CI 示例:
load-test:
stage: test
image: grafana/k6:0.56.0
script:
- k6 run --out experimental-prometheus-rw load-test.js
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
allow_failure: false # thresholds 不通过则 MR 失败
k6 的 thresholds 机制会在指标超标时返回非零退出码,CI 自动标记失败,无需额外脚本判断。
第 5 步:在 K8s 中分布式执行(可选)
对于需要上万 VU 的场景,使用 k6-operator:
helm repo add grafana https://grafana.github.io/helm-charts
helm install k6-operator grafana/k6-operator -n k6-operator-system --create-namespace
创建 TestRun CRD:
apiVersion: k6.io/v1alpha1
kind: TestRun
metadata:
name: peak-load-test
spec:
parallelism: 4 # 4 个 Runner Pod 并行
script:
configMap:
name: load-test-script
file: load-test.js
arguments: --out experimental-prometheus-rw
4 个 Pod 各跑 200 VU,总并发 800,施压能力线性扩展。
避坑
1. Prometheus Remote Write 超时丢数据
k6 默认 batch 间隔 1s,高并发时 Prometheus 写入压力大。调大 buffer:
K6_PROMETHEUS_RW_PUSH_INTERVAL=5s k6 run --out experimental-prometheus-rw load-test.js
2. K8s 内部压测时 DNS 解析成瓶颈
大量 VU 同时解析 Service 域名会打满 CoreDNS。解决方案:在压测脚本中直接用 ClusterIP,或提前扩容 CoreDNS 副本数:
kubectl -n kube-system scale deployment coredns --replicas=5
3. thresholds 设置过严导致 CI 频繁失败
P95 < 200ms 在共享集群上几乎不可能稳定达标。建议区分环境:
const ENV = __ENV.TEST_ENV || 'staging';
export const options = {
thresholds: {
http_req_duration: [ENV === 'prod' ? 'p(95)<300' : 'p(95)<800'],
},
};
总结
Grafana k6 的核心价值是压测即可观测 — 施压指标和服务指标在同一个 Grafana 大盘上实时关联,精准定位「是压测端瓶颈还是服务端瓶颈」。结合 CI/CD thresholds 机制,性能回归在合并前就能拦截。对于已经建立 Prometheus + Grafana 监控体系的团队,k6 是目前融合度最高的云原生压测方案。