4. 压测环境搭建:在 K8s 集群中部署压测工具(以 k6 Operator 为例)

在 Kubernetes 资源限制场景下,压测工具本身也必须以云原生的方式运行,才能与被压测服务处于同一网络平面、共享节点资源视图,并避免宿主机环境差异带来的干扰。k6 Operator 是 Grafana 官方维护的 Kubernetes 原生压测方案,它通过自定义资源(CRD)将压测脚本、执行参数、并行副本声明式地提交给集群,天然适配 RBAC 与 ServiceAccount 体系。本节将完整演示从 Operator 安装到 RBAC 配置的全流程。

4.1 部署架构概览

k6 Operator 在集群中的工作分为三个层次:Operator 控制器监听 CRD 事件,k6 Runner Pod 执行实际压测,ServiceAccount + RBAC 控制 Operator 对集群资源的访问权限。下图展示了核心组件及其交互关系。

k6 Operator 部署架构与 RBAC 关系 k6 Operator 部署架构与 RBAC 关系 控制平面 数据平面 权限层 K6 CRD K6 / K6Runner k6 Operator 控制器 Pod k6 Runner 压测执行 Pod ServiceAccount k6-operator-sa ClusterRole k6-operator-role ClusterRoleBinding k6-operator-bind 压测目标 Service 绑定 Operator 通过 ServiceAccount 获取对 K6 CRD 的 watch/list/create 权限,Runner Pod 无需额外 RBAC

4.2 安装 k6 Operator

推荐使用 Helm Chart 进行安装,版本锁定与升级管理更可控。以下步骤基于 k6 Operator v0.0.17 版本。

前置条件:Kubernetes 集群版本 ≥ 1.19,已安装 Helm v3,集群具备 cert-manager(Operator 内部 webhook 需要 TLS 证书)。

4.2.1 添加 Helm 仓库并安装

# 添加 Grafana 官方 Helm 仓库
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

# 创建命名空间
kubectl create namespace k6-operator-system

# 安装 k6 Operator
helm install k6-operator grafana/k6-operator \
  --namespace k6-operator-system \
  --version 0.0.17 \
  --set operator.resources.requests.cpu=100m \
  --set operator.resources.requests.memory=128Mi \
  --set operator.resources.limits.cpu=500m \
  --set operator.resources.limits.memory=256Mi

4.2.2 验证安装状态

# 检查 Operator Pod 运行状态
kubectl get pods -n k6-operator-system -l app.kubernetes.io/name=k6-operator

# 预期输出示例:
# NAME                              READY   STATUS    RESTARTS   AGE
# k6-operator-controller-manager-xxx   1/1     Running   0          2m

# 检查 CRD 是否注册
kubectl get crd | grep k6

# 预期输出:
# k6s.k6.io                         2025-01-15T10:00:00Z
# k6runners.k6.io                   2025-01-15T10:00:00Z

4.3 配置 RBAC 与 ServiceAccount

k6 Operator 默认会创建专用的 ServiceAccount 和 ClusterRole,但在生产环境中,建议按最小权限原则显式声明绑定关系。以下配置适用于 Operator 需要跨命名空间管理 K6 资源的场景。

4.3.1 创建 ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: k6-operator-sa
  namespace: k6-operator-system

4.3.2 定义 ClusterRole

