从零开始搭建ETCD分布式一致性存储系统

什么是ETCD

Etcd是一个高可用的 Key/Value 存储系统,用于服务发现的基础注册和通知,通过注册和监听,实现基础的服务发现。
Etcd是coreos开发的分布式服务系统,内部采用raft协议作为一致性算法

Etcd构建自身高可用集群主要有三种形式:

  1. 静态发现: 预先已知 Etcd 集群中有哪些节点,在启动时直接指定好Etcd的各个node节点地址
  2. Etcd动态发现: 通过已有的Etcd集群作为数据交互点,然后在扩展新的集群时实现通过已有集群进行服务发现的机制
  3. DNS动态发现: 通过DNS查询方式获取其他节点地址信息

下面会给大家介绍etcd的使用,主要包括下面几步

  1. 安装
  2. 单机运行
  3. 集群搭建
  4. 监听功能watch(服务发现原理)
  5. curl调用API

一.安装

下载地址:https://github.com/coreos/etcd/releases/

mkdir -p /home/chenqionghe/test/etcd/
cd !$
# 下载
wget https://github.com/etcd-io/etcd/releases/download/v3.3.12/etcd-v3.3.12-linux-amd64.tar.gz
# 解压安装
tar zxvf etcd-v3.3.12-linux-amd64.tar.gz
cd etcd-v3.3.12-linux-amd64
## 将启动文件和命令管理文件拷贝到 PATH找到的路径中
cp etcd /usr/local/bin
cp etcdctl /usr/local/bin
cp -r etcd-v3.2.5-linux-amd64 /usr/local/etcd  #将软件放置到常用目录下

启动参数解释

--name
etcd集群中的节点名,这里可以随意,可区分且不重复就行  
--listen-peer-urls
监听的用于节点之间通信的url,可监听多个,集群内部将通过这些url进行数据交互(如选举,数据同步等)
--initial-advertise-peer-urls 
建议用于节点之间通信的url,节点间将以该值进行通信。
--listen-client-urls
监听的用于客户端通信的url,同样可以监听多个。
--advertise-client-urls
建议使用的客户端通信url,该值用于etcd代理或etcd成员与etcd节点通信。
--initial-cluster-token etcd-cluster-1
节点的token值,设置该值后集群将生成唯一id,并为每个节点也生成唯一id,当使用相同配置文件再启动一个集群时,只要该token值不一样,etcd集群就不会相互影响。
--initial-cluster
也就是集群中所有的initial-advertise-peer-urls 的合集
--initial-cluster-state new
新建集群的标志

二.单机运行

直接启动

etcd

etcd默认监听的是localhost的2379端口,既只监听了lo设备,这样会导致启动后集群中的其他机器无法访问
因此我们可以在启动的时候将默认的localhost改成0.0.0.0l,确保etcd监听了所有网卡。

etcd -listen-client-urls="http://0.0.0.0:2379" --advertise-client-urls="http://0.0.0.0:2379"

*** 注意:etcd有要求,如果--listen-client-urls被设置了,那么就必须同时设置--advertise-client-urls,所以即使设置和默认相同,也必须显式设置***
我们来使用curl来测试一下,是否可以远程访问,这里我的机器IP是10.211.55.25

➜  ~ curl -L  http://10.211.55.25:2379/version
{"etcdserver":"3.3.12","etcdcluster":"3.3.0"}%

ok,我们可以看到etcd已经可以正常访问了

三.集群搭建

这里我们采用Static方式,准备三台机器,ip如下(都已经安装etcd)

node1 10.211.55.2
node2 10.211.55.25
node3 10.211.55.26

进入node1,创建并运行run.sh,脚本内容如下

#!/usr/bin/env bash
#节点名称
ETCD_NAME=node-1
#本机IP地址
LOCAL_IP=10.211.55.2
#ETCD存储目录
ETCD_DATA_DIR=/usr/local/etcd/data
#初始化名称
INITIAL_CLUSTER_TOKEN=cqh-test-cluster
#初始化群集列表
INITIAL_CLUSTER="node-1=http://10.211.55.2:2380,node-2=http://10.211.55.25:2380,node-3=http://10.211.55.26:2380"
#初始化状态
INITIAL_CLUSTER_STATE=new

#开始运行
etcd --name ${ETCD_NAME} --data-dir ${ETCD_DATA_DIR} \
    --initial-advertise-peer-urls http://${LOCAL_IP}:2380 \
    --listen-peer-urls http://${LOCAL_IP}:2380 \
    --listen-client-urls http://${LOCAL_IP}:2379,http://127.0.0.1:2379 \
    --advertise-client-urls http://${LOCAL_IP}:2379 \
    --initial-cluster-token ${INITIAL_CLUSTER_TOKEN} \
    --initial-cluster ${INITIAL_CLUSTER} \
    --initial-cluster-state ${INITIAL_CLUSTER_STATE}

