CoreOS 实战:剖析 etcd(2)
时间:2014-11-23 13:58 来源:linux.it.net.cn 作者:IT
3.4. 日志
3.4.1. 复制
在 raft 集群中,所有日志都必须首先提交至 leader 节点。leader 在每个 heartbeat 向 follower 同步日志,follower 在收到日志之后向 leader 反馈结果,leader 在确认日志内容正确之后将此条目提交并存储于本地磁盘。

➢ 首先有一条 uncommitted 的日志条目提交至 leader 节点。

➢ 在下一个 heartbeat,leader 将此条目复制给所有的 follower。

➢ 当大多数节点记录此条目之后,leader 节点认定此条目有效,将此条目设定为已提交并存储于本地磁盘。


➢ 在下一个 heartbeat,leader 通知所有 follower 提交这一日志条目并存储于各自的磁盘内。

3.4.2. 容错
如果由于网络的隔断,造成集群中多数的节点在一段时间内无法访问到 leader 节点。按照 raft 共识算法,没有 leader 的那一组集群将会通过选举投票出新的 leader,甚至会在两个集群内产生不一致的日志条目。在集群重新完整连通之后,原来的 leader 仍会按照 raft 共识算法从步进数更高的 leader 同步日志并将自己切换为 follower。
➢ 集群的理想状态。

➢ 网络间隔造成大多数的节点无法访问 leader 节点。

➢ 新的日志条目添加到 leader 中。

➢ leader 节点将此条日志同步至能够访问到 leader 的节点。

➢ follower 确认日志被记录,但是确认记录日志的 follower 数量没有超过集群节点的半数,leader 节点并不将此条日志存档。

➢ 在被隔断的这部分节点,在 election timeout 之后,followers 中产生 candidate 并发起选举。

➢ 多数节点接受投票之后,candidate 成为 leader。

➢ 一个日志条目被添加到新的 leader。

➢ 日志被复制给新 leader 的 follower。

➢ 多数节点确认之后,leader 将日志条目提交并存储。

➢ 在下一个 heartbeat,leader 通知 follower 各自提交并保存在本地磁盘。

➢ 经过一段时间之后,集群重新连通到一起,集群中出现两个 leader 并且存在不一致的日志条目。

➢ 新的 leader 在下一次 heartbeat timeout 时向所有的节点发送一次 heartbeat。

➢ #1 leader 在收到步进数更高的 #2 leader heartbeat 时放弃 leader 地位并切换到 follower 状态。

➢ 节点中所有未存档的日志条目都将被丢弃。

➢ 未被复制的日志条目将会被同步给所有的 follower。

通过这种方式,只要集群中有效连接的节点超过总数的一半,集群将一直以这种规则运行下去并始终确保各个节点中的数据始终一致。
4. 实现
4.1. etcd 结构

一个 etcd 节点的核心由三部分组成:
-
Raft:raft 状态机是对 raft 共识算法的实现
-
WAL:raft 日志存储
-
Storage:数据的存储与索引
WAL (Write-ahead logging),是用于向系统提供原子性和持久性的一系列技术。在使用 WAL 的系提供中,所有的修改在提交之前都要先写入 log 文件中。etcd 的 WAL 由日志存储与快照存储两部分组成,其中 Entry 负责存储具体日志的内容,而 Snapshot 负责在日志内容发生变化的时候保存 raft 的状态。WAL 会在本地磁盘的一个指定目录下分别日志条目与快照内容。
4.2. 服务
4.2.1. Clients
在默认设定下,etcd 通过主机的 2379 端口向 Client 提供服务。如下图:

每个主机上的应用程序都可以通过主机的 2379 以 HTTP + JSON 的方式向 etcd 读写数据。写入的数据会由 etcd 同步到集群的其它节点中。
4.2.2. Peers
在默认设定下,etcd 通过主机的 2380 端口在各个节点中同步 raft 状态及数据。

