4. 压测沙盘环境搭建:Docker Compose 与 Kubernetes Operator 部署 etcd 集群

压测沙盘环境是进行性能瓶颈分析与参数调优的基础。本章将指导你使用两种主流方式部署 etcd 集群:Docker Compose(适用于本地开发与快速原型验证)与 Kubernetes Operator(适用于生产级、可自愈的集群管理)。两种方式均会构建一个 3 节点 etcd 集群,并配置必要的监控与压测工具。

环境前提: 确保宿主机已安装 Docker Engine 24+、Docker Compose v2+、kubectl 1.28+ 以及 kind 或 minikube(用于本地 K8s 环境)。

4.1 部署架构概览

下图展示了两种部署模式下的组件关系与数据流。左侧为 Docker Compose 模式,右侧为 Kubernetes Operator 模式,两者均包含 etcd 节点、负载均衡器(或 Service)以及压测客户端。

etcd 压测沙盘部署架构对比 Docker Compose 模式 压测客户端 (benchmark) HAProxy / Nginx etcd-1 etcd-2 etcd-3 vol-1 vol-2 vol-3 Kubernetes Operator 模式 压测客户端 (Pod) etcd Service (ClusterIP) etcd-0 Pod etcd-1 Pod etcd-2 Pod pvc-0 pvc-1 pvc-2 etcd-operator

4.2 方式一:Docker Compose 部署

Docker Compose 适合在单机或开发环境中快速拉起一个完整的 etcd 集群。以下配置包含 3 个 etcd 成员、一个 HAProxy 负载均衡器以及一个用于压测的客户端容器。

4.2.1 docker-compose.yml 核心配置

version: '3.8'

services:
  etcd-1:
    image: quay.io/coreos/etcd:v3.5.15
    container_name: etcd-1
    environment:
      - ETCD_NAME=etcd-1
      - ETCD_INITIAL_CLUSTER=etcd-1=http://etcd-1:2380,etcd-2=http://etcd-2:2380,etcd-3=http://etcd-3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ETCD_INITIAL_CLUSTER_=etcd-cluster-
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd-1:2379
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd-1:2380
      - ETCD_DATA_DIR=/etcd-data
    volumes:
      - etcd-1-data:/etcd-data
    networks:
      - etcd-net

  etcd-2:
    image: quay.io/coreos/etcd:v3.5.15
    container_name: etcd-2
    environment:
      - ETCD_NAME=etcd-2
      - ETCD_INITIAL_CLUSTER=etcd-1=http://etcd-1:2380,etcd-2=http://etcd-2:2380,etcd-3=http://etcd-3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ETCD_INITIAL_CLUSTER_=etcd-cluster-
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd-2:2379
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd-2:2380
      - ETCD_DATA_DIR=/etcd-data
    volumes:
      - etcd-2-data:/etcd-data
    networks:
      - etcd-net

  etcd-3:
    image: quay.io/coreos/etcd:v3.5.15
    container_name: etcd-3
    environment:
      - ETCD_NAME=etcd-3
      - ETCD_INITIAL_CLUSTER=etcd-1=http://etcd-1:2380,etcd-2=http://etcd-2:2380,etcd-3=http://etcd-3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ETCD_INITIAL_CLUSTER_=etcd-cluster-
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd-3:2379
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd-3:2380
      - ETCD_DATA_DIR=/etcd-data
    volumes:
      - etcd-3-data:/etcd-data
    networks:
      - etcd-net

  haproxy:
    image: haproxy:2.8-alpine
    container_name: haproxy
    ports:
      - "2379:2379"
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    depends_on:
      - etcd-1
      - etcd-2
      - etcd-3
    networks:
      - etcd-net

  benchmark:
    image: quay.io/coreos/etcd:v3.5.15
    container_name: benchmark
    entrypoint: ["/bin/sh"]
    stdin_open: true
    tty: true
    networks:
      - etcd-net

volumes:
  etcd-1-data:
  etcd-2-data:
  etcd-3-data:

networks:
  etcd-net:
    driver: bridge

4.2.2 HAProxy 配置(haproxy.cfg)

global
  log stdout format raw local0
  maxconn 4096

defaults
  log global
  mode tcp
  option tcplog
  timeout connect 5000ms
  timeout client 50000ms
  timeout server 50000ms

frontend etcd_front
  bind *:2379
  default_backend etcd_back

backend etcd_back
  balance roundrobin
  server etcd-1 etcd-1:2379 check inter 2s fall 3 rise 2
  server etcd-2 etcd-2:2379 check inter 2s fall 3 rise 2
  server etcd-3 etcd-3:2379 check inter 2s fall 3 rise 2

4.2.3 启动与验证

  1. 启动集群:docker compose up -d
  2. 检查成员状态:docker exec etcd-1 etcdctl member list
  3. 验证写入:docker exec etcd-1 etcdctl put /test/key "hello"
  4. 验证读取:docker exec etcd-1 etcdctl get /test/key
  5. 进入压测容器:docker exec -it benchmark sh
