Etcd超全解:原理阐释及部署设置的最佳实践

本文将带你充分了解Etcd的工做原理,演示如何用Kubernetes创建并运行etcd集群,如何与Etcd交互,如何在Etcd中设置和检索值,如何配置高可用等等。git


介 绍github

Etcd是一个开源的分布式键值存储,它由CoreOS团队开发,如今由Cloud Native Computing Foundation负责管理。这个词的发音是“et-cee-dee”,表示在多台机器上分发Unix系统的“/etc”目录,其中包含了大量的全局配置文件。它是许多分布式系统的主干,为跨服务器集群存储数据提供可靠的方式。它适用于各类操做系统,包括Linux、BSD和OS X。算法

Etcd具备下面这些属性:数据库

  • 彻底复制:集群中的每一个节点均可以使用完整的存档api

  • 高可用性:Etcd可用于避免硬件的单点故障或网络问题缓存

  • 一致性:每次读取都会返回跨多主机的最新写入安全

  • 简单:包括一个定义良好、面向用户的API(gRPC)服务器

  • 安全:实现了带有可选的客户端证书身份验证的自动化TLS网络

  • 快速:每秒10000次写入的基准速度app

  • 可靠:使用Raft算法实现了存储的合理分布

Etcd的工做原理

在理解Etcd的工做机制以前,咱们先定义三个关键概念:leaders、elections以及terms。在一个基于Raft的系统中,集群使用election为给定的term选择leader。

Leader处理全部须要集群一致协商的客户端请求。不须要一致协商的请求(如读取)能够由任何集群成员处理。Leader负责接受新的更改,将信息复制到follower节点,并在follower验证接受后提交更改。每一个集群在任何给定的时间内只能有一个leader。

若是leader挂了或者再也不响应了,那么其余节点将在预约的时间超时以后开启一个新的term来建立新election。每一个节点维护一个随机的election计时器,该计时器表示节点在调用新的election以及选择本身做为候选以前须要等待的时间。

若是节点在超时发生以前没有收到leader的消息,则该节点将经过启动新的term、将本身标记为候选,并要求其余节点投票来开始新的election。每一个节点投票给请求其投票的第一个候选。若是候选从集群中的大多数节点处得到了选票,那么它就成为了新的leader。可是,若是存在多个候选且得到了相同数量的选票,那么现有的election term将在没有leader的状况下结束,而新的term将以新的随机选举计时器开始。

如上所述,任何更改都必须链接到leader节点。Etcd没有当即接受和提交更改,而是使用Raft算法确保大多数节点都赞成更改。Leader将提议的新值发送到集群中的每一个节点。而后,节点发送一条消息确认收到了新值。若是大多数节点确认接收,那么leader提交新值,并向每一个节点发送将该值提交到日志的消息。这意味着每次更改都须要获得集群节点的仲裁才能提交。

Kubernetes中的Etcd

自从2014年成为Kubernetes的一部分以来,Etcd社区呈现指数级的增加。CoreOS、谷歌、Redhat、IBM、思科、华为等等均是Etcd的贡献成员。其中AWS、谷歌云平台和Azure等大型云提供商成功在生产环境中使用了Etcd。

Etcd在Kubernetes中的工做是为分布式系统安全存储关键数据。它最著名的是Kubernetes的主数据存储,用于存储配置数据、状态和元数据。因为Kubernetes一般运行在几台机器的集群上,所以它是一个分布式系统,须要Etcd这样的分布式数据存储。

Etcd使得跨集群存储数据和监控更改变得更加容易,它容许来自Kubernetes集群的任何节点读取和写入数据。Kubernetes使用Etcd的watch功能来监控系统实际(actual)状态或指望(desired)状态的变化。若是这两个状态不一样,Kubernetes会作出一些改变来调和这两个状态。kubectl命令的每次读取都从Etcd存储的数据中检索,所作的任何更改(kubectl apply)都会在Etcd中建立或更新条目,每次崩溃都会触发etcd中值的修改。

部署以及硬件建议

出于测试或开发目的,Etcd能够在笔记本电脑或轻量云上运行。然而,在生产环境中运行Etcd集群时,咱们应该考虑Etcd官方文档提供的指导。它为良好稳定的生产部署提供了一个良好的起点。须要留意的是:

  • Etcd会将数据写入磁盘,所以强烈推荐使用SSD

  • 始终使用奇数个集群数量,由于须要经过仲裁来更新集群的状态

  • 出于性能考虑,集群一般不超过7个节点

