前言

什么是 Etcd

Etcd 是一个 开源的分布式的一致性键值存储系统,由 CoreOS 开发和维护。Etcd 使用 Raft 算法实现分布式一致性,提供了 高可用高可靠高性能的数据存储服务。

Etcd 可以被用于存储和检索键值对数据,支持事务和版本控制,并具有分布式一致性和高可用性等特性。Etcd 还提供了 RESTful APIgRPC API,方便用户进行访问和使用。

在 Kubernetes 中,Etcd 被用作数据存储,用于存储集群的元数据和状态信息,包括 Pod、Service、ConfigMap、Secret 等对象的元数据和状态,以及节点的状态和配置信息等。Etcd 在 Kubernetes 中的主要作用是提供一个高可靠、高性能、分布式的数据存储系统,用于管理 Kubernetes 集群中各种对象的元数据和状态信息,从而实现集群的高效运行和管理。

除了 k8s 外,Etcd 还被广泛应用于微服务架构、配置管理、服务发现等场景,成为了一个重要的分布式系统基础组件。

为啥 K8S 要选择 Etcd

让我们看看聪明的 ChatGPT 是怎么分析这个问题的:

upload successful

我也试着问了为啥其他如 RedisMysqlMongoDBZookeeper 等为何不适合:

upload successful

upload successful

其他的就不用看了,ChatGPT 已经成为了复读机了哈,总而言之,如前面介绍中凸显的 Etcd 特点

  • 高可用
  • 分布式
  • 数据一致性
  • 高性能

最终它成为了 K8S 的首选存储系统!

当前以集群构建为主,后续再考虑出一篇文章单独介绍 Etcd的架构和原理!

环境准备

当前的环境准备均以博主本身的实际配置出发,如果使用的系统版本和环境有区别,可能搭建流程会有不一样,但是原理差不多,碰到问题的情况可以留言和博主以及小伙伴们一起讨论看看!

机器准备

机器名 机器外部IP 机器内网IP
k8sdev001 10.12.3.40 192.168.3.35
k8sdev002 10.12.3.41 192.168.3.34
k8sdev003 10.12.3.42 192.168.3.33

系统和软件版本

  • CentOS 7.4.1708
  • etcd Version: 3.3.11
  • cfssl 1.6.3

配置 hosts

下面的机器命名和服务域名定义均是博主个人喜好,大家可以按照自己的习惯变更!

1
2
3
4
5
6
7
8
9
# hostname resolve
192.168.3.35 k8sdev001
192.168.3.34 k8sdev002
192.168.3.33 k8sdev003

# etcd cluster
192.168.3.35 etcd01-dev.inner.com
192.168.3.34 etcd02-dev.inner.com
192.168.3.33 etcd03-dev.inner.com

安装必备软件

博主使用的是 root 用户进行操作,如果您当前的用户没有权限,请记得切换 root 用户或者使用 sudo 进行操作!

安装 cfssl

1
2
3
4
5
6
7
8
9
10
cd /tmp

wget https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl_1.6.3_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssljson_1.6.3_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl-certinfo_1.6.3_linux_amd64
chmod +x cfssl_1.6.3_linux_amd64 cfssljson_1.6.3_linux_amd64 cfssl-certinfo_1.6.3_linux_amd64

mv cfssl_1.6.3_linux_amd64 /usr/local/bin/cfssl
mv cfssljson_1.6.3_linux_amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_1.6.3_linux_amd64 /usr/local/bin/cfssl-certinfo

安装 etcd

此处博主使用系统默认的安装命令安装,因为对应 etcd 版本刚好是 3.3.11

1
yum install etcd

如果您想自己指定版本安装,可以参考如下命令(GPT式教程):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装依赖包
yum install -y curl wget tar

# 下载对应版本的压缩包,此处使用 v3.3.11
cd /tmp
wget https://github.com/coreos/etcd/releases/download/v3.3.11/etcd-v3.3.11-linux-amd64.tar.gz
tar -xzf etcd-v3.3.11-linux-amd64.tar.gz
cd etcd-v3.3.11-linux-amd64/

# 将 etcd 和 etcdctl 可执行文件复制到 /usr/local/bin 目录下
cp etcd /usr/local/bin/
cp etcdctl /usr/local/bin/

# 创建 etcd 的数据目录和日志目录
mkdir -p /var/lib/etcd/
mkdir -p /var/log/etcd/