关键参数说明:
  • ETCD_INITIAL_CLUSTER:必须列出所有成员的 peer URL,顺序无关。
  • ETCD_INITIAL_CLUSTER_STATE=new:首次启动必须为 new,后续重启需改为 existing。
  • ETCD_LISTEN_CLIENT_URLS:绑定 0.0.0.0:2379 以接受外部连接。

4.3 方式二:Kubernetes Operator 部署

在生产环境或需要自动故障恢复的场景下,推荐使用 etcd-operator。Operator 负责管理 etcd 集群的生命周期,包括创建、扩缩容、备份与恢复。

4.3.1 安装 etcd-operator

# 创建命名空间
kubectl create namespace etcd-cluster

# 部署 operator
kubectl apply -f https://raw.githubusercontent.com/coreos/etcd-operator/master/example/deployment.yaml -n etcd-cluster

# 验证 operator 运行
kubectl get pods -n etcd-cluster -l name=etcd-operator

4.3.2 创建 etcd 集群 CR(Custom Resource)

apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
  name: "etcd-cluster"
  namespace: "etcd-cluster"
spec:
  size: 3
  version: "3.5.15"
  pod:
    resources:
      requests:
        cpu: 500m
        memory: 512Mi
      limits:
        cpu: 1000m
        memory: 1Gi
    etcdEnv:
      - name: ETCD_QUOTA_BACKEND_BYTES
        value: "8589934592"  # 8GB
      - name: ETCD_AUTO_COMPACTION_RETENTION
        value: "1"
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector:
              matchExpressions:
              - key: etcd_cluster
                operator: In
                values:
                - "etcd-cluster"
            topologyKey: kubernetes.io/hostname

4.3.3 应用 CR 并验证

# 应用 CR
kubectl apply -f etcd-cluster.yaml

# 查看集群状态
kubectl get etcdcluster -n etcd-cluster

# 查看 Pod 列表
kubectl get pods -n etcd-cluster -l app=etcd

# 查看 Service
kubectl get svc -n etcd-cluster

# 测试连接(从集群内)
kubectl run -it --rm --image=quay.io/coreos/etcd:v3.5.15 test-client --restart=Never -- \
  etcdctl --endpoints=http://etcd-cluster-client:2379 put /test/key "hello"

4.4 两种部署方式对比

维度 Docker Compose Kubernetes Operator
部署复杂度 低,单机即可运行 中,需要 K8s 集群
故障自愈 无,需手动重启 自动重建故障 Pod
扩缩容 手动修改 compose 文件 修改 CR 中 size 字段
持久化 Docker Volume PVC + PV
网络模型 Docker 网络 K8s Service + DNS
适用场景 本地开发、快速原型 生产环境、CI/CD

4.5 压测沙盘初始化检查清单

在开始压测之前,请确认以下项目均已就绪:

  • 集群健康:所有 etcd 成员处于 started 状态,leader 选举正常。
  • 网络连通:压测客户端可通过负载均衡器或 Service 访问 etcd 的 2379 端口。
  • 资源预留:CPU 和内存限制已设置,避免压测时资源争抢。
  • 数据目录:持久化卷已挂载,且具有足够的 IOPS 能力(建议 SSD)。
  • 监控接入:Prometheus 或 etcd 内置 metrics 端点可访问(/metrics)。
注意: 在 Kubernetes 环境中,如果使用 kind 或 minikube,请确保为 etcd Pod 分配了足够的节点资源。建议为每个 etcd 实例预留至少 1 个 CPU 核心和 1GB 内存,以避免压测过程中出现 OOMKill 或 CPU Throttling。

4.6 快速验证脚本

以下脚本可用于验证集群是否具备压测条件:

#!/bin/bash
# etcd 压测前健康检查脚本

ENDPOINT=${1:-"http://localhost:2379"}

echo "=== 检查集群健康 ==="
etcdctl --endpoints=$ENDPOINT endpoint health --cluster

echo "=== 检查成员列表 ==="
etcdctl --endpoints=$ENDPOINT member list

echo "=== 检查 leader 状态 ==="
etcdctl --endpoints=$ENDPOINT endpoint status --cluster -w table

echo "=== 写入测试键值 ==="
etcdctl --endpoints=$ENDPOINT put /health-check "ok"

echo "=== 读取测试键值 ==="
etcdctl --endpoints=$ENDPOINT get /health-check

echo "=== 删除测试键值 ==="
etcdctl --endpoints=$ENDPOINT del /health-check

echo "=== 检查 metrics 端点 ==="
curl -s $ENDPOINT/metrics | head -20

echo "=== 完成 ==="

执行 bash check_etcd.sh http://etcd-cluster-client:2379(K8s 环境)或 bash check_etcd.sh http://localhost:2379(Docker Compose 环境),输出应显示所有端点均为 healthy,且 leader 唯一。