让咱们回顾一下在Kubernetes中部署Etcd集群所需的步骤。以后,咱们将演示一些基本的CLI命令以及API调用。咱们将结合Kubernetes的概念(如StatefulSets和PersistentVolume)进行部署。

预先准备

在继续demo以前,咱们须要准备:

  • 一个谷歌云平台的帐号:免费的tier应该足够了。你也能够选择大多数其余云提供商,只需进行少许修改便可。

  • 一个运行Rancher的服务器

启动Rancher实例

在你控制的服务器上启动Rancher实例。这里有一个很是简单直观的入门指南:https://rancher.com/quick-start/

使用Rancher部署GKE集群

参照本指南使用Rancher在GCP帐户中设置和配置Kubernetes集群:

https://rancher.com/docs/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/gke/

在运行Rancher实例的同一服务器上安装Google Cloud SDK以及kubelet命令。按照上面提供的连接安装SDK,并经过Rancher UI安装kubelet。

使用gcloud init和gcloud auth login,确保gcloud命令可以访问你的GCP帐户。

集群部署后,输入下面的命令检查基本的kubectl功能:

在部署Etcd集群(经过kubectl或在Rancher的UI中导入YAML文件)以前,咱们须要配置一些项。在GCE中,默认的持久化磁盘是pd-standard。咱们将为Etcd部署配置pd-ssd。这不是强制性的,不过根据Etcd的建议,SSD是很是好的选择。查看此连接能够了解其余云提供商的存储类:

https://kubernetes.io/docs/concepts/storage/storage-classes/

让咱们检查一下GCE提供的可用存储类。正如预期的那样,咱们看到了一个默认的结果,叫作standard:

应用下面这个YAML文件,更新zone的值来匹配你的首选项,这样咱们就可使用SSD存储了:

咱们再一次检查,能够看到,除了默认standard类以外,ssd也可使用了:

如今咱们能够继续部署Etcd集群了。咱们将建立一个带有3个副本的StatefulSet,每一个副本都有一个ssd storageClass的专用卷。咱们还须要部署两个服务,一个用于内部集群通讯,一个用于经过API从外部访问集群。

在搭建集群时,咱们须要将一些参数传递给Etcd二进制文件再到数据存储中。Listen-client-urls和listen-peer-urls选项指定Etcd服务器用于接受传入链接的本地地址。指定0.0.0.0做为IP地址意味着Etcd将监听全部可用接口上的链接。Advertise-client-urls和initial-advertise-peer-urls参数指定了在Etcd客户端或者其余Etcd成员联系etcd服务器时应该使用的地址。

下面的YAML文件定义了咱们的两个服务以及Etcd StatefulSe图:

`# etcd-sts.yaml--- apiVersion: v1 kind: Service metadata: name: etcd-client spec: type: LoadBalancer ports:

  • name: etcd-client port: 2379 protocol: TCP targetPort: 2379 selector: app: etcd

apiVersion: v1 kind: Service metadata: name: etcd spec: clusterIP: None ports:

  • port: 2379 name: client
  • port: 2380 name: peer selector: app: etcd

apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: etcd labels: app: etcd spec: serviceName: etcd replicas: 3 template: metadata: name: etcd labels: app: etcd spec: containers: - name: etcd image: quay.io/coreos/etcd:latest ports: - containerPort: 2379 name: client - containerPort: 2380 name: peer volumeMounts: - name: data mountPath: /var/run/etcd command: - /bin/sh - -c - | PEERS="etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" exec etcd --name ${HOSTNAME}
--listen-peer-urls http://0.0.0.0:2380
--listen-client-urls http://0.0.0.0:2379
--advertise-client-urls http://${HOSTNAME}.etcd:2379
--initial-advertise-peer-urls http://${HOSTNAME}:2380
--initial-cluster-token etcd-cluster-1
--initial-cluster ${PEERS}
--initial-cluster-state new
--data-dir /var/run/etcd/default.etcd volumeClaimTemplates:

  • metadata: name: data spec: storageClassName: ssd accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi`

输入下列命令应用YAML:

在应用YAML文件后,咱们能够在Rancher提供的不一样选项卡中定义资源:

与Etcd交互

与Etcd交互的方式主要有两种:使用etcdctl命令或者直接经过RESTful API。咱们将简要介绍这两种方法,不过你还能够经过访问这里和这里的完整文档找到更加深刻的信息和示例。