构建集群

生成自签名证书

CFSSL(CloudFlare SSL)是一个开源的 PKI/TLS 工具包,用于创建、签署、验证 SSL 证书。

它是由 CloudFlare 公司开发并开源的,目的是提供一个轻量级、易于使用的工具包,以便开发人员可以更轻松地设置自己的 PKI/TLS 系统。

CFSSL 支持多种证书颁发机构(CA)的配置,并且可以使用 JSON 或 YAML 配置文件定义证书和请求。

如果您比较熟悉 openssl ,也可以使用 openssl 进行自签名!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# 创建存放密钥的文件夹
mkdir -p /etc/etcd/etcd-certs

# 下面的操作都在该文件夹下面进行
cd /etc/etcd/etcd-certs

# 创建 CA 配置文件
# expiry 为签名过期时长
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes": {
"expiry": "876000h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF

# 创建证书签名请求文件(请根据自己实际情况更新 names 里面的内容)
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key":
{
"algo": "rsa",
"size": 2048
},
"names":
[
{
"C": "CN",
"ST": "GuangDong",
"L": "GuangDong",
"O": "k8s",
"OU": "System"
}
]
}
EOF


# 创建 etcd 证书配置文件 etcd-csr.json
# hosts 把之后会对外暴露的域名、服务器名字、内外网IP都加上吧,然后是否对外通过防火墙控制就好,这样比较大程度能增加后期维护的扩展性
# names 信息和 ca-csr.json 保持一致
cat > kubernetes-csr.json << EOF
{
"CN": "kubernetes",
"hosts":
[
"10.12.3.40",
"10.12.3.41",
"10.12.3.42",
"192.168.3.35",
"192.168.3.34",
"192.168.3.33",
"etcd01-dev.inner.com",
"etcd02-dev.inner.com",
"etcd03-dev.inner.com",
"k8sdev001",
"k8sdev002",
"k8sdev003"
],
"key":
{
"algo": "rsa",
"size": 2048
},
"names":
[
{
"C": "CN",
"ST": "GuangDong",
"L": "GuangDong",
"O": "k8s",
"OU": "System"
}
]
}
EOF


# 创建 CA 证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
# 创建 etcd 证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
# 此时执行 ls -al |grep -v json 可以看到如下文件情况
-rw-r--r-- 1 root root 1005 Mar 23 16:06 ca.csr
-rw------- 1 root root 1675 Mar 23 16:06 ca-key.pem
-rw-rw-r-- 1 root root 1322 Mar 23 16:06 ca.pem
-rw-r--r-- 1 root root 1188 Mar 23 16:06 kubernetes.csr
-rw------- 1 root root 1679 Mar 23 16:06 kubernetes-key.pem
-rw-rw-r-- 1 root root 1521 Mar 23 16:06 kubernetes.pem

上面生成的文件应该复制到所有机器,一个是构建 etcd 集群需要,再者后续如果需要构建 k8s 集群,kubeadm 也需要用到它们!

进行 etcd 配置

关于 etcd 的配置内容本篇文章不多讲解,大家可以先自行了解!

下面的配置着重关注几点:

  1. name 的配置需要每个服务器设置单独的名字,此处我用了 etcd-dev-${num}
  2. listen-client-urls , listen-peer-urls, initial-advertise-peer-urls 替换成节点的 IP
  3. advertise-client-urls 修改成你需要对外暴露的地址,如果需要内外网都设置可以参考我的设置进行调整
  4. initial-cluster 是集群的所有机器地址, 格式为 ${name}=https://${your_ip}:2380,多个机器用英文逗号分隔
  5. initial-cluster-token 按照您的需要调整即可
  6. etcd 使用的默认端口号 23792380 您也可以根据实际需要调整,调整的话防火墙策略也要进行变更
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cat > /etc/etcd/etcd-config.yaml <<EOF
# 请注意,每台服务器需要控制name是不一样的
name: etcd-dev-1
data-dir: /data/database/etcd
listen-client-urls: https://192.168.3.35:2379
listen-peer-urls: https://192.168.3.35:2380
initial-advertise-peer-urls: https://192.168.3.35:2380
advertise-client-urls: https://192.168.3.35:2379,https://10.12.3.40:2379
initial-cluster: etcd-dev-1=https://192.168.3.35:2380,etcd-dev-2=https://192.168.3.34:2380,etcd-dev-3=https://192.168.3.33:2380
# 请按需调整 initial-cluster-token
initial-cluster-token: etcd-dev-cluster
initial-cluster-state: new
client-transport-security:
cert-file: /etc/etcd/etcd-certs/kubernetes.pem
key-file: /etc/etcd/etcd-certs/kubernetes-key.pem
client-cert-auth: true
trusted-ca-file: /etc/etcd/etcd-certs/ca.pem
peer-transport-security:
cert-file: /etc/etcd/etcd-certs/kubernetes.pem
key-file: /etc/etcd/etcd-certs/kubernetes-key.pem
client-cert-auth: true
trusted-ca-file: /etc/etcd/etcd-certs/ca.pem
auto-compaction-mode: "periodic"
auto-compaction-retention: "24h"
EOF

