Kubernetes 数据库 Etcd 日常运维及技巧

微信公众号搜索 DevOps和k8s全栈技术 ,或者扫描文章最后的二维码,即可关注公众号,每天会分享技术文章供大家阅读参考哈~

正文

etcd 是基于 raft算法的分布式键值数据库,生来就为集群化而设计的,由于Raft算法在做决策时需要超半数节点的投票,所以etcd集群一般推荐奇数节点,如3、5或者7个节点构成一个集群。

以上是etcd集群部署的共识,但是还需要注意以下问题:

一、Etcd选主过程

etcd 是高可用的,允许部分机器故障,以标准的3 节点etcd 集群,容忍1台机器宕机,下面以最简单的leader宕机来演示raft 的投票逻辑,以实际的运行日志来验证并理解。更多的场景可以看之前的原理解析

场景:正常运行的三台etcd:100、101、102。当前任期为 7,leader 为 101机器。使101 宕机

宕机前:101 为 leader,3 个 member

宕机后:102 成为新 leader,2 个 member

选举过程:

将 101 机器的 etcd 停止,此时只剩 2 台,但总数为 3。

1、101停止etcd 的运行

2、102(91d63231b87fadda) 收到消息,发现101(8a4bb0af2f19bd46)心跳超时,于是发起了新一轮选举,任期为 7+1=8

91d63231b87fadda [term 7] received MsgTimeoutNow from 8a4bb0af2f19bd46 and starts an election to get leadership.

3、102(91d63231b87fadda)成为新一任的候选人,然后自己投给了自己,获得 1 票;

91d63231b87fadda became candidate at term 8
91d63231b87fadda received MsgVoteResp from 91d63231b87fadda at term 8

4、102(91d63231b87fadda)发送给 挂掉的101 和 另一个100,希望他们也投给自己;

91d63231b87fadda [logterm: 7, index: 4340153] sent MsgVote request to 8a4bb0af2f19bd46 at term 8


91d63231b87fadda [logterm: 7, index: 4340153] sent MsgVote request to 9feab580a25dd270 at term 8

5、102 肯定收不到 101 的回应,因为 101 已经挂掉;

etcd[24203]: lost the TCP streaming connection with peer 8a4bb0af2f19bd46 (stream MsgApp v2 reader)

6、100 (9feab580a25dd270)收到了 102 的拉票消息,因为任期 8 大于当前100机器所处的 7,于是知道是发起了新的一轮选举,因此回应 101,我给你投票。这里任期term是关键,也就是说,100 和 102 谁先感受到 101 宕机,发起投票,谁就是新的 leader,这个也和进程初始的启动时间有关。

9feab580a25dd270 [term: 7] received a MsgVote message with higher term from 91d63231b87fadda [term: 8]


9feab580a25dd270 became follower at term 8


9feab580a25dd270 [logterm: 7, index: 4340153, vote: 0] cast MsgVote for 91d63231b8


9feab580a25dd270 elected leader 91d63231b87fadda at term 8

7、102 获得了 2 票,一票是自己,一票是 100,超过半数,成为新的 leader。任期为 8;

91d63231b87fadda elected leader 91d63231b87fadda at term 8
  • 更换完成。

二、Etcd集群必须是奇数节点吗?

etcd官方推荐3、5、7个节点,虽然raft算法也是半数以上投票才能有 leader,但奇数只是推荐,其实偶数也是可以的。如 2、4、8个节点。分情况说明:

  • 1 个节点:就是单实例,没有集群概念,不做讨论;

  • 2 个节点:是集群,但没人会这么配,这里说点废话:双节点的etcd能启动,启动时也能有主,可以正常提供服务,但是一台挂掉之后,就选不出主了,因为他只能拿到1票,剩下的那台也无法提供服务,也就是双节点无容错能力,不要使用。

2节点正常运行:

1台宕机后:

  • 3 节点:标准的3 节点etcd 集群只能容忍1台机器宕机,挂掉 1 台的逻辑上边已经演示过,如果再挂 1 台,就和 2节点的情形一致了,一直选,一直增加任期,但就是选不出来,服务也就不可用了;

  • 4 节点:最大容忍1 台

  • 5 节点:最大容忍 2 台

  • 6 节点:最大容忍 2 台

你会发现偶数节点虽然多了一台机器,但是容错能力是一样的,也就是说,你可以设置偶数节点,但没增加什么能力,还浪费了一台机器。同时etcd 是通过复制数据给所有节点来达到一致性,因此偶数的多一台机器增加不了性能,反而会拉低写入速度。

三、Etcd集群机器越多越好吗?

etcd 集群是一个 Raft Group,没有 shared。所以它的极限有两部分,一是单机的容量限制,内存和磁盘;二是网络开销,每次 Raft 操作需要所有节点参与,每一次写操作需要集群中大多数节点将日志落盘成功后,Leader 节点才能修改内部状态机,并将结果返回给客户端。因此节点越多性能越低,所以扩展很多 etcd 节点是没有意义的,一般是 3、5、7, 7 个也足够了。