Etcdctl是一个和Etcd服务器交互的命令行接口。它能够用于执行各类操做,如设置、更新或者删除键、验证集群健康状况、添加或删除Etcd节点以及生成数据库快照。默认状况下,etcdctl使用v2 API与Etcd服务器通讯来得到向后兼容性。若是但愿etcdctl使用v3 API和Etcd通讯,则必须经过ETCDCTL_API环境变量将版本设置为3。

对于API,发送到Etcd服务器的每个请求都是一个gRPC远程过程调用。这个gRPC网关提供一个RESTful代理,可以将HTTP/JSON请求转换为gRPC消息。

让咱们来找到API调用所需的外部IP:

咱们应该还能找到3个pods的名称,这样咱们就可使用etcdctl命令:

咱们检查Etcd版本。为此咱们可使用API或CLI(v2和v3).根据你选择的方法, 输出的结果将略有不一样。

使用此命令可直接与API联系:

检查API版本为v2的etcdctl客户端,输入:

检查API版本为v3的etcdctl客户端,则输入:

接下来,列出集群成员,就像咱们上面作的那样:

{"members":[{"id":"2e80f96756a54ca9","name":"etcd-0","peerURLs":["http://etcd-0.etcd:2380"],"clientURLs":["http://etcd-0.etcd:2379"]},{"id":"7fd61f3f79d97779","name":"etcd-1","peerURLs":["http://etcd-1.etcd:2380"],"clientURLs":["http://etcd-1.etcd:2379"]},{"id":"b429c86e3cd4e077","name":"etcd-2","peerURLs":["http://etcd-2.etcd:2380"],"clientURLs":["http://etcd-2.etcd:2379"]}]}

V2版本的etcdctl:

V3版本的etcdctl:

在Etcd中设置和检索值

下面咱们将介绍的最后一个示例是在Etcd集群中所有3个pods上建立一个键并检查其值。而后咱们会杀掉leader,在咱们的场景中是etcd-0,而后来看看新的leader是如何选出来的。最后,在集群恢复以后,咱们将在全部成员上验证以前建立的键的值。咱们会看到,没有数据丢失的状况发生,集群只是换了一个leader而已。

咱们能够经过输入下面的命令来验证集群最初是健康的:

接下来,验证当前leader。最后一个字段代表etcd-0是咱们集群中的leader:

使用该API,咱们将建立一个名为message的键并给它分配一个值,请记住在下面的命令中把IP地址替换为你在集群中经过下面命令获取到的地址:

不管查询哪一个成员,键都具备相同的值。这帮助咱们验证值是否已经复制到其余节点并提交到日志。

演示高可用性和恢复

接下来,咱们能够杀掉Etcd集群leader。这样咱们能够看到新的leader是如何选出的,以及集群如何从degraded状态中恢复过来。删除与上面发现的Etcd leader相关的pod:

下面咱们检查一下集群的健康状况:

failed to check the health of member 2e80f96756a54ca9 on http://etcd-0.etcd:2379: Get http://etcd-0.etcd:2379/health: dial tcp: lookup etcd-0.etcd on 10.15.240.10:53: no such host

member 2e80f96756a54ca9 is unreachable: [http://etcd-0.etcd:2379] are all unreachable

member 7fd61f3f79d97779 is healthy: got healthy result from http://etcd-1.etcd:2379

member b429c86e3cd4e077 is healthy: got healthy result from http://etcd-2.etcd:2379cluster is degraded

command terminated with exit code 5

上面的信息代表,因为失去了leader节点,集群出于degrade状态。

一旦Kubernetes经过启动新实例来响应删除的pod,Etcd集群应该就恢复过来了:

输入下面指令,咱们能够看到新的leader已经选出来了:

在咱们的例子中,etcd-1节点被选为leader

若是咱们再一次检查message键的值,会发现没有出现数据的损失:

结 论

Etcd是一种很是强大、高可用以及可靠的分布式键值存储,专门为特定用例设计。常见的例子包括存储数据哭链接细节、缓存设置、特性标记等等。它被设计成顺序一致的,所以在整个集群中每一个事件都是以相同的顺序存储。

咱们了解了如何在Rancher的帮助下用Kubernetes创建并运行etcd集群。以后,咱们可以使用一些基本的Etcd命令进行操做。为了更好的了解这个项目,键是如何组织的,如何为键设置TTLs,或者如何备份全部数据,参考官方的Etcd repo会是个不错的选择:

https://github.com/etcd-io/etcd/tree/master/Documentation

相关文章
相关标签/搜索