别忘了设置文件权限 chown etcd:etcd /etc/etcd/etcd-config.yaml

提前放行防火墙策略

博主此处放行的是内外部的网段,因为本身博主是要将这个集群共享给不同团队使用!
如果您搭建的集群是团队内自使用的请自行定义放行范围规则!
另外,无论是防火墙还是下面的启动服务操作,都需要多台机器进行处理,请做好自检!

1
2
iptables -A INPUT -s 10.12.3.0/24 -p tcp -i eth0 -m multiport --dports 2379:2380 -j ACCEPT
iptables -A INPUT -s 192.168.3.0/24 -p tcp -i eth0 -m multiport --dports 2379:2380 -j ACCEPT

启动集群

  • 创建或者调整服务文件 vim /usr/lib/systemd/system/etcd.service ,参考如下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
WorkingDirectory=/data/database/etcd
EnvironmentFile=-/etc/etcd/etcd.conf
User=etcd
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --config-file /etc/etcd/etcd-config.yaml"
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
  • 设置开机启动并启动服务
1
2
3
4
5
6
7
8
# 重载上面变更的 service 配置
systemctl daemon-reload
# 设置 etcd 服务开机启动
systemctl enable etcd
# 启动 etcd
systemctl start etcd
# 检查服务是否正常运行
systemctl status etcd

如果您碰到无法解决的问题,欢迎在评论区留言,我这边会根据自己的经验看下是否能为您提供一些帮助!

验证集群

恭喜您,到了这一步基本说明您前面搭建都是比较顺利的,接下来就是最重要的,验证集群是否顺利搭建完成

1
2
3
4
5
6
7
8
9
10
11
# 登录到任意一台 etcd 节点, 执行 etcdctl 命令,获取 etcd 集群的状态信息
etcdctl --endpoints=https://192.168.3.33:2379,https://192.168.3.34:2379,https://192.168.3.35:2379 --ca-file=/etc/etcd/etcd-certs/ca.pem --cert-file=/etc/etcd/etcd-certs/kubernetes.pem --key-file=/etc/etcd/etcd-certs/kubernetes-key.pem cluster-health
# 如果您也开启了外部访问,别忘了也进行简单的验证哦
etcdctl --endpoints=https://10.12.3.40:2379,https://10.12.3.41:2379,https://10.12.3.42:2379 --ca-file=/etc/etcd/etcd-certs/ca.pem --cert-file=/etc/etcd/etcd-certs/kubernetes.pem --key-file=/etc/etcd/etcd-certs/kubernetes-key.pem cluster-health

# 下面是更为美化的查看方式
ETCDCTL_API=3 etcdctl --endpoints=https://192.168.3.33:2379,https://192.168.3.34:2379,https://192.168.3.35:2379 --cacert=/etc/etcd/etcd-certs/ca.pem --cert=/etc/etcd/etcd-certs/kubernetes.pem --key=/etc/etcd/etcd-certs/kubernetes-key.pem endpoint health --write-out=table
# 如果您能看到类似如下的输出,恭喜您已经成功搭建好集群了
https://192.168.3.34:2379 is healthy: successfully committed proposal: took = 3.457399ms
https://192.168.3.35:2379 is healthy: successfully committed proposal: took = 4.456716ms
https://192.168.3.33:2379 is healthy: successfully committed proposal: took = 1.745809ms

etcd 也提供了基于用户名和密码的身份认证机制,可以用来替代或补充 TLS 证书认证机制。
您可以根据您的实际需要来选择用 TLS 模式还是身份认证模式来构建集群,但是后者安全性较弱一些!