Etcd 单节点部署

发布时间: 更新时间: 总字数:3234 阅读时间:7m 作者: IP上海 分享 网址

etcd 基于 Go 语言实现,因此,用户可以从github下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 Docker 镜像文件来体验。

介绍

  • etcd 有 v2.x 和 v3.x 两大版本,且两个版本接口不一样,存储不同,数据相互隔离

二进制文件方式

参考

安装

编译好的二进制文件都在 github.com/coreos/etcd/releases 页面,用户可以选择需要的版本,或通过下载工具下载。

例如,使用 curl 工具下载压缩包,并解压。

$ curl -L  https://github.com/coreos/etcd/releases/download/v3.2.10/etcd-v3.2.10-linux-amd64.tar.gz -o etcd-v3.2.10-linux-amd64.tar.gz
$ tar xzvf etcd-v3.2.10-linux-amd64.tar.gz
$ cd etcd-v3.2.10-linux-amd64

解压后,可以看到文件包括

$ ls
Documentation README-etcdctl.md README.md READMEv2-etcdctl.md etcd etcdctl

其中 etcd 是服务主文件,etcdctl 是提供给用户的命令客户端,其他文件是支持文档。

下面将 etcd etcdctl 文件放到系统可执行目录(例如 /usr/local/bin/)。

$ sudo cp etcd* /usr/local/bin/

端口说明:

  • 默认 2379 端口处理客户端的请求
  • 2380 端口用于集群各成员间的通信

启动

启动 etcd 显示类似如下的信息:

# etcd
2017-12-03 11:18:34.406082 I | etcdmain: etcd Version: 3.2.10
2017-12-03 11:18:34.406226 I | etcdmain: Git SHA: GitNotFound
2017-12-03 11:18:34.406235 I | etcdmain: Go Version: go1.9.2
2017-12-03 11:18:34.406242 I | etcdmain: Go OS/Arch: darwin/amd64
2017-12-03 11:18:34.406250 I | etcdmain: setting maximum number of CPUs to 4, total number of available CPUs is 4
2017-12-03 11:18:34.406265 N | etcdmain: failed to detect default host (default host not supported on darwin_amd64)
2017-12-03 11:18:34.406279 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd
2017-12-03 11:18:34.406457 N | etcdmain: the server is already initialized as member before, starting as etcd member...
2017-12-03 11:18:34.411579 I | embed: listening for peers on http://localhost:2380
2017-12-03 11:18:34.411938 I | embed: listening for client requests on localhost:2379

此时,可以使用 etcdctl 命令进行测试,设置和获取键值 testkey: "hello world",检查 etcd 服务是否启动成功:

# export ETCDCTL_API=3
$ etcdctl member list
8e9e05c52164694d, started, default, http://localhost:2380, http://localhost:2379

$ etcdctl put testkey "hello world"
OK

$ etcdctl get testkey
testkey
hello world

说明 etcd 服务已经成功启动了。

参数说明

常用配置的参数和它们的解释:

  • –name:方便理解的节点名称,默认为 default,在集群中应该保持唯一,可以使用 hostname
  • –data-dir:服务运行数据保存的路径,默认为 ${name}.etcd
  • –snapshot-count:指定有多少事务(transaction)被提交时,触发截取快照保存到磁盘
  • –heartbeat-interval:leader 多久发送一次心跳到 followers。默认值是 100ms
  • –eletion-timeout:重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票,默认为 1000 ms
  • –listen-peer-urls:和同伴通信的地址,比如 http://ip:2380,如果有多个,使用逗号分隔。需要所有节点都能够访问,所以不要使用 localhost!
  • –listen-client-urls:对外提供服务的地址:比如 http://ip:2379,http://127.0.0.1:2379,客户端会连接到这里和 etcd 交互
  • –advertise-client-urls:对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
  • –initial-advertise-peer-urls:该节点同伴监听地址,这个值会告诉集群中其他节点
  • –initial-cluster:集群中所有节点的信息,格式为 node1=http://ip1:2380,node2=http://ip2:2380,…。注意:这里的 node1 是节点的 –name 指定的名字;后面的 ip1:2380 是 –initial-advertise-peer-urls 指定的值
  • –initial-cluster-state:新建集群的时候,这个值为 new;假如已经存在的集群,这个值为 existing
  • –initial-cluster-token:创建集群的 token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误

所有以 --init 开头的配置都是在 bootstrap 集群的时候才会用到,后续节点的重启会被忽略。

systemctl 启动

  • /etc/systemd/system/etcd.service参考
[Unit]
Description=etcd
Documentation=https://github.com/coreos/etcd

[Service]
Type=notify
Restart=always
RestartSec=5s
LimitNOFILE=40000
TimeoutStartSec=0
EnvironmentFile=-/etc/sysconfig/etcd-ssl

