关于raft模式下的orderer新增,官网给了大概流程
重新配置
Raft 排序节点支持动态地(意思是,当通道正在使用时)添加和移除节点,只是一次只能添加或移除一个节点。在你尝试重新配置之前,请注意你的集群必须处于可以承受维护的状态,并且能够获得共识。举个最糟糕的例子,如果你有 3 个节点,然后 2 个节点宕机了,你就不能通过配置你的raft集群来移除节点。同样地,如果你在一个有着3个节点的通道内有1个宕机的节点,那么不应该尝试替换证书,因为这会造成二次错误。*作为一个准则,除非所有共识者都在线且健康,你永远都不应该尝试对 Raft 共识者做配置变更,如添加或删除共识者,或替换共识者的证书等。
如果你决定修改这些参数,我们建议只在维护周期内进行尝试。修改配置的问题绝大多数都发生在只有少量节点的集群中且有一个节点宕机之时。比如,如果你有三个节点的共识者,其中有一个宕机,这意味着你只有两个节点存活。如果你在这个状态下将集群扩展到 4 个节点,你仍然只有 2 个节点存活,这无法达到法定人数。第四个节点不能上线,因为节点只能加入到运作中的集群(集群总大小是 1 或 2的情况)。
因此,在扩展一个(只有两个节点存活的)三节点集群为四节点时,你完全会被卡住,直到原先离线的节点恢复。
添加一个新节点到 Raft 集群需要通过以下步骤完成:
- 通过一个通道配置更新交易将新节点的 TLS 证书添加到通道中。注意:新节点在加入一个或更多应用通道前,必须先加入到系统通道。
- 从一个排序节点中获取最新的系统通道配置区块,这是系统通道的一部分。
- 通过验证配置区块是否包含(即将)加入的节点证书来确保此节点是系统通道的一部分。
- 使用在
General.BootstrapFile
配置参数中指定的配置区块路径启动新的 Raft 节点。 - 等待 Raft 节点从已有节点复制其证书所加入的通道中的区块。在这一步完成后,节点开始服务于通道。
- 将新增的 Raft 节点端点加入所有通道的配置。
简单的说,可以将已经运行(且已经加入某些通道)的节点在运行时加入到通道中。要做到这点,只需添加该节点的证书到通道的通道配置中。节点会自动检测其加入到新的通道(默认值是 5 分钟,但如果你想让节点更快检测新通道,可以重启节点),然后从通道中的 orderer 拉取通道区块,最后为该链启动 Raft 实例。
在成功完成以上步骤后,就能更新通道配置以纳入新 Raft orderer 的端点。
#查看这个介绍,我们可以感觉到官方在介绍这一部分时只给了大概流程,仅看这个的话很难操作。这是因为这类操作,官方在【动态新增组织】中进行了比较详见的流程介绍,主要区别在于
#1.在将orderer节点添加到指定应用通道前,需要先将orderer节点添加到系统通道中。
#2.修改配置区由peer修改为orderer。这部分需要自己寻找
所以,参考官方介绍,可以设计动态添加流程如下
动态添加流程
环境配置
设备已有3orderer节点,1个peer节点
生成orderer证书
fabric提供了两种生成证书的方式fabric-ca生成和cryptogen工具生成,我们使用cryptogen工具生成
修改配置文件
证书生成文件 crypto-config.yaml 新增orderer4的配置
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: Orderer
Domain: example.com.local
# ---------------------------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer1
- Hostname: orderer2
- Hostname: orderer3
- Hostname: orderer4 #新增
生成证书
fabric原生命令
cryptogen extend --input crypto-config --config ./crypto-config.yaml
allin改造后
#allin改造中使用证书合并模式。复制orderer1的证书,修改路径及证书名称
准备包含待更新数据的通道配置文件
方案一
修改configtx.yaml文件,新增orderer4的相关信息 这个流程主要是参照动态添加组织的流程。通过fabric自带命令自动生成json文件,自动化较高
SampleMultiNodeEtcdRaft:
<<: *ChannelDefaults
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
OrdererType: etcdraft
EtcdRaft:
Consenters:
- Host: orderer1.example.com.local
Port: 7050
ClientTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer1.example.com.local/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer1.example.com.local/tls/server.crt
- Host: orderer2.example.com.local
Port: 8050
ClientTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer2.example.com.local/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer2.example.com.local/tls/server.crt
- Host: orderer3.example.com.local
Port: 9050
ClientTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer3.example.com.local/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer3.example.com.local/tls/server.crt
- Host: orderer4.example.com.local #新增
Port: 10050 #新增
ClientTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer4.example.com.local/tls/server.crt #新增
ServerTLSCert: crypto-config/ordererOrganizations/example.com.local/orderers/orderer4.example.com.local/tls/server.crt #新增
Addresses:
- orderer1.example.com.local:7050
- orderer2.example.com.local:8050
- orderer3.example.com.local:9050
- orderer4.example.com.local:10050 #新增
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Application:
<<: *ApplicationDefaults
Organizations:
- <<: *Org1
Consortiums:
SampleConsortium:
Organizations:
- *Org1
修改完测试发现fabric提供的命令只支持组织级别的选取,但是我们需要修改的部分集中在Profiles模块无法使用。
configtxgen -configPath $FABRIC_CFG_PATH/configs -printOrg ${SET_MSP_ID} >$FABRIC_CFG_PATH/configs/${SET_PEER_ORG_NAME}.json
-printOrg string 将组织的定义打印为JSON。(对于手动向通道添加组织非常有用)
方案二
不提前准备准备添加的数据,在更新的时候,直接生成然后更新到对应文件中
获取当前的通道配置文件
设置环境变量
export FABRIC_CFG_PATH=/root/raft/configs
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_MSPCONFIGPATH=${FABRIC_CFG_PATH}/crypto-config/peerOrganizations/org1.example.local/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org1.example.local:7051
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_TLS_ROOTCERT_FILE=${FABRIC_CFG_PATH}/crypto-config/peerOrganizations/org1.example.local/peers/peer1.org1.example.local/tls/ca.crt
export CORE_PEER_TLS_KEY_FILE=${FABRIC_CFG_PATH}/crypto-config/peerOrganizations/org1.example.local/peers/peer1.org1.example.local/tls/server.key
export CORE_PEER_TLS_CERT_FILE=${FABRIC_CFG_PATH}/crypto-config/peerOrganizations/org1.example.local/peers/peer1.org1.example.local/tls/server.crt
export ordererCa=${FABRIC_CFG_PATH}/crypto-config/ordererOrganizations/example.local/orderers/orderer1.example.local/msp/tlscacerts/tlsca.example.local-cert.pem
注意:新节点在加入一个或更多应用通道前,必须先加入到#系统通道 即syschannel
所以在文档中以syschannel为例,讲解流程。在加入应用通道是,需要经syschannel 更换为对应应用通道的名称
拉取最新配置块文件
config_block.pb
peer channel fetch config $FABRIC_CFG_PATH/config_block.pb -o orderer1.example.com:7050 -c syschannel --tls --cafile $ordererCa
提取并转换格式
从config_block.pb中提取有效的数据,并转换成可编辑json格式
configtxlator proto_decode --input $FABRIC_CFG_PATH/config_block.pb --type common.Block | jq .data.data[0].payload.data.config > $FABRIC_CFG_PATH/config.json
修改orderer配置
在生成的json文件里,在方案一里的对应新增位置,将orderer4的信息(证书相关路径要修改成证书文件本身(base64)格式)写入进去。得到新的json文件 config_updated.json
//此处应有图,脚本编写完成,实际执行成功后补
构建新配置
#把前后的两个json文件重新转换回pb类型文件
configtxlator proto_encode --input $FABRIC_CFG_PATH/config.json --type common.Config > $FABRIC_CFG_PATH/config_block_origin.pb
configtxlator proto_encode --input $FABRIC_CFG_PATH/config_updated.json --type common.Config > $FABRIC_CFG_PATH/config_block_updated.pb
#比较前后两个pb文件的差异,得到改动部分
configtxlator compute_update --channel_id byfn-sys-channel --original $FABRIC_CFG_PATH/config_block_origin.pb --updated $FABRIC_CFG_PATH/config_block_updated.pb > $FABRIC_CFG_PATH/config_diff.pb
#把配置变化部分转化为json文件
configtxlator proto_decode --input $FABRIC_CFG_PATH/config_diff.pb --type common.ConfigUpdate > $FABRIC_CFG_PATH/config_diff.json
#为上述json文件添加头部信息(Header),封装成一个完整的config update请求
echo '{"payload":{"header":{"channel_header":{"channel_id":"byfn-sys-channel", "type":2}},"data":{"config_update":'$(cat $FABRIC_CFG_PATH/config_diff.json)'}}}' | jq . > $FABRIC_CFG_PATH/config_diff_envelope.json
#把封装好的json文件转换回pb格式文件
configtxlator proto_encode --input $FABRIC_CFG_PATH/config_diff_envelope.json --type common.Envelope > $FABRIC_CFG_PATH/config_diff_envelope.pb
签名
peer channel signconfigtx -f $FABRIC_CFG_PATH/config_diff_envelope.pb
提交更新请求
peer channel update -f $FABRIC_CFG_PATH/config_diff_envelope.pb -c byfn-sys-channel -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA
完成
系统通道加入完成,应修改通道名称为(你想加入的)应用通道名称,重新执行上诉步骤。
启动orderer4节点
启动orderer节点流程与原启动方式无太大区别,但是有几个需要注意和解决的点
1.新节点的hosts更新
2.peer的客户端维护的orderer列表里,需要把新增的orderer更新进去
查看日志,如果正常启动,且开始同步(所有已加入的应用通道的)区块,则代表全部流程正常完成
参考文档
官方文档重新配置RAFT:https://hyperledger-fabric.readthedocs.io/en/latest/raft_configuration.html#reconfiguration
官方文档动态新增组织:https://hyperledger-fabric.readthedocs.io/en/latest/channel_update_tutorial.html
Fabric 1.4.2 动态添加orderer节点:https://www.jianshu.com/p/49a915bed152
Fabric动态配置Raft节点:https://www.cnblogs.com/cbkj-xd/p/12123860.html
动态新增orderer流程设计
在产品的边界里,我们有需要遵循的设定,在进行此次设计中需要遵循的有一下几点
1、每台机器上的orderer节点不允许超过3个。
2、sdk(即peer的客户端),需要动态的更新最新的orderer列表,以便可发送消息给最新的orderer节点
3、私钥不出设备
在遵循上述限定的前提下,进行流程设计。
执行环境
在预研过程中我们发现决定流程执行环境的主要因素,证书生成和签名权限都指向orderer组织Admin所在节点。
签名权限
虽然我们可以通过修改权限策略的方式,为所有orderer成员赋予Admin权限。但是我们无法将orderer的私钥上链分享给一个没有orderer节点的设备。
所有,我们的执行对象应该是
1.如果不将Admin权限下放,执行对象应该是orderer组织Admin在的设备,即联盟的第一台设备。
2.如果将权限下放给组织成员,那执行对象也至少要是一个已存在orderer节点的设备,而不是任意一台机器。
这就要求我们在链上维护一个可用orderer列表,并且设定一个在何时应该选择哪一个orderer所在设备作为执行环境的规则。
证书生成
因为私钥不出设备的前提,在新设备上没有orderer节点的情况下。直接共用已存在的orderer证书变成了不可能。
在这种情况下,只能使用csr去orderer组织ca申请证书的方式在新设备上提前准备orderer私钥及证书。
这样的话在流程中必然要预留生成证书的步骤,无法向用户解释两种流程的差异(orderer用户都感知不到)。
且当前产品主要适配证书方案为csr-ca-cert方案,所以即使在已有orderer的设备上进行orderer新增,也不再选用证书共用模式。
投票
参考配置中心动态添加节点的设计,在组织内成员加入的时候。只需要组织内管理员节点同意一次皆可。
这样的话,在非动态添加新组织orderer的情况下,所选择的执行设备是不投票可以直接进行签名操作的。考虑orderer尽量不对用户开放概念,在此情况下,暂不添加投票流程。
sdk更新
为了新加入节点可以拿到orderer所在设备的IP,以便设置自己的hosts。在第一台设备初始化网络完成后,就进行了orderer列表上链。上链数据为设备ip和orderer1的ca/tlsca证书(创建通道用)。所以当新orderer完成操作后,我们可以通过很简单的方式知道当前那些设备是需要进行更新操作的,向列表里的ip发送通知,对应设备收到通知后去链上获取最新的orderer列表。更新自己的hosts和sdk里orderer用户列表。
要注意的是,更新sdk用户列表也应是动态的,在不影响正常使用的前提下进行