etcd介绍
Etcd 是 CoreOS 推出的高可用的键值存储系统,内部采用 raft 协议作为一致性算法,主要用于k8s集群的服务发现等,而本身 Etcd 也支持集群模式部署,从而实现自身高可用;
作为服务发现系统,有以下的特点:
- 简单:安装配置简单,而且提供restful的http接口,使用也很简单
- 安全:支持 SSL 证书验证
- 快速:根据官方提供的 benchmark 数据,单实例支持每秒 2k+ 读操作
- 可靠:采用 raft 算法,实现分布式系统数据的可用性和一致性
Etcd 构建自身高可用集群主要有三种形式:
- 静态发现: 预先已知 Etcd 集群中有哪些节点,在启动时直接指定好 Etcd 的各个 node 节点地址
- Etcd 动态发现: 通过已有的 Etcd 集群作为数据交互点,然后在扩展新的集群时实现通过已有集群进行服务发现的机制
- DNS 动态发现: 通过 DNS 查询方式获取其他节点地址信息
etcd 目前默认使用2379
端口提供HTTP API
服务,2380
端口和peer
通信这两个端口已经被 IANA 官方预留给 etcd;在之前的版本中,可能会分别使用 4001 和 7001,在使用的过程中需要注意这个区别。
虽然 etcd 也支持单点部署,但是在生产环境中推荐集群方式部署,一般 etcd 节点数会选择 3、5、7。etcd 会保证所有的节点都会保存数据,并保证数据的一致性和正确性。
etcd入门指南
etcd使用入门
Discovery官网参考
etcd集群部署
etcd集群部署
etcd安装有yum安装和二进制包安装的方式,使用http,https协议
这里的实验是使用二进制方式开启TLS认证
节点规划
节点 | 地址 |
---|---|
etcd0 | 192.168.16.235 |
etcd1 | 192.168.16.236 |
etcd2 | 192.168.16.237 |
etcd3 | 192.168.16.238 |
etcd4 | 192.168.16.239 |
TLS认证文件
创建证书目录
mkdir -p /usr/local/kubernetes/crts # 证书请求文件工作目录
mkdir -p /etc/etcd/ssl # etcd证书路径
mkdir -p /usr/local/etcd/bin/ # etcd 二进制程序路径
制作自签名根证书
配置文件
cat > /usr/local/kubernetes/crts/ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
配置文件为CA签署证书提供配置项,可定义多个profile,此处定义了一个名为kubernetes的profile,可以提供服务端和客户端签署认证,签署的证书有效期为87600小时(10年)
- signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
- server auth:表示client可以用该 CA 对server提供的证书进行验证;
- client auth:表示server可以用该 CA 对client提供的证书进行验证。
CA证书请求文件
cat > /usr/local/kubernetes/crts/ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
EOF
- CN: Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
- O: Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group)
使用cfssl工具根据请求文件生成证书文件和密钥文件
cd /usr/local/kubernetes/crts
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
-rw-------. 1 root root 1679 May 25 14:36 ca-key.pem # 证书对应的密钥文件
-rw-r--r--. 1 root root 1314 May 25 14:36 ca.pem # 证书文件
制作etcd证书
创建etcd 证书签名请求:
cat > /usr/local/kubernetes/crts/etcd-csr.json <<EOF
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"192.168.16.235",
"192.168.16.236",
"192.168.16.237",
"192.168.16.238",
"192.168.16.239"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
EOF
【注意】:证书的 hosts 字段列表中包含上面台机器的
IP
,否则后续证书校验会失败
生成etcd证书和私钥:
cd /usr/local/kubernetes/crts
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
-rw-------. 1 root root 1679 May 25 14:55 etcd-key.pem
-rw-r--r--. 1 root root 1456 May 25 14:55 etcd.pem
复制分发证书
要求此节点可以自动化分发到其他节点上,可以使用ansible或者saltstack来进行分发
vim /etc/ansible/hosts
[k8s]
k8s-m1-16-235
k8s-m2-16-236
k8s-m3-16-237
k8s-n1-16-238
k8s-n2-16-239
k8s-n3-16-240
k8s-n4-16-241
k8s-n5-16-242
k8s-n6-16-243
k8s-n7-16-244
[etcd]
k8s-m1-16-235
k8s-m2-16-236
k8s-m3-16-237
k8s-n1-16-238
k8s-n2-16-239
[k8s-master]
k8s-m1-16-235
k8s-m2-16-236
k8s-m3-16-237
[k8s-node]
k8s-n1-16-238
k8s-n2-16-239
k8s-n3-16-240
k8s-n4-16-241
k8s-n5-16-242
k8s-n6-16-243
k8s-n7-16-244
复制ectd证书
# 创建相关目录
ansible k8s -a 'mkdir -p /usr/local/kubernetes/bin'
ansible k8s -a 'mkdir -p /etc/kubernetes/ssl'
ansible etcd -a 'mkdir -p /etc/etcd/ssl'
ansible etcd -a 'mkdir -p /usr/local/etcd/bin'
ansible etcd -a 'mkdir -p /var/lib/etcd/'
cp /usr/local/kubernetes/crts/ca*.pem /etc/kubernetes/ssl/
cp /usr/local/kubernetes/crts/etcd*.pem /etc/etcd/ssl/
ansible k8s -m copy -a 'src=/etc/kubernetes/ssl/ dest=/etc/kubernetes/ssl'
ansible etcd -m copy -a 'src=/etc/etcd/ssl/ dest=/etc/etcd/ssl'
下载安装etcd
wget https://github.com/coreos/etcd/releases/download/v3.3.6/etcd-v3.3.6-linux-amd64.tar.gz
tar -xf etcd-v3.3.6-linux-amd64.tar.gz -C /usr/local/src/
cp /usr/local/src/etcd-v3.3.6-linux-amd64/{etcd,etcdctl} /usr/local/etcd/bin/
echo 'export PATH=$PATH:/usr/local/etcd/bin' > /etc/profile.d/etcd.sh
source !$
etcd配置
cat > /etc/etcd/etcd.conf << EOF
# [member]
ETCD_NAME=etcd0
ETCD_DATA_DIR="/var/lib/etcd/"
ETCD_WAL_DIR="/var/lib/etcd/wal"
ETCD_SNAPSHOT_COUNT="100"
ETCD_HEARTBEAT_INTERVAL="100"
ETCD_ELECTION_TIMEOUT="1000"
ETCD_LISTEN_PEER_URLS="https://192.168.16.235:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.16.235:2379,https://127.0.0.1:2379"
ETCD_MAX_SNAPSHOTS="5"
ETCD_MAX_WALS="5"
# [cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.16.235:2380"
ETCD_INITIAL_CLUSTER="etcd0=https://192.168.16.235:2380,etcd1=https://192.168.16.236:2380,etcd2=https://192.168.16.237:2380,etcd3=https://192.168.16.238:2380,etcd4=https://192.168.16.239:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.16.235:2379"
# [security]
ETCD_CERT_FILE="/etc/etcd/ssl/etcd.pem"
ETCD_KEY_FILE="/etc/etcd/ssl/etcd-key.pem"
ETCD_CLIENT_CERT_AUTH="true"
ETCD_TRUSTED_CA_FILE="/etc/kubernetes/ssl/ca.pem"
ETCD_AUTO_TLS="true"
ETCD_PEER_CERT_FILE="/etc/etcd/ssl/etcd.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/ssl/etcd-key.pem"
ETCD_PEER_CLIENT_CERT_AUTH="true"
ETCD_PEER_TRUSTED_CA_FILE="/etc/kubernetes/ssl/ca.pem"
ETCD_PEER_AUTO_TLS="true"
EOF
- 对应的主机修改ip与名字即可
- 指定etcd的工作目录和数据目录为/var/lib/etcd,需要在启动服务前创建这个目录;
- 为了保证通信安全,需要指定etcd 的公私钥(cert-file和key-file)、Peers通信的公私钥和CA 证书(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客户端的CA 证书(trusted-ca-file);
- --initial-cluster-state值为new时,--name的参数值必须位于--initial-cluster
etcd服务启动脚本
cat > /usr/lib/systemd/system/etcd.service << EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/local/etcd/bin/etcd
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
分发文件到其他机器
etcd二进制文件
ansible etcd -m copy -a 'src=/usr/local/etcd/bin/ dest=/usr/local/etcd/bin'
ansible etcd -a 'chmod +x /usr/local/etcd/bin/etcdctl'
ansible etcd -a 'chmod +x /usr/local/etcd/bin/etcd'
etcd配置文件
ansible etcd -m copy -a 'src=/etc/etcd/etcd.conf dest=/etc/etcd/etcd.conf'
记得逐个修改etcd节点名称和ip
ectd服务启动脚本
ansible etcd -m copy -a 'src=/usr/lib/systemd/system/etcd.service dest=/usr/lib/systemd/system/etcd.service'
启动etcd服务
ansible etcd -m systemd -a 'daemon-reload=yes enabled=yes name=etcd state=started'
验证etcd集群
查看集群健康状态
etcdctl \
--endpoints=https://192.168.16.235:2379 \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/etcd/ssl/etcd.pem \
--key-file=/etc/etcd/ssl/etcd-key.pem \
cluster-health
member 6c1783871ca5db4 is healthy: got healthy result from https://192.168.16.239:2379
member b4237dbfd3897ed is healthy: got healthy result from https://192.168.16.238:2379
member 3e659394cad5de8c is healthy: got healthy result from https://192.168.16.235:2379
member 80996653f2b4ed3c is healthy: got healthy result from https://192.168.16.237:2379
member d922ad5b843b78c3 is healthy: got healthy result from https://192.168.16.236:2379
cluster is healthy
查看集群成员,并能看出哪个是leader节点
etcdctl \
--endpoints=https://192.168.16.235:2379 \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/etcd/ssl/etcd.pem \
--key-file=/etc/etcd/ssl/etcd-key.pem \
member list
6c1783871ca5db4: name=etcd4 peerURLs=https://192.168.16.239:2380 clientURLs=https://192.168.16.239:2379 isLeader=false
b4237dbfd3897ed: name=etcd3 peerURLs=https://192.168.16.238:2380 clientURLs=https://192.168.16.238:2379 isLeader=false
3e659394cad5de8c: name=etcd0 peerURLs=https://192.168.16.235:2380 clientURLs=https://192.168.16.235:2379 isLeader=true
80996653f2b4ed3c: name=etcd2 peerURLs=https://192.168.16.237:2380 clientURLs=https://192.168.16.237:2379 isLeader=false
d922ad5b843b78c3: name=etcd1 peerURLs=https://192.168.16.236:2380 clientURLs=https://192.168.16.236:2379 isLeader=false
etcd使用
V3版本,注意在V3版本中所有的key和value都必须转换为base64编码然后才可以存储
通过curl来维护etcd
查看版本
> curl -k --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem https://127.0.0.1:2379/version
{"etcdserver":"3.3.6","etcdcluster":"3.3.0"}
etcdctl
查看版本
> ETCDCTL_API=3 etcdctl version
etcdctl version: 3.3.6
API version: 3.3