在 k8s 中一般是3*master机器做高可用,也就是 3节点的 etcd。也有人将 etcd独立于 k8s集群之外,来更好地扩展 etcd 集群,或者根据 k8s 的资源来拆分 etcd,如 events 放在单独的 etcd 集群中。不同的副本数视业务规模而定,3,5,7 都可以。

四、Etcd有脑裂问题吗?

集群化的软件总会提到脑裂问题,如ElasticSearch、Zookeeper集群,脑裂就是同一个集群中的不同节点,对于集群的状态有了不一样的理解。

etcd 中有没有脑裂问题?答案是:没有

The majority side becomes the available cluster and the minority side is unavailable; there is no “split-brain” in etcd.

以网络分区导致脑裂为例,一开始有5个节点, Node 5 为 Leader。

由于出现网络故障,124 成为一个分区,35 成为一个分区, Node 5 的 leader 任期还没结束的一段时间内,仍然认为自己是当前leader,但是此时另外一边的分区,因为124无法连接 5,于是选出了新的leader 1,网络分区形成。

35分区是否可用?如果写入了1而读取了 5,是否会读取旧数据(stale read)?

答:35分区属于少数派,被认为是异常节点,无法执行写操作。写入 1 的可以成功,并在网络分区恢复后,35 因为任期旧,会自动成为 follower,异常期间的新数据也会从 1 同步给 35。

而 5 的读请求也会失败,etcd 通过ReadIndex、Lease read保证线性一致读,即节点5在处理读请求时,首先需要与集群多数节点确认自己依然是Leader并查询 commit index,5做不到多数节点确认,因此读失败。

因此 etcd 不存在脑裂问题。线性一致读的内容下面会提到。

五、Etcd是强一致性吗?

是强一致性,读和写都可以保证线性一致,关于一致性的分析可以看 这篇文章

线性一致读

线性一致性读需要在所有节点走一遍确认,查询速度会有所降低,要开启线性一致性读,在不同的 client是有所区别的:

  • v2 版本:通过 sdk访问时,quorum=true 的时候读取是线性一致的,通过etcdctl访问时,该参数默认为true。

  • v3 版本:通过 sdk访问时,WithSerializable=true 的时候读取是线性一致的,通过etcdctl访问时consistency=“l”表示线性(默认为 l,非线性为 s)

为了保证线性一致性读,早期的 etcd(_etcd v3.0 _)对所有的读写请求都会走一遍 Raft 协议来满足强一致性。然而通常在现实使用中,读请求占了 etcd 所有请求中的绝大部分,如果每次读请求都要走一遍 raft 协议落盘,etcd 性能将非常差。

因此在 etcd v3.1 版本中优化了读请求(PR#6275),使用的方法满足一个简单的策略:每次读操作时记录此时集群的 commit index,当状态机的 apply index 大于或者等于 commit index 时即可返回数据。由于此时状态机已经把读请求所要读的 commit index 对应的日志进行了 apply 操作,符合线性一致读的要求,便可返回此时读到的结果。

六、Etcd集群部署

简单介绍下 etcd 的安装过程。下载 etcd3.4 的 release 包。

1、生成证书

1.1 ca-config.json

创建用来生成 CA 文件的 JSON 配置文件,这个文件后面会被各种组件使用,包括了证书过期时间的配置,expiry字段:

{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "demo": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}

1.2 ca-csr.json

创建用来生成 CA 证书签名请求(CSR)的 JSON 配置文件:

{
  "CN": "demo",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "demo",
      "OU": "cloudnative"
    }
  ]
}

1.3 生成基础 ca 证书

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

执行后会生成三个文件:

  • ca.csr:证书签名请求,一般用于提供给证书颁发机构,自签就不需要了

  • ca.pem:证书,公共证书

  • ca-key.pem:CA密钥

1.4 生成 etcd 证书

增加etcd-csr.json文件,ip 需要填写三台 etcd 机器的 ip:

{
    "CN": "demo",
    "hosts": [
        "127.0.0.1",
        "ip1","ip2","ip3"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "ST": "BeiJing",
            "L": "BeiJing",
            "O": "demo",
            "OU": "cloudnative"
        }
    ]
}

这里的hosts字段中指定了授权使用该证书的IP和域名列表,因为现在要生成的证书需要被etcd集群各个节点使用,所以这里指定了各个节点的IP。

生成证书:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=jpaas etcd-csr.json | cfssljson -bare etcd

创建etcd 的 CA 证书:这里需要4 个文件

  • etcd-csr.json:etcd的证书配置

  • ca.pem:基础公钥

  • ca-key.pem:基础私钥

  • ca-config.json:配置文件,如过期时间

执行后会生成三个文件:

  • etcd.csr

  • etcd.pem

  • etcd-key.pem

在一台机器上做证书生成,生成后将这三个文件拷贝到其他几台机器。