Operator 需要以下权限:对 K6 CRD 的 get/list/watch/create/update/patch/delete,以及对 Pod、ConfigMap、Service 的 get/list/watch(用于管理 Runner Pod 生命周期)。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: k6-operator-role
rules:
  # K6 CRD 资源
  - apiGroups: ["k6.io"]
    resources: ["k6s", "k6runners"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  # 核心资源(Runner Pod 管理)
  - apiGroups: [""]
    resources: ["pods", "configmaps", "services", "events"]
    verbs: ["get", "list", "watch"]
  # 部署与副本集(可选,用于高级编排)
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets"]
    verbs: ["get", "list", "watch"]

4.3.3 绑定 ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: k6-operator-bind
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: k6-operator-role
subjects:
  - kind: ServiceAccount
    name: k6-operator-sa
    namespace: k6-operator-system
权限边界说明:Operator 本身不需要对压测目标 Service 的访问权限。压测流量由 Runner Pod 直接发出,Runner Pod 继承其所在命名空间的默认 ServiceAccount(通常为 default)。如果压测目标需要身份认证,应在 Runner Pod 的 spec.serviceAccountName 字段指定。

4.4 配置 Helm Values 注入 RBAC

如果使用 Helm 安装,可以在 values 文件中直接指定 ServiceAccount 和 RBAC 参数,避免手动创建 YAML 文件。

参数路径 类型 默认值 说明
serviceAccount.create bool true 是否自动创建 ServiceAccount
serviceAccount.name string k6-operator 自定义 ServiceAccount 名称
rbac.create bool true 是否自动创建 ClusterRole 与 ClusterRoleBinding
rbac.rules list 内置默认规则 自定义 RBAC 规则列表,覆盖默认值
# values-override.yaml
serviceAccount:
  create: true
  name: k6-operator-sa
rbac:
  create: true
  rules:
    - apiGroups: ["k6.io"]
      resources: ["k6s", "k6runners"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
    - apiGroups: [""]
      resources: ["pods", "configmaps", "events"]
      verbs: ["get", "list", "watch"]

# 使用自定义 values 重新安装
helm upgrade --install k6-operator grafana/k6-operator \
  --namespace k6-operator-system \
  -f values-override.yaml

4.5 验证 RBAC 配置有效性

使用 kubectl auth can-i 命令验证 Operator 的 ServiceAccount 是否具备预期权限。

# 验证对 K6 CRD 的创建权限
kubectl auth can-i create k6s.k6.io \
  --as=system:serviceaccount:k6-operator-system:k6-operator-sa

# 验证对 Pod 的读取权限
kubectl auth can-i list pods \
  --as=system:serviceaccount:k6-operator-system:k6-operator-sa

# 验证对 Deployment 的读取权限(如果配置了)
kubectl auth can-i list deployments.apps \
  --as=system:serviceaccount:k6-operator-system:k6-operator-sa
常见问题:如果 auth can-i 返回 no,请检查 ClusterRoleBinding 的 subjects.namespace 是否与 ServiceAccount 所在命名空间一致。跨命名空间绑定时,subjects.namespace 必须显式指定,不能为空。

4.6 提交第一个压测任务(端到端验证)

完成 RBAC 配置后,提交一个最小化的 K6 CRD 实例,验证整个链路是否通畅。

apiVersion: k6.io/v1alpha1
kind: K6
metadata:
  name: hello-k6
  namespace: default
spec:
  parallelism: 2
  script:
    configMap:
      name: k6-script-cm
      file: script.js
  runner:
    serviceAccountName: default
    resources:
      requests:
        cpu: 200m
        memory: 256Mi
      limits:
        cpu: 500m
        memory: 512Mi
# 创建 ConfigMap 存放压测脚本
kubectl create configmap k6-script-cm \
  --from-literal=script.js='
import http from "k6/http";
import { sleep } from "k6";
export default function () {
  http.get("http://test-service:8080/health");
  sleep(1);
}
'

# 提交 K6 资源
kubectl apply -f hello-k6.yaml

# 观察 Runner Pod 启动
kubectl get pods -l app.kubernetes.io/instance=hello-k6

# 查看压测日志
kubectl logs -l app.kubernetes.io/instance=hello-k6 --tail=20
k6 压测任务提交与执行流程 k6 压测任务提交与执行流程 kubectl apply K6 CRD YAML k6 Operator Reconcile 循环 Runner Pod 压测执行 目标 Service 被压测应用 状态更新 Operator 通过 ServiceAccount 监听 K6 CRD 变化,自动创建 Runner Pod 并跟踪其生命周期

4.7 环境验证清单

完成部署后,建议逐项检查以下关键点,确保压测环境就绪。

检查项 验证方法 预期结果
Operator Pod 运行 kubectl get pods -n k6-operator-system 1/1 Running
CRD 注册 kubectl get crd | grep k6 k6s.k6.io / k6runners.k6.io
ServiceAccount 存在 kubectl get sa -n k6-operator-system k6-operator-sa 列出
RBAC 权限 kubectl auth can-i create k6s --as=... yes
Runner Pod 创建 kubectl apply -f hello-k6.yaml Pod 进入 Running 状态
压测日志输出 kubectl logs <runner-pod> 显示 k6 执行指标
最佳实践:将上述验证步骤写入 CI/CD 流水线中的 post-install 测试阶段,确保每次集群更新或 Operator 升级后压测环境依然可用。同时建议为压测任务单独创建命名空间(如 loadtest),并通过 ResourceQuota 限制 Runner Pod 的资源消耗上限,避免压测任务影响集群中其他业务。