1. etcd概念

1.1. etcd介绍

etcd的名字来源于/etcdistibuted,即Unix下配置文件目录和分布式两个关键词。Etcd是一个分布式、可靠的k-v分布式数据库,同时还能提供配置共享、服务发现等功能,常常用在go语言的项目中。etcd主要有以下几个方面的特点:

  • 部署简单:只有一个二进制文件,可以开箱即用
  • 使用简单:etcd有着丰富的client SDK
  • 安全性高:支持SSL证书认证,数据加密,节点之间相互验证身份
  • 强一致性:通过raft算法实现数据的强一致性,少于二分之一节点宕机仍然能提供服务,通常部署3个或者5个节点
  • 数据落地:etcd的数据会通过wal格式的数据持久化到磁盘,并且支持snapshot快照

etcd的架构主要由以下四个部分:

  • HTTP Server:请求的入口,用来处理各种API请求
  • Store:用于处理etcd支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事件处理与执行等等,是etcd对用户提供的大多数API功能的具体实现
  • Raft状态机:实现多节点的etcd集群中数据一致性和节点选主
  • WAL:Write Ahead Log(预写式日志),是etcd的数据存储方式。除了在内存中存有所有数据的状态以及节点的索引以外,etcd就通过WAL进行持久化存储。WAL中,所有的数据提交前都会事先记录日志。Snapshot是为了防止数据过多而进行的状态快照;Entry表示存储的具体日志内容。

    1.2. Raft

    Raft 是etcd保障分布式节点中数据一致性的关键,该算法本身有一定的复杂度。网上有很多etcd的raft算法的博客,详细介绍了节点直接如何选主、如何同步数据、如何补偿数据的。

  • ETCD背后的Raft一致性算法原理

  • 分布式一致性算法 Raft 和 Etcd 原理解析
  • 一文搞懂Raft算法

2. etcd部署

2.1. 准备工作

2.1.1. 硬件需求

这里简单介绍下ectd对硬件的要求,详情需要参考官方文档

  1. CPU

etcd对CPU的消耗不是很大,通常需要2-4个核心即可。在高负载集群下,如同时给上千个客户端提供服务,或者每秒有上万个请求的场景,需要8-16核心。一般规模,可以先使用2-4核心的CPU,后续如果CPU使用率较高,可以逐个节点升级配置。

  1. Memory

etcd对内存的需求不是很大,但是也会积极的缓存k-v数据到内存,并用剩余的内存跟踪watcher。一般而言,8G内存也足够了。

  1. Disk

磁盘的写入速度是影响etcd性能的关键,etcd的raft共识协议依赖于将元数据写入到日志中,每个etcd节点都要将每个请求写入磁盘。并且,etcd还需要将增量的checkpoint写入磁盘,用来截断日志。如果写入时间过长,可能因为超过心跳时间造成集群重新选举,从而破坏集群的稳定性。在检查磁盘性能的时候,可以使用 fio 进行测试,具体可以参考IBM的这篇文章
磁盘的性能要从两个方面去评估,第一个是IOPS能力:一般而言,需要50顺序IOPS的速度(比如7200RPM的机械盘),高负载集群需要500顺序IOPS速度(通常是固态)。第二个是磁盘带宽,这个决定了新节点或者失败节点同步数据的时间,典型的10MB/s的磁盘通常在15秒内能恢复100MB数据,100MB/s可以在15秒内恢复1GB的数据。
etcd的数据会相互同步,不要担心节点坏盘问题,因此没必要做RAID5这种RAID10,如果需要做RAID提升磁盘性能,请考虑使用RAID0。

  1. Network

etcd集群需要快速网络,并且保障网络的稳定性,通常1GbE的内部网络可以满足大部分场景的需求,通常建议将etcd节点部署到一个网络域内,减少跨网络的延迟。

etcd官方文档还提供了,不同规模下的kubernetes的对etcd集群配置的要求,需要注意的是,这些集群中etcd是单独部署的,并不是和master节点共用。

  1. 小集群

请求客户端少于100个,每秒请求少于200个,并且存储数据少于100MB。如50个node的kuberentes集群:

Provider Type vCPUs Memory (GB) Max concurrent IOPS Disk bandwidth (MB/s)
AWS m4.large 2 8 3600 56.25
GCE n1-standard-2 + 50GB PD SSD 2 7.5 1500 25
  1. 中等规模集群

