Docker Etcd Setup

Docker Etcd 部署指南

本文介绍如何使用 Docker 和 Docker Compose 部署 Etcd 分布式键值存储系统。Etcd 是一个高可用的分布式键值存储,常用于服务发现、配置管理和分布式协调。

📋 前置要求

  • Docker 20.10+ 已安装
  • Docker Compose V2 已安装(推荐)或 Docker Compose V1
  • 如需使用 Docker Swarm,需要初始化 Swarm 集群

🚀 快速部署(单节点)

1. 克隆项目(如果使用项目模板)

1
2
git clone https://github.com/noahzaozao/docker-etcd.git
cd docker-etcd

2. 配置环境变量

1
2
cp .env-trunk .env
vi .env

编辑 .env 文件,设置 Etcd IP 地址:

1
ETCD_IP=127.0.0.1

3. 创建数据目录

1
mkdir -p ./default.etcd

4. 使用 Docker Compose 部署

1
2
3
4
5
# 使用 Docker Compose V2(推荐)
docker compose up -d

# 或使用旧版
docker-compose up -d

5. 验证部署

1
2
3
4
5
# 查看容器状态
docker compose ps

# 测试 Etcd 连接
docker compose exec etcd etcdctl --endpoints=http://127.0.0.1:2379 version

📝 Docker Compose 配置示例

单节点配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3.8'

services:
etcd:
container_name: etcd
image: quay.io/coreos/etcd:v3.5.9
environment:
ETCD_NAME: etcd-node
ETCD_DATA_DIR: /default.etcd
ETCD_ADVERTISE_CLIENT_URLS: "http://${ETCD_IP:-127.0.0.1}:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://${ETCD_IP:-127.0.0.1}:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_INITIAL_CLUSTER_TOKEN: etcd-cluster-1
ETCD_INITIAL_CLUSTER: etcd-node=http://${ETCD_IP:-127.0.0.1}:2380
ETCD_INITIAL_CLUSTER_STATE: new
ETCDCTL_API: "3"
volumes:
- ./default.etcd:/default.etcd
ports:
- "2379:2379" # Client API
- "2380:2380" # Peer communication
restart: unless-stopped
healthcheck:
test: ["CMD", "etcdctl", "--endpoints=http://localhost:2379", "endpoint", "health"]
interval: 30s
timeout: 10s
retries: 3

三节点集群配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
version: '3.8'

services:
etcd0:
image: quay.io/coreos/etcd:v3.5.9
container_name: etcd0
environment:
ETCD_NAME: etcd0
ETCD_DATA_DIR: /default.etcd
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd0:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd0:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380"
ETCD_INITIAL_CLUSTER_TOKEN: etcd-cluster-1
ETCD_INITIAL_CLUSTER_STATE: new
ETCDCTL_API: "3"
volumes:
- etcd0_data:/default.etcd
networks:
- etcd_network

etcd1:
image: quay.io/coreos/etcd:v3.5.9
container_name: etcd1
environment:
ETCD_NAME: etcd1
ETCD_DATA_DIR: /default.etcd
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd1:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd1:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380"
ETCD_INITIAL_CLUSTER_TOKEN: etcd-cluster-1
ETCD_INITIAL_CLUSTER_STATE: new
ETCDCTL_API: "3"
volumes:
- etcd1_data:/default.etcd
networks:
- etcd_network

etcd2:
image: quay.io/coreos/etcd:v3.5.9
container_name: etcd2
environment:
ETCD_NAME: etcd2
ETCD_DATA_DIR: /default.etcd
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd2:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd2:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380"
ETCD_INITIAL_CLUSTER_TOKEN: etcd-cluster-1
ETCD_INITIAL_CLUSTER_STATE: new
ETCDCTL_API: "3"
volumes:
- etcd2_data:/default.etcd
networks:
- etcd_network

volumes:
etcd0_data:
etcd1_data:
etcd2_data:

networks:
etcd_network:
driver: bridge

生产环境配置(带认证)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
version: '3.8'

