Docker 最佳实战:Docker 部署 etcd 集群实战
2024 年云原生运维实战文档 99 篇原创计划 第 005 篇 |Docker 最佳实战「2024」系列 第 005 篇
前言
你好,欢迎来到运维有术。
今天分享的内容是 Docker 最佳实战「2024」 系列文档中的 Docker 部署 etcd 集群实战。
内容导图
实战服务器配置 (架构 1:1 复刻小规模生产环境,配置略有不同)
主机名 | IP | CPU(核) | 内存(GB) | 系统盘(GB) | 数据盘(GB) | 用途 |
---|---|---|---|---|---|---|
docker-node-1 | 192.168.9.81 | 4 | 16 | 40 | 100 | Docker 节点 1 |
docker-node-2 | 192.168.9.82 | 4 | 16 | 40 | 100 | Docker 节点 2 |
docker-node-3 | 192.168.9.83 | 4 | 16 | 40 | 100 | Docker 节点 3 |
合计 | 3 | 12 | 48 | 120 | 300 |
实战环境涉及软件版本信息
- 操作系统:openEuler 22.03 LTS SP3
- Docker:24.0.7
- Containerd:1.6.27
- Etcd:3.5.12
上一期我们基于 coreos 官方提供的 Docker 镜像完成了单节点 etcd 部署实战。
本期我们继续基于配置文件和环境变量两种方式,完成 etcd 集群部署实战。
1. 部署 etcd 集群-基于配置文件
本节内容使用配置文件的方式实现 etcd 集群服务配置。
1.1 创建 etcd 数据目录
代码语言:bash复制mkdir -p /data/containers/etcd/{data,config}
- data 目录:建议, 存储容器持久化数据
- config 目录:建议, 存储容器使用的配置文件
1.2 创建 etcd 配置文件
etcd 服务配置文件路径为:/data/containers/etcd/config/etcd.conf.yml
每个节点内容不一样,需要分别编写。
节点 1 的文件内容如下:
代码语言:yaml复制name: etcd-1
data-dir: /var/etcd
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls: http://192.168.9.81:2379
listen-peer-urls: http://0.0.0.0:2380
initial-advertise-peer-urls: http://192.168.9.81:2380
initial-cluster: etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380
initial-cluster-token: etcd-cluster
initial-cluster-state: new
logger: zap
log-level: info
#log-outputs: stder
节点 2 的文件内容如下:
代码语言:yaml复制name: etcd-2
data-dir: /var/etcd
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls: http://192.168.9.82:2379
listen-peer-urls: http://0.0.0.0:2380
initial-advertise-peer-urls: http://192.168.9.82:2380
initial-cluster: etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380
initial-cluster-token: etcd-cluster
initial-cluster-state: new
logger: zap
log-level: info
#log-outputs: stderr
节点 3 的文件内容如下:
代码语言:yaml复制name: etcd-3
data-dir: /var/etcd
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls: http://192.168.9.83:2379
listen-peer-urls: http://0.0.0.0:2380
initial-advertise-peer-urls: http://192.168.9.83:2380
initial-cluster: etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380
initial-cluster-token: etcd-cluster
initial-cluster-state: new
logger: zap
log-level: info
#log-outputs: stder
配置文件特殊配置项说明:
- name: 每个节点的 etcd 服务名称
- advertise-client-urls: 填写每个 etcd 容器所在节点对外提供服务的 IP
- initial-advertise-peer-urls: 填写每个 etcd 容器所在节点对外提供服务的 IP
- initial-cluster: 每个节点使用相同配置,包含所有节点的名称和 initial-advertise-peer-urls 地址
1.3 创建 docker-compose 文件
代码语言:yaml复制version: '3'
services:
etcd:
container_name: etcd
image: quay.io/coreos/etcd:v3.5.12
command: /usr/local/bin/etcd --config-file=/var/lib/etcd/conf/etcd.conf.yml
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd
- ${DOCKER_VOLUME_DIRECTORY:-.}/config/etcd.conf.yml:/var/lib/etcd/conf/etcd.conf.yml
- "/etc/localtime:/etc/localtime:ro"
ports:
- 2379:2379
- 2380:2380
restart: always
networks:
default:
name: etcd-tier
driver: bridge
1.4 创建并启动 etcd 服务
所有节点都执行下面的命令,完成 etcd 集群服务的创建。
代码语言:bash复制cd /data/containers/etcd
docker compose up -d
命令成功执行的结果如下 (以节点 1 为例):
代码语言:bash复制[root@docker-node-1 etcd]# docker compose up -d
[ ] Running 1/2
⠸ Network etcd-tier Created 0.4s
✔ Container etcd-s1 Started
1.5 验证容器状态
- 查看 etcd 容器状态 (以节点 1 为例)
[root@docker-node-1 etcd]# docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
etcd-1 quay.io/coreos/etcd:v3.5.12 "/usr/local/bin/etcd…" etcd 53 seconds ago Up 53 seconds 0.0.0.0:2379-2380->2379-2380/tcp, :::2379-2380->2379-2380/tcp
2. 部署 etcd 集群-基于环境变量
本节内容使用环境变量的方式实现 etcd 服务配置。
2.1 创建 etcd 数据目录
代码语言:bash复制mkdir -p /data/containers/etcd/data
- data 目录:建议, 存储容器持久化数据
2.2 创建 docker-compose 文件
每个节点内容不一样,需要分别编写,vi/data/containers/etcd/docker-compose.yml
节点 1 的文件内容如下:
代码语言:yaml复制version: '3'
services:
etcd:
container_name: etcd-s1
image: quay.io/coreos/etcd:v3.5.12
environment:
- ETCD_NAME=etcd-1
- ETCD_DATA_DIR=/var/etcd
- ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
- ETCD_ADVERTISE_CLIENT_URLS=http://192.168.9.81:2379
- ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
- ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.168.9.81:2380
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
- ETCD_INITIAL_CLUSTER=etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCD_LOGGER=zap
- ETCD_LOG_LeveL=info
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd
- "/etc/localtime:/etc/localtime:ro"
ports:
- 2379:2379
- 2380:2380
restart: always
networks:
default:
name: etcd-tier
driver: bridge
节点 2 的文件内容如下:
代码语言:yaml复制version: '3'
services:
etcd:
container_name: etcd-s1
image: quay.io/coreos/etcd:v3.5.12
environment:
- ETCD_NAME=etcd-1
- ETCD_DATA_DIR=/var/etcd
- ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
- ETCD_ADVERTISE_CLIENT_URLS=http://192.168.9.82:2379
- ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
- ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.168.9.82:2380
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
- ETCD_INITIAL_CLUSTER=etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCD_LOGGER=zap
- ETCD_LOG_LeveL=info
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd
- "/etc/localtime:/etc/localtime:ro"
ports:
- 2379:2379
- 2380:2380
restart: always
networks:
default:
name: etcd-tier
driver: bridge
节点 3 的文件内容如下:
代码语言:yaml复制version: '3'
services:
etcd:
container_name: etcd-s1
image: quay.io/coreos/etcd:v3.5.12
environment:
- ETCD_NAME=etcd-1
- ETCD_DATA_DIR=/var/etcd
- ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
- ETCD_ADVERTISE_CLIENT_URLS=http://192.168.9.83:2379
- ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
- ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.168.9.83:2380
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
- ETCD_INITIAL_CLUSTER=etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCD_LOGGER=zap
- ETCD_LOG_LeveL=info
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd
- "/etc/localtime:/etc/localtime:ro"
ports:
- 2379:2379
- 2380:2380
restart: always
networks:
default:
name: etcd-tier
driver: bridge
配置文件特殊配置项说明:
- ETCD_NAME 每个节点的 etcd 服务名称
- ETCD_ADVERTISE_CLIENT_URLS 填写每个 etcd 容器所在节点对外提供服务的 IP
- ETCD_INITIAL_ADVERTISE_PEER_URLS 填写每个 etcd 容器所在节点对外提供服务的 IP
- ETCD_INITIAL_CLUSTER:每个节点使用相同配置,包含所有节点的名称和
ETCD_INITIAL_ADVERTISE_PEER_URLS
地址
2.3 创建并启动 etcd 服务
所有节点都执行下面的命令,完成 etcd 集群服务的创建。
代码语言:bash复制cd /data/containers/etcd
docker compose up -d
2.4 验证容器状态
- 查看 etcd 容器状态 (以节点 1 为例)
[root@docker-node-1 etcd]# docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
etcd-1 quay.io/coreos/etcd:v3.5.12 "/usr/local/bin/etcd…" etcd 53 seconds ago Up 53 seconds 0.0.0.0:2379-2380->2379-2380/tcp, :::2379-2380->2379-2380/tcp
3. etcd 服务可用性测试
为了测试 etcd 服务的可用性,额外再找一台机器安装 etcd 客户端工具用于验证测试。
- 下载并解压软件包
cd /srv
wget https://github.com/etcd-io/etcd/releases/download/v3.5.12/etcd-v3.5.12-linux-amd64.tar.gz
tar xvf etcd-v3.5.12-linux-amd64.tar.gz
cd etcd-v3.5.12-linux-amd64
- 使用 etcdctl 工具验证测试 endpoint
# ./etcdctl --endpoints=192.168.9.81:2379,192.168.9.82:2379,192.168.9.83:2379 --write-out=table endpoint health
------------------- -------- ------------- -------
| ENDPOINT | HEALTH | TOOK | ERROR |
------------------- -------- ------------- -------
| 192.168.9.81:2379 | true | 6.698562ms | |
| 192.168.9.82:2379 | true | 20.894522ms | |
| 192.168.9.83:2379 | true | 21.585328ms | |
------------------- -------- ------------- -------
# ./etcdctl --endpoints=192.168.9.81:2379,192.168.9.82:2379,192.168.9.83:2379 --write-out=table endpoint status
------------------- ------------------ --------- --------- ----------- ------------ ----------- ------------ -------------------- --------
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
------------------- ------------------ --------- --------- ----------- ------------ ----------- ------------ -------------------- --------
| 192.168.9.81:2379 | ee1780cf52566749 | 3.5.12 | 20 kB | true | false | 2 | 13 | 13 | |
| 192.168.9.82:2379 | 94e339f5d245a36b | 3.5.12 | 20 kB | false | false | 2 | 13 | 13 | |
| 192.168.9.83:2379 | 247803a54771eb27 | 3.5.12 | 20 kB | false | false | 2 | 13 | 13 | |
------------------- ------------------ --------- --------- ----------- ------------ ----------- ------------ -------------------- --------
- 使用 etcdctl 工具验证测试 member
# ./etcdctl --endpoints=192.168.9.81:2379,192.168.9.82:2379,192.168.9.83:2379 --write-out=table member list
------------------ --------- -------- -------------------------- -------------------------- ------------
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
------------------ --------- -------- -------------------------- -------------------------- ------------
| 247803a54771eb27 | started | etcd-3 | http://192.168.9.83:2380 | http://192.168.9.83:2379 | false |
| 94e339f5d245a36b | started | etcd-2 | http://192.168.9.82:2380 | http://192.168.9.82:2379 | false |
| ee1780cf52566749 | started | etcd-1 | http://192.168.9.81:2380 | http://192.168.9.81:2379 | false |
------------------ --------- -------- -------------------------- -------------------------- ------------
- 使用 etcdctl 工具验证测试数据读写
# 写入数据
# ./etcdctl --endpoints=192.168.9.81:2379,192.168.9.82:2379,192.168.9.83:2379 put foo bar
OK
# 读取数据
# ./etcdctl --endpoints=192.168.9.81:2379,192.168.9.82:2379,192.168.9.83:2379 get foo
foo
bar
4. 自动化 Shell 脚本
全文所有的操作,我都整理成了自动化脚本。
自动化脚本说明:
- 由于调试过程中没有解决 EOF 报错的问题,function 里 cat 部分的内容没有缩进,看着不美观,但是不影响使用。
- Shell 脚本实现这种多节点,多变量的自动化部署配置比较麻烦,实际中建议使用 Ansible 实现自动化。
4.1 配置文件模式
编写部署脚本 deploy-etcd-cluser-conf.sh
#!/bin/bash
# author:@运维有术
set -e
# 设置 etcd 服务名称,必须修改
etcd_name=${1:-"etcd-1"}
# 设置 etcd 服务对外 IP,必须修改(填写 etcd 容器所在节点对外提供服务的 IP)
etcd_client_ip=${2:-"0.0.0.0"}
# 设置 etcd 初始化集群信息,必须修改
etcd_initial_cluster=${3:-"etcd-1=http://192.168.9.81:2380,etcd-2=http://192.168.9.82:2380,etcd-3=http://192.168.9.83:2380"}
# 设置 containers 基础目录,可选修改
docker_container_dir=${4:-"/data/containers"}
# 创建基础目录
mkdir -p ${docker_container_dir}/etcd/{data,config}
# 创建 etcd 配置文件
function deploy_etcd_config(){
cat > ${docker_container_dir}/etcd/config/etcd.conf.yml <<-EOF
name: ${etcd_name}
data-dir: /var/etcd
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls: http://${etcd_client_ip}:2379
listen-peer-urls: http://0.0.0.0:2380
initial-advertise-peer-urls: http://${etcd_client_ip}:2380
initial-cluster: ${etcd_initial_cluster}
initial-cluster-token: etcd-cluster
initial-cluster-state: new
logger: zap
log-level: info
#log-outputs: stderr
EOF
}
# 创建 docker-compose 文件
function deploy_compose_config(){
cat > ${docker_container_dir}/etcd/docker-compose.yml <<-EOF
version: '3'
services:
etcd:
container_name: ${etcd_name}
image: quay.io/coreos/etcd:v3.5.12
command: /usr/local/bin/etcd --config-file=/var/lib/etcd/conf/etcd.conf.yml
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd
- ${DOCKER_VOLUME_DIRECTORY:-.}/config/etcd.conf.yml:/var/lib/etcd/conf/etcd.conf.yml
- "/etc/localtime:/etc/localtime:ro"
ports:
- 2379:2379
- 2380:2380
restart: always
networks:
default:
name: etcd-tier
driver: bridge
EOF
}
# 创建 etcd 服务
function deploy_etcd(){
cd ${docker_container_dir}/etcd
docker compose up -d
}
# 验证 etcd 服务
function check_etcd(){
cd ${docker_container_dir}/etcd
docker compose ps
}
echo -e "