5. 创建
从方法上来划分,创建 etcd 集群的方式分为两种:Static (通过制定 peers 的 IP 和端口创建)与 Discovery (通过一个发现服务创建)。
Static 方式需要预先知道集群所有节点的 IP,所以适合小规模的集群或者搭建一个临时的开发与测试环境。
Discovery 方式不需要预先了解其他节点的 IP。启动时 etcd 通过访问一个 Discovery URL 来注册自己并获取其他节点的信息。这种方式通常适合将 etcd 部署在某个云服务平台或是一个 DHCP 环境中。其中 Discovery 服务可以使用 CoreOS 提供的一个公共地址 https://discovery.etcd.io/new 来申请一个 token,或者自己搭建一个这样的服务并设定一个 token。出于安全的考虑,这个 token 应该只在集群初始引导时短暂存在,因为集群建立之后将不再需要这一地址,而集群中节点的变更可以通过 etcd 运行时重构的能力来进行配置。
6. 运行
下面我们尝试使用 etcd 0.5.0 以 discovery 方式创建一个 CoreOS 集群。当然由于 etcd 0.5.0 尚未正式发布,所以我们目前还无法从官方渠道获得打包 etcd 0.5.0 的 CoreOS 镜像,但是我们可以修改引导文件,在 CoreOS 启动时将 etcd 0.5.0 下载至系统里进行配置并启动。
CoreOS 官方提供了一个使用 vagrant + virtualbox 项目,供用户在本地电脑中创建一个微型 CoreOS 集群。我们可以在这个项目的基础上进行修改来实现我们的需求。
6.1. Clone 项目到本地
-
git clone
-
https://github.com/coreos/coreos-vagrant.git
-
cd coreos-vagrant
-
cp config.rb.sample config.rb
-
cp user-data.sample user-data.sample
6.2. 通过 CoreOS 提供的公共 discovery 服务申请 token
curl https://discovery.etcd.io/new?size=3
https://discovery.etcd.io/780456e1317eb2db312b62ba1cb9a4f7
size = 3 表示这个集群节点总数为 3 个。
6.3. 修改 config.rb 文件
-
# Size of the CoreOS cluster created by Vagrant
-
$num_instances=3
将启动的 CoreOS 实例数量定为 3 个
6.4. 修改 user-data 文件
6.4.1. 修改 etcd 参数:
-
etcd:
-
discovery: https://discovery.etcd.io/780456e1317eb2db312b62ba1cb9a4f7
-
advertise-client-urls: http://$public_ipv4:2379
-
initial-advertise-peer-urls: http://$public_ipv4:2380
-
listen-client-urls: http://$public_ipv4:2379
-
listen-peer-urls: http://$public_ipv4:2380
6.4.2. 修改 etcd 服务内容
-
- name: etcd.service
-
command: start
-
content: |
-
[Unit]
-
After=network-online.target
-
Requires=network-online.target
-
-
[Service]
-
ExecStartPre=/usr/bin/wget -N -P /opt/bin https://github.com/coreos/etcd/releases/
-
download/v0.5.0-alpha.3/etcd-v0.5.0-alpha.3-linux-amd64.tar.gz
-
ExecStartPre=/usr/bin/tar -C /opt/bin -xvf /opt/bin/etcd-v0.5.0-alpha.3-linux-amd64.tar.gz
-
ExecStartPre=/usr/bin/chmod +x /opt/bin/etcd-v0.5.0-alpha.3-linux-amd64/etcd
-
ExecStart=/opt/bin/etcd-v0.5.0-alpha.3-linux-amd64/etcd
-
-
[Install]
-
WantedBy=multi-user.target
修改的部分让我们重新定制了 etcd 服务的内容。在系统启动时,先将 etcd 0.5.0 的打包文件下载至指定目录并在稍后将其启动。
6.4.3. 使用 vagrant 启动集群
-
vagrant up
稍后 vagrant 将帮助我们在 VirtualBox 中创建三个 CoreOS 实例。
6.4.4. 登录到 CoreOS
登录到其中的一个节点
-
vagrant ssh core-01
查看一下 etcd.service 的状态,输入:
-
systemctl status etcd.service
不出意外的话,可以看到其状态为 active (running)
-
etcd.service
-
Loaded: loaded (/etc/systemd/system/etcd.service; disabled)
-
Drop-In: /run/systemd/system/etcd.service.d
-
└─20-cloudinit.conf
-
Active: active (running) since Sun 2014-11-16 13:10:59 UTC; 12min ago
-
Process: 894 ExecStartPre=/usr/bin/chmod +x /opt/bin/etcd-v0.5.0-alpha.3-
-
linux-amd64/etcd (code=exited, status=0/SUCCESS)
-
Process: 890 ExecStartPre=/usr/bin/tar -C /opt/bin -xvf /opt/bin/etcd-
-
v0.5.0-alpha.3-linux-amd64.tar.gz (code=exited, status=0/SUCCESS)
-
Process: 857 ExecStartPre=/usr/bin/wget -N -P /opt/bin
-
https://github.com/coreos/etcd/releases/download/v0.5.0-alpha.3/etcd-v0.5.0
-
-alpha.3-linux-amd64.tar.gz (code=exited, status=0/SUCCESS)
-
Main PID: 896 (etcd)
-
CGroup: /system.slice/etcd.service
-
└─896 /opt/bin/etcd-v0.5.0-alpha.3-linux-amd64/etcd
6.4.5. 通过 etcdctl 查询集群状态
etcdctl 可以帮助我们查询一下集群中节点信息,输入:
-
/opt/bin/etcd-v0.5.0-alpha.3-linux-amd64/etcdctl --peers 172.17.8.101:2379 member list
启动参数 --peers 172.17.8.101:2379 表示通过本节点的 2379 端口访问 etcd 接口,用户可以根据自己的实际情况对 IP 地址进行修正。
正常情况下可看到如下输出:
-
b4f4d25ed56d7a44: name=b74c24773df147e1be8e1e35defaad38 peerURLs=
-
http://172.17.8.101:2380 clientURLs=http://172.17.8.101:2379
-
b7404cc414e7affa: name=001db0fc02184af5b293e2cb21c86a11 peerURLs=
-
http://172.17.8.102:2380 clientURLs=http://172.17.8.102:2379
-
f609956c55a6809e: name=2840dc331d224360a097b781c876c9e5 peerURLs=
-
http://172.17.8.103:2380 clientURLs=http://172.17.8.103:2379
这样,我们就在本地创建了一个基于 etcd 0.5.0 的 CoreOS 集群。
7. 预告
作为 CoreOS 及管理工具介绍的第三部分,笔者将向大家介绍 CoreOS 集群的重要管理工具 fleet ,通过 fleet 用户可以在 CoreOS 实现简单的 Orchestration 功能,敬请期待。
(责任编辑:IT)
3.4. 日志 3.4.1. 复制在 raft 集群中,所有日志都必须首先提交至 leader 节点。leader 在每个 heartbeat 向 follower 同步日志,follower 在收到日志之后向 leader 反馈结果,leader 在确认日志内容正确之后将此条目提交并存储于本地磁盘。
➢ 首先有一条 uncommitted 的日志条目提交至 leader 节点。
➢ 在下一个 heartbeat,leader 将此条目复制给所有的 follower。
➢ 当大多数节点记录此条目之后,leader 节点认定此条目有效,将此条目设定为已提交并存储于本地磁盘。
➢ 在下一个 heartbeat,leader 通知所有 follower 提交这一日志条目并存储于各自的磁盘内。
3.4.2. 容错如果由于网络的隔断,造成集群中多数的节点在一段时间内无法访问到 leader 节点。按照 raft 共识算法,没有 leader 的那一组集群将会通过选举投票出新的 leader,甚至会在两个集群内产生不一致的日志条目。在集群重新完整连通之后,原来的 leader 仍会按照 raft 共识算法从步进数更高的 leader 同步日志并将自己切换为 follower。 ➢ 集群的理想状态。
➢ 网络间隔造成大多数的节点无法访问 leader 节点。
➢ 新的日志条目添加到 leader 中。
➢ leader 节点将此条日志同步至能够访问到 leader 的节点。
➢ follower 确认日志被记录,但是确认记录日志的 follower 数量没有超过集群节点的半数,leader 节点并不将此条日志存档。
➢ 在被隔断的这部分节点,在 election timeout 之后,followers 中产生 candidate 并发起选举。
➢ 多数节点接受投票之后,candidate 成为 leader。
➢ 一个日志条目被添加到新的 leader。
➢ 日志被复制给新 leader 的 follower。
➢ 多数节点确认之后,leader 将日志条目提交并存储。
➢ 在下一个 heartbeat,leader 通知 follower 各自提交并保存在本地磁盘。
➢ 经过一段时间之后,集群重新连通到一起,集群中出现两个 leader 并且存在不一致的日志条目。
➢ 新的 leader 在下一次 heartbeat timeout 时向所有的节点发送一次 heartbeat。
➢ #1 leader 在收到步进数更高的 #2 leader heartbeat 时放弃 leader 地位并切换到 follower 状态。
➢ 节点中所有未存档的日志条目都将被丢弃。
➢ 未被复制的日志条目将会被同步给所有的 follower。
通过这种方式,只要集群中有效连接的节点超过总数的一半,集群将一直以这种规则运行下去并始终确保各个节点中的数据始终一致。 4. 实现4.1. etcd 结构
一个 etcd 节点的核心由三部分组成:
WAL (Write-ahead logging),是用于向系统提供原子性和持久性的一系列技术。在使用 WAL 的系提供中,所有的修改在提交之前都要先写入 log 文件中。etcd 的 WAL 由日志存储与快照存储两部分组成,其中 Entry 负责存储具体日志的内容,而 Snapshot 负责在日志内容发生变化的时候保存 raft 的状态。WAL 会在本地磁盘的一个指定目录下分别日志条目与快照内容。 4.2. 服务4.2.1. Clients在默认设定下,etcd 通过主机的 2379 端口向 Client 提供服务。如下图:
每个主机上的应用程序都可以通过主机的 2379 以 HTTP + JSON 的方式向 etcd 读写数据。写入的数据会由 etcd 同步到集群的其它节点中。 4.2.2. Peers在默认设定下,etcd 通过主机的 2380 端口在各个节点中同步 raft 状态及数据。
5. 创建从方法上来划分,创建 etcd 集群的方式分为两种:Static (通过制定 peers 的 IP 和端口创建)与 Discovery (通过一个发现服务创建)。 Static 方式需要预先知道集群所有节点的 IP,所以适合小规模的集群或者搭建一个临时的开发与测试环境。 Discovery 方式不需要预先了解其他节点的 IP。启动时 etcd 通过访问一个 Discovery URL 来注册自己并获取其他节点的信息。这种方式通常适合将 etcd 部署在某个云服务平台或是一个 DHCP 环境中。其中 Discovery 服务可以使用 CoreOS 提供的一个公共地址 https://discovery.etcd.io/new 来申请一个 token,或者自己搭建一个这样的服务并设定一个 token。出于安全的考虑,这个 token 应该只在集群初始引导时短暂存在,因为集群建立之后将不再需要这一地址,而集群中节点的变更可以通过 etcd 运行时重构的能力来进行配置。 6. 运行下面我们尝试使用 etcd 0.5.0 以 discovery 方式创建一个 CoreOS 集群。当然由于 etcd 0.5.0 尚未正式发布,所以我们目前还无法从官方渠道获得打包 etcd 0.5.0 的 CoreOS 镜像,但是我们可以修改引导文件,在 CoreOS 启动时将 etcd 0.5.0 下载至系统里进行配置并启动。 CoreOS 官方提供了一个使用 vagrant + virtualbox 项目,供用户在本地电脑中创建一个微型 CoreOS 集群。我们可以在这个项目的基础上进行修改来实现我们的需求。 6.1. Clone 项目到本地
6.2. 通过 CoreOS 提供的公共 discovery 服务申请 tokencurl https://discovery.etcd.io/new?size=3 https://discovery.etcd.io/780456e1317eb2db312b62ba1cb9a4f7 size = 3 表示这个集群节点总数为 3 个。 6.3. 修改 config.rb 文件
将启动的 CoreOS 实例数量定为 3 个 6.4. 修改 user-data 文件6.4.1. 修改 etcd 参数:
6.4.2. 修改 etcd 服务内容
修改的部分让我们重新定制了 etcd 服务的内容。在系统启动时,先将 etcd 0.5.0 的打包文件下载至指定目录并在稍后将其启动。 6.4.3. 使用 vagrant 启动集群
稍后 vagrant 将帮助我们在 VirtualBox 中创建三个 CoreOS 实例。 6.4.4. 登录到 CoreOS登录到其中的一个节点
查看一下 etcd.service 的状态,输入:
不出意外的话,可以看到其状态为 active (running)
6.4.5. 通过 etcdctl 查询集群状态etcdctl 可以帮助我们查询一下集群中节点信息,输入:
启动参数 --peers 172.17.8.101:2379 表示通过本节点的 2379 端口访问 etcd 接口,用户可以根据自己的实际情况对 IP 地址进行修正。 正常情况下可看到如下输出:
这样,我们就在本地创建了一个基于 etcd 0.5.0 的 CoreOS 集群。 7. 预告
作为 CoreOS 及管理工具介绍的第三部分,笔者将向大家介绍 CoreOS 集群的重要管理工具 fleet ,通过 fleet 用户可以在 CoreOS 实现简单的 Orchestration 功能,敬请期待。 |