docker部署etcd集群

最近因为工作内容调整,需要对etcd进行学习。随手记录了一些docker部署etcd集群的方式。

首先什么是etcd

etcd是一个高可用的分布式键值(KV)数据库。可以用来实现各种分布式协同服务。内部采用raft协议作为一致性算法。基于go语言实现

特点

简单:

  • 支持RESTful风格的HTTP+JSON的API

  • v3版本增加了对gRPC的支持 同时也提供rest gateway进行转化

  • Go语言编写,跨平台,部署和维护简单

  • 使用Raft算法保证强一致性,Raft算法可理解性好

安全:支持SSL证书验证、支持TLS客户端安全认证

性能:单实例(V3)支持每秒10KQps Qps = 并发量/平均相应时间 并发量 = Qps * 平均相应时间

可靠:使用 Raft 算法充分保证了分布式系统数据的强一致性 etcd 集群是一个分布式系统,由多个节点相互通信构成整体的对外服务,每个节点都存储了完整的数据,并且通过 Raft 协议保证了每个节点维护的数据都是一致的。

etcd可以扮演两大角色:

  • 持久化的键值存储系统

  • 分布式系统数据一致性服务提供者

架构模块

etcd 大体可以分为 网络层(http(s) server)、raft算法模块、复制状态机(RSM)和存储模块

  • 网络层:提供网络数据读写功能,监听服务端口,完成集群节点之间数据通信,收发客户端数据。

  • Raft模块:Raft强一致性算法的具体实现。

  • 存储模块:涉及KV存储、WAL文件、Snapshot管理等,用户处理etcd支持的各类功能的事务,包括数据索引 节点状态变更、监控与反馈、事件处理与执行 ,是 etcd 对用户提供的大多数 API 功能的具体实现。

  • 复制状态机:这是一个抽象的模块,状态机的数据维护在内存中,定期持久化到磁盘,每次写请求都会持久化到 WAL 文件,并根据写请求的内容修改状态机数据。

执行流程

通常,一个用户的请求发送过来,会经由 HTTP ( S) Server 转发给存储模块进行具体的事务处理,如果涉及节点状态的更新,则交给 Raft 模块进行仲裁和日志的记录,然后再同步给别的 etcd 节点,只有当半数以上的节点确认了该节点状态的修改之后,才会进行数据的持久化。

etcd 集群的各个节点之间需要通过网络来传递数据,具体表现为如下几个方面:

  1. Leader Follower 发送心跳包, Follower Leader 回复消息

  2. Leader Follower 发送日志追加信息

  3. Leader Follower 发送 Snapshot 数据

  4. Candidate 节点发起选举,向其他节点发起投票请求

  5. Follower 将收到的写操作转发给 Leader

etcd与zookeeper的比较

  1. CAP原则(CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。)

    zk和etcd都是顺序一致性的,满足CAP中的CP。任何时间访问节点都会获取到最终一致的数据视图。因为zk的paxos和etcd使用的raft算法都是大多数同意原则。所以部分节点可能会延迟接收到更新,但数据最终将一致。

  2. zk从逻辑上来讲是一种目录结构,etcd从逻辑上来说就是一个k-v结构

    但是etcd的key可以是任意字符串,同时在存储上实现了key的有序排列

    所以etcd是可以模拟出树桩的结构的 key = /A/B/C 、/A/B、/A

    本质上来说etcd是一个有序的kv存储

  3. 临时节点

    在实现服务发现时,我们一般都会用到zookeeper的临时节点。当客户端掉线一段时间,对应的zookeeper session会过期,那么对应的临时节点就会被自动删除。

    在etcd中对应的是lease租约机制,通过该机制实现了key的自动删除。

    可以在set key的同时携带lease ID,当lease过期后所有关联的key都将被自动删除

  4. 事件模型

    在我们用zookeeper实现服务发现时,我们一般会getChildrenAndWatch来获取一个目录下的所有在线节点,这个API会先获取当前的孩子列表并同时原子注册了一个观察器。

    每当zookeeper发现孩子有变动的时候,就会发送一个通知事件给客户端(同时关闭观察器),此时我们会再次调用getChildrenAndWatch再次获取最新的孩子列表并重新注册观察器。

    简单的来说,zookeeper提供了一个原子API,它先获取当前状态,同时注册一个观察器,当后续变化发生时会发送一次通知到客户端:获取并观察->收到变化事件->获取并观察->收到变化事件->….,如此往复。

    zookeeper的事件模型非常可靠,不会出现发生了更新而客户端不知道的情况,但是特点也很明显:

    • 事件不包含数据,仅仅是通知变化。

    • 多次连续的更新,通知会合并成一个;即,客户端收到通知再次拉取数据,会跳过中间的多个版本,只拿到最新数据。

    这些特点并不是缺点,因为一般应用只关注最新状态,并不关注中间的连续变化。

    相反etcd的事件是包含数据的,并且通常情况下连续的更新不会被合并通知,而是逐条通知到客户端。

docker部署etcd集群

vmwarm 16 pro 本地虚拟机

198.168.234.128~130

