前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用 Docker 在一台宿主机启动多个 etcd 节点

用 Docker 在一台宿主机启动多个 etcd 节点

原创
作者头像
amc
修改2021-03-11 17:23:44
1.9K0
修改2021-03-11 17:23:44
举报
文章被收录于专栏:后台全栈之路后台全栈之路

在学习和开发基于 etcd 的服务和功能时,需要自己在本地部署一套 etcd 集群。

原以为这是一个简单的事情,但意外地花了我几个小时才搞定……本文介绍有效的部署方法和踩过的一些坑。


网络准备

  我们以三个节点为例。首先,默认的 etcd 监听 2370 端口,提供 HTTP API;另外采用 2380 端口完成节点之间(peer)的通信。

  其次,官方文档采用的是在多个 IP 地址上部署不同的节点。但我只想在手头的一台 MacBook 上部署多个 etcd 容器。

  第三,网上的教程使用的都是 docker-compose 来部署多节点,但这也不符合我的需求,因为我需要动态启动和关闭节点,模拟节点故障,从而观察 etcd 的状态。

  综上所述,我需要给这个 etcd 集群分配总共 6 个端口,举例如下:

节点名称

http

peer

etcd-node-1

21379

21380

etcd-node-2

22379

22380

etcd-node-3

23379

23380


启动脚本

  我的操作系统是 maxOS v11.2.1,Docker 是 Docker Desktop 3.1.0 版,shell 是 zsh,脚本如下:

代码语言:txt
复制
# For each machine
# SUDO=sudo
SUDO=
ETCD_VERSION=v3.2.30
TOKEN=amc-etcd-token
CLUSTER_STATE=new
NAMES=(etcd-node-0 etcd-node-1 etcd-node-2)
HOSTS=(host.docker.internal host.docker.internal host.docker.internal)
CLIENT_PORTS=(21379 22379 23379)
PARTNER_PORTS=(21380 22380 23380)

# test array index start
_first=0
if [ -z ${NAMES[0]} ]; then
    _first=1;
fi

CLUSTER=${NAMES[_first]}=http://${HOSTS[_first]}:${PARTNER_PORTS[_first]}
for (( i=1; i < ${#NAMES[@]}; i++)) do
    CLUSTER=${CLUSTER},${NAMES[$i+${_first}]}=http://${HOSTS[$i+${_first}]}:${PARTNER_PORTS[$i+${_first}]};
done;

echo CLUSTER=${CLUSTER}

# For each node 1
for (( i=0; i < ${#NAMES[@]}; i++)) do
    THIS_NAME=${NAMES[$i+${_first}]};
    THIS_HOST=${HOSTS[$i+${_first}]};
    THIS_CLIENT_PORT=${CLIENT_PORTS[$i+${_first}]};
    THIS_PARTNER_PORT=${PARTNER_PORTS[$i+${_first}]};
    ${SUDO} docker run -d --name ${THIS_NAME} \
        -p ${THIS_PARTNER_PORT}:2380 -p ${THIS_CLIENT_PORT}:2379 \
        quay.io/coreos/etcd:${ETCD_VERSION} \
        /usr/local/bin/etcd \
        --data-dir=data.etcd --name ${THIS_NAME} \
        --initial-advertise-peer-urls http://${THIS_HOST}:${THIS_PARTNER_PORT} --listen-peer-urls http://0.0.0.0:2380 \
        --advertise-client-urls http://${THIS_HOST}:${THIS_CLIENT_PORT} --listen-client-urls http://0.0.0.0:2379 \
        --initial-cluster ${CLUSTER} \
        --initial-cluster-token ${TOKEN} \
        --initial-cluster-state ${CLUSTER_STATE};
done;

脚本逻辑说明

  读者只需要修改上文的脚本中前置的几个变量即可,如下:

  • ETCD_VERSION: etcd 的版本
  • NAMES: 这是个数组,表示各个节点的名称。本脚本中也作为容器名
  • HOSTS: 各个节点对外暴露的主机地址。既然是同一主机,并且我采用的是 docker 的 bridge 网络,那么就统一采用 host.docker.internal 即可
  • CLIENT_PORTS: 分配给各个节点的原 2379 端口的映射
  • PARTNER_PORTS: 分配给各个节点的原 2380 端口的映射

  后面的四个数组变量的长度必须相等。

其他注意事项

数组下标问题

  首先,该脚本采用了 macOS 现在的默认 shell /bin/zsh,但依然也可以在 shbash 下执行。但是 zsh 有一个很大的不同:数组下标从 1 而不是 0 开始。

笔者长期在 Linux 下写脚本,差点把这个问题忽略了。因此,在脚本中通过以下语句做了兼容:

代码语言:txt
复制
_first=0
if [ -z ${NAMES[0]} ]; then
    _first=1;
fi

  迭代数组成员的时候使用 $i+${_first}

etcd 版本

  笔者最开始参照 etcd 的官方文档,采用了 v3.0.0 版的 etcd,但是节点在启动后会出现以下错误:

代码语言:txt
复制
v3rpc/grpc: grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp [::]:2379: connect: cannot assign requested address"; Reconnecting to {"[::]:2379" <nil>}

  找了很久没有找到原因和解决方案。后来,我改用 v3.2.20,问题就迎刃而解了。看来这应该是 etcd 旧版的一个 bug 了。

  此外,--listen-peer-urls--listen-client-urls 不能监听在 127.0.0.1localhost 上,因为这就变成了容器内部的环回地址,无法接收到来自容器外的(包括宿主机和其他容器)的请求。


验证功能

  搭建成功啦,在宿主机上调用 etcd API 即可验证,三个节点都可以验证一遍:

代码语言:txt
复制
% curl http://127.0.0.1:21379/v2/keys/message -X PUT -d value="Hello world"
{"action":"set","node":{"key":"/message","value":"Hello world","modifiedIndex":8,"createdIndex":8}}
% curl http://127.0.0.1:22379/v2/keys/message -X PUT -d value="Hello etcd"
{"action":"set","node":{"key":"/message","value":"Hello etcd","modifiedIndex":9,"createdIndex":9},"prevNode":{"key":"/message","value":"Hello world","modifiedIndex":8,"createdIndex":8}}
% curl http://127.0.0.1:23379/v2/keys/message -X PUT -d value="Hello ALL"
{"action":"set","node":{"key":"/message","value":"Hello ALL","modifiedIndex":10,"createdIndex":10},"prevNode":{"key":"/message","value":"Hello etcd","modifiedIndex":9,"createdIndex":9}}

  实际开发调试中,将这几个节点挂在 nginx 负载均衡后面就可以访问了。


参考资料


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原作者: amc,欢迎转载,但请注明出处。

原文标题:《用 Docker 在一台宿主机启动多个 etcd 节点

发布日期:2021-02-22

原文链接:/developer/article/1790869

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 网络准备
  • 启动脚本
    • 脚本逻辑说明
      • 其他注意事项
        • 数组下标问题
        • etcd 版本
    • 验证功能
    • 参考资料
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
    http://www.vxiaotou.com