ExecStart=/usr/local/bin/etcd \
  --name etcd1 \
  --data-dir /data/bkee/public/etcd \
  --initial-advertise-peer-urls http://<ip1>:2380 \
  --listen-peer-urls http://<ip1>:2380 \
  --advertise-client-urls http://<ip1>:2379 \
  --listen-client-urls http://<ip1>:2379,http://127.0.0.1:2379 \
  --initial-cluster etcd0=http://<ip0>:2380 \
  --initial-cluster-state new \
  --initial-cluster-token etcd-cluster-token \
  --auto-compaction-retention 1

[Install]
WantedBy=multi-user.target

操作命令:

  • systemctl enable etcd
  • systemctl start etcd

Docker 镜像方式

  • 可以通过下面的命令启动 etcd 服务监听到 2379 和 2380 端口,参考
    • quay.io/coreos/etcd:v3.5.14
rm -rf /tmp/etcd-data.tmp && mkdir -p /tmp/etcd-data.tmp && \
  docker rmi gcr.io/etcd-development/etcd:v3.5.14 || true && \
  docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
  --name etcd-1 \
  quay.io/coreos/etcd:v3.5.14 \
  /usr/local/bin/etcd \
  --data-dir /etcd-data \
  --listen-client-urls http://0.0.0.0:2379 \
  --advertise-client-urls http://0.0.0.0:2379 \
  --listen-peer-urls http://0.0.0.0:2380 \
  --initial-advertise-peer-urls http://0.0.0.0:2380 \
  --initial-cluster etcd-1=http://0.0.0.0:2380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new \
  --log-level info \
  --logger zap \
  --log-outputs stderr

docker exec etcd-gcr-v3.5.14 /usr/local/bin/etcd --version
docker exec etcd-gcr-v3.5.14 /usr/local/bin/etcdctl version
docker exec etcd-gcr-v3.5.14 /usr/local/bin/etcdutl version
docker exec etcd-gcr-v3.5.14 /usr/local/bin/etcdctl endpoint health
docker exec etcd-gcr-v3.5.14 /usr/local/bin/etcdctl put foo bar
docker exec etcd-gcr-v3.5.14 /usr/local/bin/etcdctl get foo

打开新的终端按照上一步的方法测试 etcd 是否成功启动。

docker-compose 方式

docker-compose.yaml ...
# Copyright Broadcom, Inc. All Rights Reserved.
# SPDX-License-Identifier: APACHE-2.0

version: '2'

services:
  etcd1:
    image: bitnami/etcd:3.5.14-debian-12-r0
    # ports:
    #   - 2379
    #   - 2380
    #   - 23790
    environment:
      - ALLOW_NONE_AUTHENTICATION=yes
      - ETCD_NAME=etcd1
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd1:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd1:2379
      - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
      - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
  etcd2:
    image: bitnami/etcd:3.5.14-debian-12-r0
    environment:
      - ALLOW_NONE_AUTHENTICATION=yes
      - ETCD_NAME=etcd2
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd2:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd2:2379
      - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
      - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
  etcd3:
    image: bitnami/etcd:3.5.14-debian-12-r0
    environment:
      - ALLOW_NONE_AUTHENTICATION=yes
      - ETCD_NAME=etcd3
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd3:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd3:2379
      - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
      - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
  • 启动
$ docker-compose up -d
[+] Running 4/4
 ✔ Network etcd_default    Created                                                                               0.2s
 ✔ Container etcd-etcd2-1  Started                                                                               1.4s
 ✔ Container etcd-etcd3-1  Started                                                                               1.5s
 ✔ Container etcd-etcd1-1  Started
  • 使用
$ docker exec -it etcd-etcd1-1 bash
$ etcdctl version
etcdctl version: 3.5.14
API version: 3.5
$ etcdctl member list
ade526d28b1f92f7, started, etcd1, http://etcd1:2380, http://etcd1:2379, false
bd388e7810915853, started, etcd3, http://etcd3:2380, http://etcd3:2379, false
d282ac2ce600c1ce, started, etcd2, http://etcd2:2380, http://etcd2:2379, false

k8s 部署

参考

集群运行时重配置

  • 使用如下命令管理集群节点
    • 场景:机器升级、修改集群大小、替换故障机器、重启集群
    • 集群大多数节点正常运行时才可操作
    • 更新集群成员有两种情况
      • client URLs 用于客户端的 URL,即对外服务的 URL,通过 --advertise-client-urls 配置
      • peer URLs 用于监听 URL,即与其他节点通信
    • 如果是移除 leader 的场景,新 leader 被选举时集群将处于不活跃状态(inactive),且持续时间通常由选举超时时间和投票过程决定
    • 若添加新成员到一个节点的集群时,在新成员启动前集群无法继续工作