##通过docker pull 拉取3.5.0镜像版本
[root@localhost docker]# docker pull quay.io/coreos/etcd:v3.5.0
​
##拉取成功
[root@localhost docker]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
quay.io/coreos/etcd   v3.5.0    a7908fd5fb88   11 months ago   110MB
​
##官网下载docker-compose镜像
[root@localhost data]# cd /usr/local
[root@localhost local]# cd bin
[root@localhost bin]# ll
总用量 25912
-rw-r--r--. 1 root root 26533888 5月  23 09:44 docker-compose-linux-x86_64
[root@localhost bin]# mv docker-compose-linux-x86_64 docker-compose
[root@localhost bin]# ll
总用量 25912
-rw-r--r--. 1 root root 26533888 5月  23 09:44 docker-compose
[root@localhost bin]# chmod 777 docker-compose
[root@localhost bin]# ll
总用量 25912
-rwxrwxrwx. 1 root root 26533888 5月  23 09:44 docker-compose
##验证docker-compose 版本
[root@localhost bin]# ./docker-compose version
Docker Compose version v2.5.1
[root@localhost bin]# vim ~/.bash_profile
##配置环境变量
PATH=$PATH:$HOME/bin:/usr/local/bin
[root@localhost bin]# source ~/.bash_profile
[root@localhost bin]# cd /
[root@localhost /]# docker-compose version
Docker Compose version v2.5.1

单节点部署

docker-compose.yml文件编写

version: '3'
networks:
  myetcd_single:
services:
  etcd:
    image: quay.io/coreos/etcd
    container_name: etcd_single
    command: etcd -name etcd1 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 ##基本etcd配置 通过2380端口进行通信 通过2379端口监听
    ports:
      - 12379:2379
      - 12380:2380
    volumes:
      - ./data:/etcd-data ## 挂载数据卷
    networks:
      - myetcd_single
  etcdkeeper:
    image: deltaprojects/etcdkeeper
    container_name: etcdkeeper_single
    ports:
      - 8088:8080
    networks:
      - myetcd_single

执行docker-compose.yml文件

[root@localhost data]# docker-compose up -d
[root@localhost data]# docker ps
CONTAINER ID   IMAGE                        COMMAND                  CREATED              STATUS              PORTS                                              NAMES
45edb1a12ada   quay.io/coreos/etcd          "etcd -name etcd1 -a…"   About a minute ago   Up About a minute   0.0.0.0:12379->2379/tcp, 0.0.0.0:12380->2380/tcp   etcd_single
af5c7cb06080   deltaprojects/etcdkeeper     "/bin/sh -c './etcdk…"   About a minute ago   Up About a minute   0.0.0.0:8088->8080/tcp                             etcdkeeper_single
​
[root@localhost data]# docker exec -it 45e etcdctl member list
b063ce376278837c: name=etcd1 peerURLs=http://172.18.0.3:2380 clientURLs=http://0.0.0.0:2379 isLeader=true
​
​

集群部署

准备好三台虚机之后,调整docker-compose文件

## 其他docker-compose替换地址即可
version: '3'
services:
  etcd:
    container_name: etcd
    image: quay.io/coreos/etcd
    ports:
      - "12379:2379"
      - "12380:2380"
    network_mode: "host"
    restart: always
    stdin_open: true
    tty: true
    command: etcd --name etcd-128 --data-dir /data/app/etcd/ --listen-peer-urls http://192.168.234.128:2380 --listen-client-urls http://127.0.0.1:2379,http://192.168.234.128:2379 --initial-advertise-peer-urls http://192.168.234.128:2380 --advertise-client-urls http://127.0.0.1:2379,http://192.168.234.128:2379 --initial-cluster-token etcd-cluster --initial-cluster "etcd-128=http://192.168.234.128:2380,etcd-129=http://192.168.234.129:2380,etcd-130=http://192.168.234.130:2380" --auto-compaction-retention 24 --max-wals 3 --max-snapshots 3 --snapshot-count 30000 --heartbeat-interval 700 --election-timeout 3500 --initial-cluster-state new
    volumes:
      - /data/app/etcd/:/data/app/etcd
​
##执行docker-compose文件
[root@localhost etcd]# docker-compose up -d
[+] Running 1/1
 ⠿ Container etcd  Started                                                                                                                                         0.2s
[root@localhost etcd]# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS     NAMES
2ec977d8e222   quay.io/coreos/etcd   "etcd --name etcd-13…"   About a minute ago   Up About a minute             etcd
##执行成功后 进入docker容器中
[root@localhost etcd]# docker exec -it 2ec /bin/sh
/ # etcdctl member list 
136956e961af78a1: name=etcd-128 peerURLs=http://192.168.234.128:2380 clientURLs=http://127.0.0.1:2379,http://192.168.234.128:2379 isLeader=true
dec5185119cc78dc: name=etcd-129 peerURLs=http://192.168.234.129:2380 clientURLs=http://127.0.0.1:2379,http://192.168.234.129:2379 isLeader=false
ea5b7cd8877afcc2: name=etcd-130 peerURLs=http://192.168.234.130:2380 clientURLs=http://127.0.0.1:2379,http://192.168.234.130:2379 isLeader=false
​

通过docker-compose进行容器创建

docker-compose up -d
#集群内容器全部拉起后,执行
docker exec -it container
#进入容器后执行 put key命令发现报错
etcdctl put name "i am lipeng"
#需要执行环境变量
export ETCDCTL_API=3
#再次执行成功
/ # etcdctl put name "i am *"
OK
#在etcd-129上执行
/ # etcdctl get name
name
i am *

你可能感兴趣的:(docker,etcd)