请求客户端少于500个,每秒请求少于1000个,并且存储数据少于500MB。如250个node的kuberentes集群:

Provider Type vCPUs Memory (GB) Max concurrent IOPS Disk bandwidth (MB/s)
AWS m4.xlarge 4 16 6000 93.75
GCE n1-standard-4 + 150GB PD SSD 4 15 4500 75
  1. 大规模集群

请求客户端少于1500个,每秒请求少于10000个,并且存储数据少于1000MB。如1000个node的kuberentes集群

Provider Type vCPUs Memory (GB) Max concurrent IOPS Disk bandwidth (MB/s)
AWS m4.2xlarge 8 32 8000 125
GCE n1-standard-8 + 250GB PD SSD 8 30 7500 125
  1. 超大规模集群

请求客户端超过1500个,每秒请求超过10000个,并且存储数据大于1000MB。如3000个node的kuberentes集群

Provider Type vCPUs Memory (GB) Max concurrent IOPS Disk bandwidth (MB/s)
AWS m4.4xlarge 16 64 16,000 250
GCE n1-standard-16 + 500GB PD SSD 16 60 15,000 250

2.1.2. 机器规划

规划小规模测试集群,集群中节均关闭swap分区,安装chronyd时间同步服务。
磁盘写入性能由 fio 测试得出,具体可以参考IBM的这篇文章

节点 IP 系统 CPU/Memory Disk write IOPS avg write bandwidth avg(MB/s)
etcd-1 10.4.7.121 ubuntu 18.04.5 2C 4G 20G SSD min= 2706, max= 2758, avg=2727.14 min= 6077, max= 6194,avg=6124.86
etcd-2 10.4.7.122 ubuntu 18.04.5 2C 4G 20G SSD
etcd-3 10.4.7.123 ubuntu 18.04.5 2C 4G 20G SSD

2.2. etcd集群部署