services:
etcd:
container_name: etcd
image: quay.io/coreos/etcd:v3.5.9
environment:
ETCD_NAME: etcd-node
ETCD_DATA_DIR: /default.etcd
ETCD_ADVERTISE_CLIENT_URLS: "http://${ETCD_IP:-127.0.0.1}:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://${ETCD_IP:-127.0.0.1}:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_INITIAL_CLUSTER_TOKEN: etcd-cluster-1
ETCD_INITIAL_CLUSTER: etcd-node=http://${ETCD_IP:-127.0.0.1}:2380
ETCD_INITIAL_CLUSTER_STATE: new
ETCDCTL_API: "3"
# 启用认证
ETCD_ROOT_PASSWORD: ${ETCD_ROOT_PASSWORD}
volumes:
- ./default.etcd:/default.etcd
- ./certs:/etc/etcd/certs
ports:
- "2379:2379"
- "2380:2380"
restart: unless-stopped
command:
- /usr/local/bin/etcd
- --name=etcd-node
- --data-dir=/default.etcd
- --advertise-client-urls=http://${ETCD_IP:-127.0.0.1}:2379
- --listen-client-urls=http://0.0.0.0:2379
- --initial-advertise-peer-urls=http://${ETCD_IP:-127.0.0.1}:2380
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-cluster-token=etcd-cluster-1
- --initial-cluster=etcd-node=http://${ETCD_IP:-127.0.0.1}:2380
- --initial-cluster-state=new

🔧 常用操作

使用 etcdctl 操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 设置环境变量
export ETCDCTL_API=3
export ETCDCTL_ENDPOINTS=http://127.0.0.1:2379

# 写入键值
docker compose exec etcd etcdctl put mykey "myvalue"

# 读取键值
docker compose exec etcd etcdctl get mykey

# 读取所有键(带前缀)
docker compose exec etcd etcdctl get --prefix my

# 删除键
docker compose exec etcd etcdctl del mykey

# 列出所有键
docker compose exec etcd etcdctl get --keys-only --prefix ""

# 查看集群成员
docker compose exec etcd etcdctl member list

# 查看集群健康状态
docker compose exec etcd etcdctl endpoint health

查看日志

1
docker compose logs -f etcd

备份数据

1
2
3
4
5
# 创建快照
docker compose exec etcd etcdctl snapshot save /backup/etcd-snapshot.db

# 查看快照信息
docker compose exec etcd etcdctl snapshot status /backup/etcd-snapshot.db

恢复数据

1
2
3
4
5
6
7
8
9
# 停止 Etcd
docker compose stop etcd

# 恢复快照
docker compose exec etcd etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/default.etcd

# 重启服务
docker compose start etcd

🔐 安全配置建议

1. 启用认证

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建 root 用户
docker compose exec etcd etcdctl user add root

# 启用认证
docker compose exec etcd etcdctl auth enable

# 创建普通用户
docker compose exec etcd etcdctl user add myuser

# 授予权限
docker compose exec etcd etcdctl role add myrole
docker compose exec etcd etcdctl role grant-permission myrole readwrite --prefix=/myapp/
docker compose exec etcd etcdctl user grant-role myuser myrole

2. 使用 TLS 加密

1
2
3
4
5
6
7
8
9
10
11
command:
- /usr/local/bin/etcd
- --name=etcd-node
- --cert-file=/etc/etcd/certs/server.crt
- --key-file=/etc/etcd/certs/server.key
- --trusted-ca-file=/etc/etcd/certs/ca.crt
- --client-cert-auth=true
- --peer-cert-file=/etc/etcd/certs/peer.crt
- --peer-key-file=/etc/etcd/certs/peer.key
- --peer-trusted-ca-file=/etc/etcd/certs/ca.crt
- --peer-client-cert-auth=true

3. 限制网络访问

生产环境建议不暴露端口,或使用防火墙限制:

1
2
3
4
5
6
7
# 不暴露端口,仅内部网络访问
# ports:
# - "2379:2379"
# - "2380:2380"

networks:
- internal_network

📊 监控与维护

查看集群状态

1
docker compose exec etcd etcdctl endpoint status --write-out=table

查看集群健康

1
docker compose exec etcd etcdctl endpoint health

查看成员信息

1
docker compose exec etcd etcdctl member list

监控指标

Etcd 在 /metrics 端点提供 Prometheus 格式的指标:

1
curl http://127.0.0.1:2379/metrics

🐛 常见问题

1. 集群无法启动

  • 检查 ETCD_INITIAL_CLUSTER 配置是否正确
  • 确认所有节点网络连通性
  • 查看日志:docker compose logs etcd

2. 数据目录权限问题

1
sudo chown -R 1000:1000 ./default.etcd

3. 端口冲突

修改 docker-compose.yml 中的端口映射:

1
2
3
ports:
- "23790:2379" # 使用不同的主机端口
- "23800:2380"

4. 集群分裂

如果集群出现分裂,需要重新初始化:

1
2
3
4
5
6
7
8
# 停止所有节点
docker compose down

# 清理数据目录
rm -rf ./default.etcd

# 重新启动
docker compose up -d

📚 参考资源

0%