etcdctl member add --initial-cluster-state existing --initial-cluster http://ip1:2380,http://ip2:2380
etcdctl member remove
etcdctl member update
etcdctl member list

调优

  • 生成环境中,etcd 集群的性能受 CPU、内存、磁盘和网络的影响
    • 若客户端达到数千个,每秒请求数可能在成千上万,建议使用 8~16 个 CPU 核
    • 若具有上千个 watch 监视器或者数百万键值对的大型集群,建议内存 16GB 以上
    • etcd 对磁盘写入延迟非常敏感,通常需要 7200 RPM 转速的磁盘,对于负载较重的集群,官方建议使用 SSD、NVME 固态磁盘
      • 多个进程同时操作可能引起更高的 fsync 延迟
      • SSD/NVME 相比机械盘,写入延迟较低、能够提高 etcd 的稳定性和可靠性
      • 由于 etcd 的一致性复制已经获得了高可用,至少三个节点的集群不需要使用 RAID 的磁盘
    • etcd 集群节点网络需要保证低延迟和高带宽,不可靠的网络将导致可用性低
      • 避免多个数据中心部署 etcd 集群
      • 网络延迟可能导致 Follower 成员与 Leader 之间通信的请求处理被延迟
        • 通过提供 Leader 的网络优先级来提高 Follower 请求的响应,Linux 使用 tc 流控机制来确定对等流量的优先级
        • 通过在输出端口建立一个队列来实现流量控制
      • 若网络延迟高,etcd 集群各节点的心跳间隔和选举超时的设置需要优化

磁盘

  • etcd 对磁盘 IO 比较敏感,建议采用 SSD 或 NVME 盘,可以使用 fio 测试磁盘读写性能
    • WAL 日志受到磁盘 IO 写入速度影响
    • fdatasync 延迟也会影响 etcd 性能
fio -filename=/dev/nvme1 -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=4k -size=60G -numjobs=64 -runtime=10 -group_reporting -name=file
ionice -c2 -n0 -p $(pgrep etcd)
  • etcd 默认空间配额大小为 2G,超过 2G 将不再写入数据,修改为 8G
--quota-backend-bytes 8589934592

网络

  • 若 etcd leader 处理大量并发客户端请求,可能由于网络拥塞而延迟处理 follower 对等请求,follower 节点上可能出现如下的发送缓冲区错误的消息
dropped MsgProp to xxx since streamMsg's sending buffer is full
dropped MsgAppResp to xxx since streamMsg's sending buffer is full
  • 使用 tc 调整对等流量进行优先级
    • 集群各节点间通信的 2380 端口的命令优先级高于 2379 端口
    • 依次执行过滤器,相同优先级时,系统按照命令的先后顺序执行
tc qdisc add dev eth0 root handle 1: prio bands 3
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1

其他

  • etcd 追加所有键值对的变更到日志中
    • 每一行记录一个 key 的变更,日志规模在不断增加,为避免大量的日志,etcd 会定期生成快照
    • 默认 10000 次变更才会保存快照,如果 etcd 的内存和磁盘使用率过高,可以降低该值
      • etcd --snapshot-count=5000 ...
      • ETCD_SNAPSHOT_COUNT=5000 etcd ...
  • 时间参数
    • 心跳间隔(etcd --heartbeat-interval=100 .../ETCD_HEARBEAT_INTERVAL=100 etcd ...):被设置为节点之间网络往返时间,etcd 默认心跳间隔是 100ms
      • 推荐设置为节点之间的最大 RTT,一般可设置为平均 RTT 的 0.5~1.5 倍
      • 过长的心态间隔也会延长选举超时时间
      • RTT 一般使用 ping 命令检测
      • 若网络性能不均,5s 是一个安全的 RTT 最高值
    • 选举超时:默认是 1000ms
  • k8s 中可以将 event 写到单独的 etcd 集群中
--etcd-servers="http://etcd1:2379,http://etcd2:2379,http://etcd3:2379" \
--etcd-servers-overrides="/events#http://etcd4:2379,http://etcd5:2379,http://etcd6:2379"
  • etcd 多用于读多写少的场景,读写开销不一样
  • 尽量避免频繁更新键值对数据
  • 复用 lease,避免重复创建 lease
    • 对于相同 TTL 失效时间的键值对,绑定到相同的 lease 租约上也可以避免大量重复创建 lease

F&Q

request sent was ignored by remote peer due to cluster ID mismatch

将 etcd 数据 /var/lib/etcd/ 清理或备份,并重启服务

参考

  1. https://etcd.io/docs/v3.4/op-guide/configuration/
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数