进入node2,创建并运行run.sh,脚本内容和node1差不多(只修改了ETCD_NAME和LOCAL_IP)

#!/usr/bin/env bash
#节点名称
ETCD_NAME=node-2
#本机IP地址
LOCAL_IP=10.211.55.25
#ETCD存储目录
ETCD_DATA_DIR=/usr/local/etcd/data
#初始化名称
INITIAL_CLUSTER_TOKEN=cqh-test-cluster
#初始化群集列表
INITIAL_CLUSTER="node-1=http://10.211.55.2:2380,node-2=http://10.211.55.25:2380,node-3=http://10.211.55.26:2380"
#初始化状态
INITIAL_CLUSTER_STATE=new

#开始运行
etcd --name ${ETCD_NAME} --data-dir ${ETCD_DATA_DIR} \
    --initial-advertise-peer-urls http://${LOCAL_IP}:2380 \
    --listen-peer-urls http://${LOCAL_IP}:2380 \
    --listen-client-urls http://${LOCAL_IP}:2379,http://127.0.0.1:2379 \
    --advertise-client-urls http://${LOCAL_IP}:2379 \
    --initial-cluster-token ${INITIAL_CLUSTER_TOKEN} \
    --initial-cluster ${INITIAL_CLUSTER} \
    --initial-cluster-state ${INITIAL_CLUSTER_STATE}

进入node3,创建并运行run.sh

#!/usr/bin/env bash
#节点名称
ETCD_NAME=node-3
#本机IP地址
LOCAL_IP=10.211.55.26
#ETCD存储目录
ETCD_DATA_DIR=/usr/local/etcd/data
#初始化名称
INITIAL_CLUSTER_TOKEN=cqh-test-cluster
#初始化群集列表
INITIAL_CLUSTER="node-1=http://10.211.55.2:2380,node-2=http://10.211.55.25:2380,node-3=http://10.211.55.26:2380"
#初始化状态
INITIAL_CLUSTER_STATE=new

#开始运行
etcd --name ${ETCD_NAME} --data-dir ${ETCD_DATA_DIR} \
    --initial-advertise-peer-urls http://${LOCAL_IP}:2380 \
    --listen-peer-urls http://${LOCAL_IP}:2380 \
    --listen-client-urls http://${LOCAL_IP}:2379,http://127.0.0.1:2379 \
    --advertise-client-urls http://${LOCAL_IP}:2379 \
    --initial-cluster-token ${INITIAL_CLUSTER_TOKEN} \
    --initial-cluster ${INITIAL_CLUSTER} \
    --initial-cluster-state ${INITIAL_CLUSTER_STATE}

我们看到3台都启动成功了

接下来我们操作在node2上面执行操作

root@ubuntu:~# etcdctl member list
2033c1336b929ca7: name=node-3 peerURLs=http://10.211.55.26:2380 clientURLs=http://10.211.55.26:2379 isLeader=true
edc51d36208cfbcf: name=node-2 peerURLs=http://10.211.55.25:2380 clientURLs=http://10.211.55.25:2379 isLeader=false
f09a9dba19a725e2: name=node-1 peerURLs=http://10.211.55.2:2380 clientURLs=http://10.211.55.2:2379 isLeader=false

可以看到集群已经生效了
然后我们再来测试一下,在ndoe2上执行操作

etcdctl set /cqh muscle

看看node1和node3是否能保持数据一致

可以看到在node1和node3中都能能够正确的获取/cqh的值

四.监听功能watch演示

  • etcdctl watch key
    观察一个值的变化,观察到变化后,打印值并watch退出

  • etcdctl watch key -f
    永久观察值的变化,观察到变化后,打印直到Ctrl+C退出
  • etcdctl exec-watch key -- sh -c 'pwd'
    监听到值有变化,就执行指定的命令(且不退出执行的可以是shell命令)

五.API操作演示

  • 创建键值
➜  ~ curl http://10.211.55.25:2379/v2/keys/cqh -XPUT -d value="陈琼和1"
{"action":"set","node":{"key":"/cqh","value":"陈琼和","modifiedIndex":14,"createdIndex":14},"prevNode":{"key":"/cqh","value":"陈琼和","modifiedIndex":13,"createdIndex":13}}
  • 创建目录
➜  ~ curl http://10.211.55.25:2379/v2/keys/gym -XPUT -d dir=true
{"action":"set","node":{"key":"/gym","dir":true,"modifiedIndex":12,"createdIndex":12}}
  • 获取键值