ectd 版本下载页面:https://github.com/etcd-io/etcd/releases,这里以 3.5.1 版本为例,进行安装和学习。

  1. [root@duduniao etcd]# wget https://github.com/etcd-io/etcd/releases/download/v3.5.1/etcd-v3.5.1-linux-amd64.tar.gz
  2. [root@duduniao etcd]# tar -xf etcd-v3.5.1-linux-amd64.tar.gz
  3. [root@duduniao etcd]# ls etcd-v3.5.1-linux-amd64/etcd* -l
  4. -rwxr-xr-x 1 114762 114762 23568384 Oct 15 22:22 etcd-v3.5.1-linux-amd64/etcd
  5. -rwxr-xr-x 1 114762 114762 17981440 Oct 15 22:22 etcd-v3.5.1-linux-amd64/etcdctl
  6. -rwxr-xr-x 1 114762 114762 16056320 Oct 15 22:22 etcd-v3.5.1-linux-amd64/etcdutl
  7. # 下发etcd软件到各个服务器上
  8. [root@duduniao etcd]# scan_host.sh push -h 10.4.7.121 10.4.7.122 10.4.7.123 etcd-v3.5.1-linux-amd64/etcd* /usr/local/bin/
  9. 10.4.7.123 etcd-v3.5.1-linux-amd64/etcd etcd-v3.5.1-linux-amd64/etcdctl etcd-v3.5.1-linux-amd64/etcdutl --> /usr/local/bin/ Y
  10. 10.4.7.121 etcd-v3.5.1-linux-amd64/etcd etcd-v3.5.1-linux-amd64/etcdctl etcd-v3.5.1-linux-amd64/etcdutl --> /usr/local/bin/ Y
  11. 10.4.7.122 etcd-v3.5.1-linux-amd64/etcd etcd-v3.5.1-linux-amd64/etcdctl etcd-v3.5.1-linux-amd64/etcdutl --> /usr/local/bin/ Y
  12. # 配置启动的etcd.service文件
  13. [root@duduniao etcd]# scp etcd-1.service 10.4.7.121:/lib/systemd/system/etcd.service
  14. [root@duduniao etcd]# scp etcd-2.service 10.4.7.122:/lib/systemd/system/etcd.service
  15. [root@duduniao etcd]# scp etcd-3.service 10.4.7.123:/lib/systemd/system/etcd.service
  16. # 启动etcd
  17. [root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "mkdir /data/etcd ; systemctl daemon-reload"
  18. [root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "systemctl start etcd && systemctl enable etcd"
  19. [root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "systemctl is-enabled etcd && systemctl is-active etcd"
  20. # 检查集群状态
  21. [root@duduniao etcd]# ./etcd-v3.5.1-linux-amd64/etcdctl --endpoints=10.4.7.121:2379 member list --write-out=table
  22. +------------------+---------+--------+------------------------+------------------------+------------+
  23. | ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
  24. +------------------+---------+--------+------------------------+------------------------+------------+
  25. | 4c45db44e1021917 | started | etcd-1 | http://10.4.7.121:2380 | http://10.4.7.121:2379 | false |
  26. | 721eef2714f1477a | started | etcd-2 | http://10.4.7.122:2380 | http://10.4.7.122:2379 | false |
  27. | f6d5f5c8eef4f092 | started | etcd-3 | http://10.4.7.123:2380 | http://10.4.7.123:2379 | false |
  28. +------------------+---------+--------+------------------------+------------------------+------------+
  29. # 测试读写
  30. [root@duduniao etcd]# ./etcd-v3.5.1-linux-amd64/etcdctl --endpoints=10.4.7.121:2379 put k1 test-value-1
  31. [root@duduniao etcd]# ./etcd-v3.5.1-linux-amd64/etcdctl --endpoints=10.4.7.123:2379 get k1
  32. k1
  33. test-value-1
# etcd-1.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/data/etcd
ExecStart=/usr/local/bin/etcd \
  --name etcd-1 \
  --initial-advertise-peer-urls http://10.4.7.121:2380 \
  --listen-peer-urls http://10.4.7.121:2380 \
  --listen-client-urls http://10.4.7.121:2379,http://127.0.0.1:2379 \
  --advertise-client-urls http://10.4.7.121:2379 \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster etcd-1=http://10.4.7.121:2380,etcd-2=http://10.4.7.122:2380,etcd-3=http://10.4.7.123:2380 \
  --initial-cluster-state new \
  --data-dir /data/etcd \
  --snapshot-count 50000 \
  --auto-compaction-retention 1 \
  --auto-compaction-mode periodic \
  --max-request-bytes 10485760 \
  --quota-backend-bytes 8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

# etcd-2.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/data/etcd
ExecStart=/usr/local/bin/etcd \
  --name etcd-2 \
  --initial-advertise-peer-urls http://10.4.7.122:2380 \
  --listen-peer-urls http://10.4.7.122:2380 \
  --listen-client-urls http://10.4.7.122:2379,http://127.0.0.1:2379 \
  --advertise-client-urls http://10.4.7.122:2379 \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster etcd-1=http://10.4.7.121:2380,etcd-2=http://10.4.7.122:2380,etcd-3=http://10.4.7.123:2380 \
  --initial-cluster-state new \
  --data-dir /data/etcd \
  --snapshot-count 50000 \
  --auto-compaction-retention 1 \
  --auto-compaction-mode periodic \
  --max-request-bytes 10485760 \
  --quota-backend-bytes 8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

# etcd-3.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/data/etcd
ExecStart=/usr/local/bin/etcd \
  --name etcd-3 \
  --initial-advertise-peer-urls http://10.4.7.123:2380 \
  --listen-peer-urls http://10.4.7.123:2380 \
  --listen-client-urls http://10.4.7.123:2379,http://127.0.0.1:2379 \
  --advertise-client-urls http://10.4.7.123:2379 \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster etcd-1=http://10.4.7.121:2380,etcd-2=http://10.4.7.122:2380,etcd-3=http://10.4.7.123:2380 \
  --initial-cluster-state new \
  --data-dir /data/etcd \
  --snapshot-count 50000 \
  --auto-compaction-retention 1 \
  --auto-compaction-mode periodic \
  --max-request-bytes 10485760 \
  --quota-backend-bytes 8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

2.3. TLS加密通信的etcd集群部署

etcd有两个对外暴露的端口:2379 和 2380。其中2379是的用来接收客户端请求的,2380用来和集群内部其它节点通信和数据同步的。这两种通信都可以进行TLS加密,并且可以使用CA证书进行验证对方是否合法。etcd默认是没用启动RBAC认证的,所有连接上的客户端都是可以操作所有的key。在k8s集群中,ectd服务端是通过客户端证书验证是否合法的,只有客户端拿etcd认可的CA签发的证书才能通过认证。核心参数如下:

# client和server直接通信
--trusted-ca-file=<path>            受信任的CA证书
--cert-file=<path>                        etcd 服务端证书
--key-file=<path>                            etcd 服务端证书私钥
--client-cert-auth                        指定该参数后,服务端要求客户端证书也是trusted-ca-file签发的证书

# etcd节点之间通信(peer)
--peer-trusted-ca-file=<path>    受信任的CA证书
--peer-cert-file=<path>                etcd 服务端证书
--peer-key-file=<path>                etcd 服务端证书私钥
--peer-client-cert-auth                指定该参数后,要求对端证书也是peer-trusted-ca-file签发的证书

2.3.1. 签发证书

通常我们会同时加密 client-server 以及 peer 节点证书,为了简化,client-server 和 peer 的ca证书通常是相同的,甚至peer证书和server证书都可以相同。

# 下载证书签发工具
[root@duduniao etcd]# wget -O /usr/local/bin/cfssl  https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
[root@duduniao etcd]# wget -O /usr/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
[root@duduniao etcd]# chmod +x /usr/local/bin/cfssljson  /usr/local/bin/cfssl
# 签发ca证书,这里有个很大的坑:
#     etcd节点会不断以客户端身份访问自身的2379端口,并且使用的是server证书,因此ca的server配置必须添加line:19 "client auth"。否则会报以下错误:
#     WARNING: 2021/10/17 09:55:56 [core] grpc: addrConn.createTransport failed to connect to {127.0.0.1:2379 127.0.0.1:2379 <nil> 0 <nil>}. 
#     Err: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
[root@duduniao etcd]# mkdir ssl/ && cd ssl
[root@duduniao ssl]# cat ca-config.json
{
    "signing": {
        "default": {
            "expiry": "43800h"
        },
        "profiles": {
            "server": {
                "expiry": "43800h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            },
            "client": {
                "expiry": "43800h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "client auth"
                ]
            },
            "peer": {
                "expiry": "43800h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            }
        }
    }
}
[root@duduniao ssl]# cat ca-csr.json
{
    "CN": "local-etcd-ca",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Shanghai",
            "O": "duduniao",
            "ST": "Shanghai",
            "OU": "devops"
        }
    ]
}
[root@duduniao ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
[root@duduniao ssl]# ll
total 20
-rw-r--r-- 1 root root  832 2021-10-17 15:23:33 ca-config.json
-rw-r--r-- 1 root root  274 2021-10-17 15:26:46 ca-csr.json
-rw------- 1 root root 1679 2021-10-17 15:27:08 ca-key.pem
-rw-r--r-- 1 root root 1013 2021-10-17 15:27:08 ca.csr
-rw-r--r-- 1 root root 1387 2021-10-17 15:27:08 ca.pem
# 签发server证书, client验证server使用,同时server自检也需要
[root@duduniao ssl]# cat server.json
{
    "CN": "local-etcd.duduniao.com",
    "hosts": [
        "10.4.7.121",
        "10.4.7.122",
        "10.4.7.123",
        "127.0.0.1",
        "etcd-1",
        "etcd-2",
        "etcd-3",
        "localhost"
    ],
    "key": {
        "algo": "ecdsa",
        "size": 256
    },
    "names": [
        {
            "C": "CN",
            "L": "Shanghai",
            "ST": "Shanghai"
        }
    ]
}
[root@duduniao ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server
[root@duduniao ssl]# ll server*
-rw------- 1 root root  227 2021-10-17 15:32:56 server-key.pem
-rw-r--r-- 1 root root  558 2021-10-17 15:32:56 server.csr
-rw-r--r-- 1 root root  391 2021-10-17 15:32:24 server.json
-rw-r--r-- 1 root root 1184 2021-10-17 15:32:56 server.pem
# 签发peer证书,推荐每个节点一个, 以etcd-1为例,其它节点修改IP、域名和主机名
[root@duduniao ssl]# cat etcd-1.json
{
    "CN": "local-etcd-1.duduniao.com",
    "hosts": [
        "10.4.7.121",
        "etcd-1"
    ],
    "key": {
        "algo": "ecdsa",
        "size": 256
    },
    "names": [
        {
            "C": "CN",
            "L": "Shanghai",
            "ST": "Shanghai"
        }
    ]
}
[root@duduniao ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer etcd-1.json | cfssljson -bare etcd-1
[root@duduniao ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer etcd-2.json | cfssljson -bare etcd-2
[root@duduniao ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer etcd-3.json | cfssljson -bare etcd-3

2.3.2. 部署etcd集群

# 停止掉非加密的etcd集群,清理etcd数据
[root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "systemctl stop etcd" 
[root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "rm -fr /data/etcd"
# 下发证书
[root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "mkdir -p /data/etcd/data /data/etcd/ssl"
[root@duduniao etcd]# scan_host.sh push -h 10.4.7.121 10.4.7.122 10.4.7.123 ssl/ca.pem ssl/server.pem ssl/server-key.pem  /data/etcd/ssl/
[root@duduniao etcd]# scp ssl/etcd-1-key.pem ssl/etcd-1.pem 10.4.7.121:/data/etcd/ssl/
[root@duduniao etcd]# scp ssl/etcd-2-key.pem ssl/etcd-2.pem 10.4.7.122:/data/etcd/ssl/
[root@duduniao etcd]# scp ssl/etcd-3-key.pem ssl/etcd-3.pem 10.4.7.123:/data/etcd/ssl/
[root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "ls -l /data/etcd/ssl"
10.4.7.122
total 20
-rw-r--r-- 1 root root 1387 Oct 17 07:53 ca.pem
-rw------- 1 root root  227 Oct 17 07:54 etcd-2-key.pem
-rw-r--r-- 1 root root 1147 Oct 17 07:54 etcd-2.pem
-rw------- 1 root root  227 Oct 17 07:53 server-key.pem
-rw-r--r-- 1 root root 1184 Oct 17 07:53 server.pem
10.4.7.121
total 20
-rw-r--r-- 1 root root 1387 Oct 17 07:53 ca.pem
-rw------- 1 root root  227 Oct 17 07:54 etcd-1-key.pem
-rw-r--r-- 1 root root 1147 Oct 17 07:54 etcd-1.pem
-rw------- 1 root root  227 Oct 17 07:53 server-key.pem
-rw-r--r-- 1 root root 1184 Oct 17 07:53 server.pem
10.4.7.123
total 20
-rw-r--r-- 1 root root 1387 Oct 17 07:53 ca.pem
-rw------- 1 root root  227 Oct 17 07:55 etcd-3-key.pem
-rw-r--r-- 1 root root 1147 Oct 17 07:55 etcd-3.pem
-rw------- 1 root root  227 Oct 17 07:53 server-key.pem
-rw-r--r-- 1 root root 1184 Oct 17 07:53 server.pem
# 修改servcie文件
# etcd-1.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/data/etcd
ExecStart=/usr/local/bin/etcd \
  --name etcd-1 \
  --initial-advertise-peer-urls https://10.4.7.121:2380 \
  --listen-peer-urls https://10.4.7.121:2380 \
  --listen-client-urls https://10.4.7.121:2379,https://127.0.0.1:2379 \
  --advertise-client-urls https://10.4.7.121:2379 \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster etcd-1=https://10.4.7.121:2380,etcd-2=https://10.4.7.122:2380,etcd-3=https://10.4.7.123:2380 \
  --initial-cluster-state new \
  --client-cert-auth \
  --cert-file ssl/server.pem \
  --key-file ssl/server-key.pem \
  --trusted-ca-file ssl/ca.pem \
  --peer-client-cert-auth \
  --peer-trusted-ca-file ssl/ca.pem \
  --peer-cert-file ssl/etcd-1.pem \
  --peer-key-file ssl/etcd-1-key.pem \
  --data-dir data \
  --snapshot-count 50000 \
  --auto-compaction-retention 1 \
  --auto-compaction-mode periodic \
  --max-request-bytes 10485760 \
  --quota-backend-bytes 8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

# etcd-2.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/data/etcd
ExecStart=/usr/local/bin/etcd \
  --name etcd-2 \
  --initial-advertise-peer-urls https://10.4.7.122:2380 \
  --listen-peer-urls https://10.4.7.122:2380 \
  --listen-client-urls https://10.4.7.122:2379,https://127.0.0.1:2379 \
  --advertise-client-urls https://10.4.7.122:2379 \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster etcd-1=https://10.4.7.121:2380,etcd-2=https://10.4.7.122:2380,etcd-3=https://10.4.7.123:2380 \
  --initial-cluster-state new \
  --client-cert-auth \
  --cert-file ssl/server.pem \
  --key-file ssl/server-key.pem \
  --trusted-ca-file ssl/ca.pem \
  --peer-client-cert-auth \
  --peer-trusted-ca-file ssl/ca.pem \
  --peer-cert-file ssl/etcd-2.pem \
  --peer-key-file ssl/etcd-2-key.pem \
  --data-dir data \
  --snapshot-count 50000 \
  --auto-compaction-retention 1 \
  --auto-compaction-mode periodic \
  --max-request-bytes 10485760 \
  --quota-backend-bytes 8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

# etcd-3.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/data/etcd
ExecStart=/usr/local/bin/etcd \
  --name etcd-3 \
  --initial-advertise-peer-urls https://10.4.7.123:2380 \
  --listen-peer-urls https://10.4.7.123:2380 \
  --listen-client-urls https://10.4.7.123:2379,https://127.0.0.1:2379 \
  --advertise-client-urls https://10.4.7.123:2379 \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster etcd-1=https://10.4.7.121:2380,etcd-2=https://10.4.7.122:2380,etcd-3=https://10.4.7.123:2380 \
  --initial-cluster-state new \
  --client-cert-auth \
  --cert-file ssl/server.pem \
  --key-file ssl/server-key.pem \
  --trusted-ca-file ssl/ca.pem \
  --peer-client-cert-auth \
  --peer-trusted-ca-file ssl/ca.pem \
  --peer-cert-file ssl/etcd-3.pem \
  --peer-key-file ssl/etcd-3-key.pem \
  --data-dir data \
  --snapshot-count 50000 \
  --auto-compaction-retention 1 \
  --auto-compaction-mode periodic \
  --max-request-bytes 10485760 \
  --quota-backend-bytes 8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
# 启动集群
[root@duduniao etcd]# scp etcd-1.service 10.4.7.121:/lib/systemd/system/etcd.service
[root@duduniao etcd]# scp etcd-2.service 10.4.7.122:/lib/systemd/system/etcd.service
[root@duduniao etcd]# scp etcd-3.service 10.4.7.123:/lib/systemd/system/etcd.service
[root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "systemctl daemon-reload"
10.4.7.122
10.4.7.123
10.4.7.121
[root@duduniao etcd]# scan_host.sh cmd -h 10.4.7.121 10.4.7.122 10.4.7.123 "systemctl restart etcd && systemctl enable etcd"

2.3.3. 客户端验证

# 不加证书
root@ubuntu-1804-122:~# etcdctl --endpoints=10.4.7.121:2379 member list --write-out=table
{"level":"warn","ts":"2021-10-17T10:26:16.722Z","logger":"etcd-client","caller":"v3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc000318380/10.4.7.121:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection closed"}
Error: context deadline exceeded

# 加上证书
root@ubuntu-1804-122:~# cd /data/etcd/ssl/ && etcdctl --cacert ca.pem --cert server.pem --key server-key.pem --endpoints https://10.4.7.121:2379 member list
4fe2b98ed7b794f7, started, etcd-3, https://10.4.7.123:2380, https://10.4.7.123:2379, false
bbd6739258f69625, started, etcd-1, https://10.4.7.121:2380, https://10.4.7.121:2379, false
c5542f3740ec56cd, started, etcd-2, https://10.4.7.122:2380, https://10.4.7.122:2379, false

2.4. etcd命令行

2.4.1. etcd

ectd 启动参数非常多,核心的启动参数有以下部分,其它请参考官方文档

  • member flgas ``` -name 节点名称,用于组建集群,默认 default -data-dir 数据存储目录,默认工作目录下 ${name}.etcd -wal-dir wal日志目录,默认为data-dir -snapshot-count 触发snapshot的事务提交次数,默认值 100000 -listen-peer-urls 集群节点中间对等网络监听URL,可以是http也可以是https, 0.0.0.0表示所有地址。默认 http://localhost:2380 -listen-peer-urls 用于暴露给客户端的URL地址,可以是http也可以是https, 0.0.0.0表示所有地址。默认 http://localhost:2379

–max-request-bytes 客户端最大请求的字节数,默认1572864 -quota-backend-bytes后端配额大小,默认为2G.最大为8G,超过会导致数据无法写入


- cluster flags

–initial-cluster 引导并初始化一个新集群。仅在启动新的集群成员时生效,后续运行中会忽略该参数 –initial-advertise-peer-urls 对外发布peer节点通信地址。仅在启动新的集群成员时生效,后续运行中会忽略该参数 -initial-cluster-state 集群状态。new:表示所有节点都是第一次启动并组建集群;existing表示加入一个已存在的集群。仅在启动新的集群成员时生效,后续运行中会忽略该参数 -initial-cluster-token 集群的token,所有节点启动时需要指定。默认为 etcd-cluster。仅在启动新的集群成员时生效,后续运行中会忽略该参数 -advertise-client-urls 发布给其它成员,告知他们当前节点暴露给客户端的地址。默认为 http://localhost:2379


- secirity flags

-trusted-ca-file # 服务端信任的CA证书,用来验证客户端是否合法 -cert-file # 服务端证书,由信任的CA签发,加密与客户端的通信,并且被客户端验证 -key-file # 服务端证书私钥 -client-cert-auth # 启用该参数表示服务端验证客户端证书是否为受信任的CA签发

–peer-trusted-ca-file # peer节点通信信任的CA证书,用来验证其它节点是否合法 -peer-cert-file # peer节点证书,由信任的CA签发,加密与客户端的通信,并且被其它节点验证 -peer-key-file # peer节点证书私钥 -peer-client-cert-auth # 启用该参数表示验证对端证书是否为受信任的CA签发


- logging flags

-log-level 指定日志级别,默认info.可选: debug, info, warn, error, panic, fatal

<a name="XNbir"></a>
### 2.4.2. etcdctl
<a name="OZIuN"></a>
#### 2.4.2.1. 常用参数

—endpoints 指定服务端GRPC接口,默认 127.0.0.1:2379

—cacert 指定ca证书,用来验证服务端是否合法 —cert 指定客户端证书 —key 指定客户端证书的私钥

对于需要通过证书访问的场景,可以配置命令的别名,以下的案例均使用别名:

alias etc=’etcdctl —cacert ssl/ca.pem —cert ssl/client.pem —key ssl/client-key.pem —endpoints https://10.4.7.121:2379

<a name="t4uZC"></a>
#### 2.4.2.2. 常用指令
etcdctl 是etcd的客户端工具,通常用来查询集群和节点状态,偶尔用来查询指定key的值。

1. 指定API版本

etcd的API有v2和v3,etcdctl 命令在3.4之前默认为v2,之后为v3。v2和v3版本的API数据不兼容,在查询的时候需要通过环境变量指定版本:

export ETCDCTL_API=3 # 指定v3版本 export ETCDCTL_API=2 # 指定v2版本


2. 写入key

[root@duduniao etcd]# etc put key-1 value-1 [root@duduniao etcd]# etc put key-2 value-2 [root@duduniao etcd]# etc put key-3 value-3


3. 查询key

精确查询

[root@duduniao etcd]# etc get key-1

根据前缀查询

[root@duduniao etcd]# etc get —prefix key

只显示value

[root@duduniao etcd]# etc get —prefix key —print-value-only

现在查询结果的数量

[root@duduniao etcd]# etc get —prefix key —limit 2


4. watch key

[root@duduniao etcd]# etc watch key-1


5. 删除key

[root@duduniao etcd]# etc del key-watch


6. 查看集群状态

[root@duduniao etcd]# etc member list —write-out=table +—————————+————-+————+————————————-+————————————-+——————+ | ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER | +—————————+————-+————+————————————-+————————————-+——————+ | 4fe2b98ed7b794f7 | started | etcd-3 | https://10.4.7.123:2380 | https://10.4.7.123:2379 | false | | bbd6739258f69625 | started | etcd-1 | https://10.4.7.121:2380 | https://10.4.7.121:2379 | false | | c5542f3740ec56cd | started | etcd-2 | https://10.4.7.122:2380 | https://10.4.7.122:2379 | false | +—————————+————-+————+————————————-+————————————-+——————+


7. 查看节点状态

[root@duduniao etcd]# etc endpoint status —write-out=table +————————————-+—————————+————-+————-+—————-+——————+—————-+——————+——————————+————+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +————————————-+—————————+————-+————-+—————-+——————+—————-+——————+——————————+————+ | https://10.4.7.121:2379 | bbd6739258f69625 | 3.5.1 | 20 kB | true | false | 2 | 23 | 23 | | +————————————-+—————————+————-+————-+—————-+——————+—————-+——————+——————————+————+ [root@duduniao etcd]# etc endpoint health —write-out=table +————————————-+————+—————+———-+ | ENDPOINT | HEALTH | TOOK | ERROR | +————————————-+————+—————+———-+ | https://10.4.7.121:2379 | true | 6.6739ms | | +————————————-+————+—————+———-+ ```