2、部署集群

etcd 启动配置示例:

./etcd \
--name=etcd-0 \
--client-cert-auth=true \
--cert-file=/etc/etcd/ssl/etcd.pem \
--key-file=/etc/etcd/ssl/etcd-key.pem \
--peer-cert-file=/etc/etcd/ssl/etcd.pem \
--peer-key-file=/etc/etcd/ssl/etcd-key.pem \
--trusted-ca-file=/etc/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \
--initial-advertise-peer-urls https://100.0.0.0:2380 \
--listen-peer-urls https://100.0.0.0:2380 \
--listen-client-urls https://100.0.0.0:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://100.0.0.0:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster etcd-0=https://100.0.0.0:2380,etcd-1=https://100.0.0.1:2380,etcd-2=https://100.0.0.2:2380 \
--initial-cluster-state new \
--quota-backend-bytes=8589934592 \
--auto-compaction-retention=10 \
--enable-pprof=true \
--data-dir=/var/lib/etcd

3、etcdctl命令

因为etcd配置了证书,所以所有的命令都要带上证书访问,如:

ETCDCTL_API=3 ./etcdctl --endpoints=https://0:2379,https://1:2379,https://2:2379 --cacert /etc/etcd/ssl/ca.pem --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem endpoint status --write-out=table
  • version: 查看版本

  • member list: 查看节点

  • endpoint status: 节点状态,leader 情况

  • endpoint health: 健康状态与耗时

  • set app demo: 写入

  • get app: 获取

  • update app demo1:更新

  • rm app: 删除

  • mkdir demo 创建文件夹

  • rmdir dir 删除文件夹

  • backup 备份

  • watch key 监测 key 变化

  • get / –prefix –keys-only: 查看所有 key

- END -

往期精彩文章

kubernetes全栈技术+企业案例演示【带你快速掌握和使用k8s】

突破运维和开发瓶颈、Python、k8s、DevOps转型一网打尽!

python运维开发实战-基础篇

python运维和开发实战-高级篇

python运维和开发实战-安装和创建Django项目

谈谈我的IT发展之路

Prometheus+Grafana+Alertmanager搭建全方位的监控告警系统-超详细文档

k8s1.18多master节点高可用集群安装-超详细中文官方文档

linux面试题汇总

python运维和开发实战-安装和创建Django项目

Docker公司禁止被列入美国"实体名单"的国家、企业使用

Jenkis pipeline构建项目实践-编写podTemplate实现和k8s对接

安装kubernetes集群-灵活安装k8s各个版本高可用集群

Kubernetes v1.19 正式发布

高效的Nginx负载均衡器

5个维度对 Kubernetes 集群优化

什么是架构师?

QPS、TPS、并发用户数、吞吐量关系

kubernetes面试题汇总

DevOps视频和资料免费领取

kubernetes技术分享-可用于企业内部培训

谈谈我的IT发展之路

kubernetes系列文章第一篇-k8s基本介绍

kubernetes系列文章第二篇-kubectl

了解pod和pod的生命周期-这一篇文章就够了

Kubernetes中部署MySQL高可用集群

k8s中蓝绿部署、金丝雀发布、滚动更新汇总

运维常见问题汇总-tomcat篇

关于linux内核参数的调优,你需要知道

kubernetes挂载ceph rbd和cephfs

报警神器Alertmanager发送报警到多个渠道

jenkins+kubernetes+harbor+gitlab构建企业级devops平台

kubernetes网络插件-flannel篇

kubernetes网络插件-calico篇

kubernetes认证、授权、准入控制

限制不同的用户操作k8s资源

面试真题&技术资料免费领取-覆盖面超全~

Prometheus监控MySQL

Prometheus监控Nginx

Prometheus监控Tomcat

linux面试题汇总

测试通过storageclass动态生成pv

通过编写k8s的资源清单yaml文件部署gitlab服务

helm安装和使用-通过helm部署k8s应用

k8s基于Ingress-nginx实现灰度发布

k8s的Pod安全策略

Prometheus Operator-上篇-安装和使用篇

Prometheus Operator-下篇

通过kubeconfig登陆k8s的dashboard ui界面

通过token令牌登陆k8s dashboard ui界面 

kubernetes集群的etcd数据库详细介绍

Linux网络流量监控工具

kubernetes搭建EFK日志管理系统

prometheus operator监控k8s集群之外的haproxy组件         

kubernetes ConfigMap存储卷      

Python采集linux服务器数据在Django Web界面展示

基于Kubernetes的GPU类型调度实现    

容器日志管理的最佳实践                               

技术交流

学无止境,了解更多关于kubernetes/docker/devops/openstack/openshift/linux/IaaS/PaaS相关内容,想要获取更多资料和免费视频,可按如下方式进入技术交流群

微信:luckylucky421302

按如下指纹可关注


作者:徐亚松

地址:http://www.xuyasong.com/?p=1983

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值