➜  ~ curl http://10.211.55.25:2379/v2/keys/cqh
{"action":"get","node":{"key":"/cqh","value":"陈琼和","modifiedIndex":14,"createdIndex":14}}
  • 创建键值带ttl
➜  ~ curl http://10.211.55.25:2379/v2/keys/hero -XPUT -d value="超人" -d ttl=5
  • 创建有序键值
curl http://10.211.55.25:2379/v2/keys/fitness -XPOST -d value="bench_press"
curl http://10.211.55.25:2379/v2/keys/fitness -XPOST -d value="dead_lift"
curl http://10.211.55.25:2379/v2/keys/fitness -XPOST -d value="deep_squat"

获取刚创建的fitness

curl http://10.211.55.25:2379/v2/keys/fitness
{"action":"create","node":{"key":"/fitness/00000000000000000020","value":"bench_press","modifiedIndex":20,"createdIndex":20}}
{"action":"create","node":{"key":"/fitness/00000000000000000021","value":"dead_lift","modifiedIndex":21,"createdIndex":21}}
{"action":"create","node":{"key":"/fitness/00000000000000000022","value":"deep_squat","modifiedIndex":22,"createdIndex":22}}
{"action":"get","node":{"key":"/fitness","dir":true,"nodes":[{"key":"/fitness/00000000000000000022","value":"deep_squat","modifiedIndex":22,"createdIndex":22},{"key":"/fitness/00000000000000000020","value":"bench_press","modifiedIndex":20,"createdIndex":20},{"key":"/fitness/00000000000000000021","value":"dead_lift","modifiedIndex":21,"createdIndex":21}],"modifiedIndex":20,"createdIndex":20}}
  • 删除键
curl http://10.211.55.25:2379/v2/keys/cqh -XDELETE
  • 列出所有集群成员
curl http://10.211.55.25:2379/v2/members

返回

[
    {
        "id": "2033c1336b929ca7",
        "name": "node-3",
        "peerURLs": [
            "http://10.211.55.26:2380"
        ],
        "clientURLs": [
            "http://10.211.55.26:2379"
        ]
    },
    {
        "id": "edc51d36208cfbcf",
        "name": "node-2",
        "peerURLs": [
            "http://10.211.55.25:2380"
        ],
        "clientURLs": [
            "http://10.211.55.25:2379"
        ]
    },
    {
        "id": "f09a9dba19a725e2",
        "name": "node-1",
        "peerURLs": [
            "http://10.211.55.2:2380"
        ],
        "clientURLs": [
            "http://10.211.55.2:2379"
        ]
    }
]
  • 统计信息-查看leader
curl http://10.211.55.25:2379/v2/stats/leader

返回

{
    "leader": "2033c1336b929ca7",
    "followers": {
        "edc51d36208cfbcf": {
            "latency": {
                "current": 0.002104,
                "average": 0.00535051111111111,
                "standardDeviation": 0.0059011238840004894,
                "minimum": 0.001839,
                "maximum": 0.029456
            },
            "counts": {
                "fail": 0,
                "success": 45
            }
        },
        "f09a9dba19a725e2": {
            "latency": {
                "current": 0.004161,
                "average": 0.005481136363636365,
                "standardDeviation": 0.008282444790560192,
                "minimum": 0.001468,
                "maximum": 0.047605
            },
            "counts": {
                "fail": 1,
                "success": 44
            }
        }
    }
}
  • 节点自身信息
curl http://10.211.55.26:2379/v2/stats/self

返回

{
    "name": "node-3",
    "id": "2033c1336b929ca7",
    "state": "StateLeader",
    "startTime": "2019-03-09T15:25:54.715490011+08:00",
    "leaderInfo": {
        "leader": "2033c1336b929ca7",
        "uptime": "38m12.85630387s",
        "startTime": "2019-03-09T15:25:56.01655006+08:00"
    },
    "recvAppendRequestCnt": 0,
    "sendAppendRequestCnt": 90
}
  • 查看集群运行状态
curl http://10.211.55.26:2379/v2/stats/store

返回

{
    "getsSuccess": 3,
    "getsFail": 29,
    "setsSuccess": 28,
    "setsFail": 0,
    "deleteSuccess": 0,
    "deleteFail": 0,
    "updateSuccess": 0,
    "updateFail": 0,
    "createSuccess": 3,
    "createFail": 0,
    "compareAndSwapSuccess": 0,
    "compareAndSwapFail": 0,
    "compareAndDeleteSuccess": 0,
    "compareAndDeleteFail": 0,
    "expireCount": 0,
    "watchers": 0
}

猜你喜欢

转载自www.cnblogs.com/chenqionghe/p/10501661.html