
ETCD安装
直接安装
以MAC系统为例,讲述2种按照方法,第一种很简单,是Mac自带的:
#用brew安装非常方便,没安装的自行安装Homebrew,通过下面命令可以查看安装包
brew search etcd
#安装
brew install etcd
#查看版本
etcd --version
#启动,如果没有--enable-v2=true,就不用使用v2的接口
etcd --enable-v2=true
复制代码
不过这种方式可能会安装失败,我这把失败时提示日志目前没有权限,根据提示执行相关命令即可,我这边的提示如下:
sudo chown -R $(whoami) /usr/local/var/log
复制代码
源码安装
我个人更推荐下面这种安装方式:
ETCD_VER=v3.4.14
# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}
rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-darwin-amd64.zip -o /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
unzip /tmp/etcd-${ETCD_VER}-darwin-amd64.zip -d /tmp && rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
mv /tmp/etcd-${ETCD_VER}-darwin-amd64/* /tmp/etcd-download-test && rm -rf mv /tmp/etcd-${ETCD_VER}-darwin-amd64
#输出etcd版本
/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
#这里是把etcd和etcdctl copy到bin目录下面
cp /tmp/etcd-download-test/etcd /usr/local/bin
cp /tmp/etcd-download-test/etcdctl /usr/local/bin
然后执行:
#安装etcd
sh etcd_install.sh
#查看版本
etcd --version
#启动,如果没有--enable-v2=true,就不用使用v2的接口
etcd --enable-v2=true
复制代码
集群部署
部署流程
下面我们可以部署一个etcd集群,我把代码还是写到文件中,第一个脚本为不支持在 Docs 外粘贴 block,内容如下(启动etcd需要很多参数,这些参数我都已经注释说明,更多参数详见:https://www.cnblogs.com/linuxws/p/11194403.html):
TOKEN=token-01
CLUSTER_STATE=new
NAME_1=etcd-01
NAME_2=etcd-02
NAME_3=etcd-03
HOST_1=127.0.0.1
HOST_2=127.0.0.1
HOST_3=127.0.0.1
PORT_API_1=2379
PORT_PEER_1=2380
PORT_API_2=2479
PORT_PEER_2=2480
PORT_API_3=2579
PORT_PEER_3=2580
CLUSTER=${NAME_1}=http://${HOST_1}:${PORT_PEER_1},${NAME_2}=http://${HOST_2}:${PORT_PEER_2},${NAME_3}=http://${HOST_3}:${PORT_PEER_3}
# For every machine
THIS_NAME=${NAME_1}
THIS_IP=${HOST_1}
THIS_PORT_API=${PORT_API_1}
THIS_PORT_PEER=${PORT_PEER_1}
# 用于杀死进程
lsof -i:2379 | awk '{print $2}' | grep -v "PID" | uniq | xargs kill -9
# --enable-v2 支持v2接口,可以省略
# --data-dir 数据存储目录,可以省略
# --name 节点名称,必须
# --initial-advertise-peer-urls 数据在集群内进行交互的url,必须
# --listen-peer-urls 集群节点之间通信监听的url,必须
# --advertise-client-urls 客户通过该地址与本member交互信息,可以省略
# --listen-client-urls 监听客户端请求的url,必须
# --initial-cluster 初始启动的集群配置,必须
# --initial-cluster-state 初始化集群状态,取值为new和existing,可以省略
# --initial-cluster-token 集群初始化token,可以省略
etcd --enable-v2=true --data-dir=data.${THIS_NAME} --name ${THIS_NAME} \
--initial-advertise-peer-urls http://${THIS_IP}:${THIS_PORT_PEER} --listen-peer-urls http://${THIS_IP}:${THIS_PORT_PEER} \
--advertise-client-urls http://${THIS_IP}:${THIS_PORT_API} --listen-client-urls http://${THIS_IP}:${THIS_PORT_API} \
--initial-cluster ${CLUSTER} \
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
复制代码
第二个脚本需要把里面的内容替换如下:
# For every machine
THIS_NAME=${NAME_2}
THIS_IP=${HOST_2}
THIS_PORT_API=${PORT_API_2}
THIS_PORT_PEER=${PORT_PEER_2}
# 用于杀死进程
lsof -i:2479 | awk '{print $2}' | grep -v "PID" | uniq | xargs kill -9
复制代码
第三个脚本需要把里面的内容替换如下:
# For every machine
THIS_NAME=${NAME_3}
THIS_IP=${HOST_3}
THIS_PORT_API=${PORT_API_3}
THIS_PORT_PEER=${PORT_PEER_3}
# 用于杀死进程
lsof -i:2579 | awk '{print $2}' | grep -v "PID" | uniq | xargs kill -9
复制代码
有了这3个脚本,分别开3个窗口,分别执行,服务启动截图如下:

当这3个脚本全部启动后,集群部署完毕,我们检查一下3个节点的健康状态:
curl http://127.0.0.1:2379/health
curl http://127.0.0.1:2479/health
curl http://127.0.0.1:2579/health
复制代码
如果都返回{“health”:”true”},表示部署成功,下面我们查看一下部署的节点信息:
curl http://127.0.0.1:2379/v2/members
复制代码
返回结果如下,其中peerURLs是节点互相通信访问的url,clientURLs是对外访问的url:
{
"members":[
{
"id":"264ae6bc59e99892",
"name":"etcd-01",
"peerURLs":[
"http://127.0.0.1:2380"
],
"clientURLs":[
"http://127.0.0.1:2379"
]
},
{
"id":"dbafe5ad6b652eda",
"name":"etcd-02",
"peerURLs":[
"http://127.0.0.1:2480"
],
"clientURLs":[
"http://127.0.0.1:2479"
]
},
{
"id":"f570ae41f524bdcb",
"name":"etcd-03",
"peerURLs":[
"http://127.0.0.1:2580"
],
"clientURLs":[
"http://127.0.0.1:2579"
]
}
]
}
复制代码
遇到问题
问题1:服务启动后,不能使用v2接口,比如执行“curl http://127.0.0.1:2379/v2/members”,提示“404 page not found”
问题原因:因为V3.4版本默认是V3接口,不支持V2
解决方案:需要在启动etcd时,加上“–enable-v2=true”,强制使用V2接口
问题2:服务启动失败,提示“conflicting environment variable “ETCD_ENABLE_V2” is shadowed by corresponding command-line flag (either unset environment variable or disable flag)”
问题原因:因为启动etcd时,参数“–enable-v2=true”导致,因为V3.4版本会读取该配置,所以提示配置重复。
解决方案:不能删除该参数,否则会引入其它问题,我是关闭所有窗口,然后重新启动etcd即可。
问题3:启动某个节点时,提示member已经存在
问题原因:因为之前启动过该节点,该member已经存在,不能初始化,只能加入已经存在的member
解决方案:需要将启动脚本中的“CLUSTER_STATE=new”改为“CLUSTER_STATE=existing”
常规操作
集群管理
我们在部署集群时,用到一些方法,这里我简单汇总一下:
// 版本检查,输出{"etcdserver":"3.4.14","etcdcluster":"3.4.0"}
curl http://127.0.0.1:2379/version
// 健康检查,输出{"health":"true"}
curl http://127.0.0.1:2379/health
// 查看集群节点
curl http://127.0.0.1:2379/v2/members
复制代码
键值操作
设置键的值:
curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="hello world"
复制代码
返回结果:
{
"action":"set",
"node":{
"key":"/message",
"value":"hello world",
"modifiedIndex":43,
"createdIndex":43
}
}
复制代码
读取键的值:
curl http://127.0.0.1:2379/v2/keys/message
复制代码
返回结果:
{
"action":"get",
"node":{
"key":"/message",
"value":"hello world",
"modifiedIndex":43,
"createdIndex":43
}
}
复制代码
给键设置10s的超时时间:
curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="hello world" -d ttl=10
复制代码
返回结果(prevNode是旧值):
{
"action":"set",
"node":{
"key":"/message",
"value":"hello world",
"expiration":"2021-01-21T00:16:13.777434Z",
"ttl":10,
"modifiedIndex":44,
"createdIndex":44
},
"prevNode":{
"key":"/message",
"value":"hello world",
"modifiedIndex":43,
"createdIndex":43
}
}
复制代码
获取该键值,超时后,就提示“key not found”:

watch通知
可以对key设置监听,当key的值有变化时,会通知监听的客户端,我们先在客户端A监听key:
curl http://127.0.0.1:2379/v2/keys/message?wait=true
复制代码
然后在客户端B,修改该key的值:
curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="hello world2"
复制代码
客户端A返回并退出,返回结果:
{
"action":"set",
"node":{
"key":"/message",
"value":"hello world2",
"modifiedIndex":48,
"createdIndex":48
}
}
复制代码
如果希望客户端A能持续监听,不退出,可以通过增加stream=true参数:
curl "http://127.0.0.1:2379/v2/keys/message?wait=true&stream=true"
复制代码
当在客户端B执行如下时:
curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="hello world" -d ttl=10
复制代码
客户端A会实时监听返回,比如当给key设置值,或者当key过期时,客户端A都会监听到:
