创建多节点 Fabirc 集群
Hyperledger Fabric 的 fabric-samples/first-network
是在单机上运行的。本章描述如何将其部署到多台 VM 上。
假设有三台VM:
- hostname:u1601 ip:192.168.16.101
- hostname:u1602 ip:192.168.16.102
- hostname:u1603 ip:192.168.16.103
计划将 u1603 当 orderer 节点,另两台当peer节点。
首先,按 Hyperledger Fabric Samples 的描述,在 3 台 VM 上都创建 Fabirc 运行环境,包括安装必要的二进制包,部署 docker 引擎和 docker-compose,部署 golang 环境,下载 Fabric 相关 docker 镜像等。
提示一个常用的 docker 命令,用于将所有容器删除,可用于peer或orderer的重启:
$ docker rm -f $(docker ps -aq)
生成密钥文件并复制(u1601)
登录u1601。首先进行环境清理,停止和删除现有docker容器,删除原有密钥文件。方法是:
$ cd /opt/fabric-samples/first-network
$ ./byfn.sh -m down
下面的命令生成密钥文件。密钥文件输出到了crypto-config
目录下。
$ ../bin/cryptogen generate --config=./crypto-config.yaml
生成的密钥文件分别属于排序服务管理员(实际上是全局管理员)、两个组织管理员、4个peer管理员以及每个peer各一个的一般用户(参考)。
按正规要求,排序服务管理员的私钥文件应复制到u1603;org1组织的peer1节点的私钥文件复制到u1602。由于org1组织的peer0节点就是u1601,所以不用复制。因为本章只是验证Fabric-samples分布式部署,所以加密材料只是简单复制到了u1602和u1603,并没有删除应当保密的管理员私钥。
$ scp -r ./crypto-config root@u1602:/opt/fabric-samples/first-network/
$ scp -r ./crypto-config root@u1603:/opt/fabric-samples/first-network/
启动排序服务
要启动排序服务,首先要生成系统创世区块,然后编辑排序服务的docker-compose文件并启动。
$ ssh root@u1603
$ cd /opt/fabric-samples/first-network
生成系统通道创世区块
下面的命令生成系统通道的创世区块。文件输出到channel-artifacts
目录下。
$ export FABRIC_CFG_PATH=$PWD
$ ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
编辑 docker-compose 配置文件
排序服务的docker-compose配置文件可以在原生docker-compose-cli.yaml
上修改。
$ cp docker-compose-cli.yaml orderer.yaml
编辑orderer.yaml,删除大部分内容,只留下orderer相关的:
version: '2'
services:
orderer.example.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.example.com
container_name: orderer.example.com
同原生定义的排序服务docker-compose配置文件相比,仅仅删除了byfn
网络。这意味着,排序服务容器与其他容器的通信不再走docker的虚拟网络,而是通过宿主机网络(至于是bridge还是host模式,不清楚)。
启动 orderer 节点
$ docker-compose -f orderer.yaml up -d
(如果启动orderer时不加-d
参数,屏幕会一直输出orderer容器的日志。)
准备peer0节点
使用u1601充当org1组织的peer0节点。
$ ssh root@u1601
$ cd /opt/fabric-samples/basic-network
生成事务文件
首先,生成创建应用通道的事务文件:
$ export CHANNEL_NAME=mychannel
$ ../bin/configtxgen -profile TwoOrgsChannel \
-outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
然后,生成“将peer0设置Org1的锚点peer”的事务文件:
$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate \
./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
编辑 docker-compose 配置文件
计划在u1601上运行两个容器,peer0.org1.example.com和cli。前者是peer容器,后者是管理员用的客户端工具。在原生docker-compose-cli.yaml
配置文件的基础上修改。
$ cp docker-compose-cli.yaml cli.yaml
编辑cli.yaml,修改成下面的样子:
version: '2'
networks:
byfn:
services:
peer0.org1.example.com:
container_name: peer0.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org1.example.com
extra_hosts:
- "orderer.example.com:192.168.16.103"
# - "peer1.org1.example.com:192.168.16.102"
networks:
- byfn
cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_default
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY} ${LANG}; sleep $TIMEOUT'
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- peer0.org1.example.com
extra_hosts:
- "orderer.example.com:192.168.16.103"
networks:
- byfn
同原来的docker-compose-cli.yaml
相比,首先多了一个extra_hosts
定义。extra_hosts
的值会自动加入到容器的/etc/hosts
文件中,以便根据hostname找到位于其他VM的服务,如找到排序服务(orderer)。
(byfn
这个docker虚拟网络也是需要的。如果不定义,会导致链码实例化报错。用docker network ls
命令可以看到byfn
被自动命名为net_byfn
。而peer服务是从base/docker-compose-base.yaml
继承来的,其中有个环境变量的定义CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn
,在运行时这个环境变量的值应该是net_byfn
。)
(如果peer0.org1.example.com
服务中不定义orderer的extra_hosts
,会导致链码无法部署。)
启动 peer 容器并初始化
使用cli.yaml
启动peer0:
$ TIMEOUT=10000 CHANNEL_NAME=$CHANNEL_NAME docker-compose -f cli.yaml up -d
用docker ps
命令可以看到启动了两个容器:peer0.org1.example.com
和cli
。
创建通道和将 peer0 加入通道
还记得之前生成的两个事务文件channel.tx
和Org1MSPanchors.tx
吗?下面利用这两个事务文件对Fabric进行初始化。
进入cli容器,并查看4个环境变量,这四个变量反应了当前cli正在以peer0的身份运行:
$ docker exec -it cli bash
$ echo $CORE_PEER_MSPCONFIGPATH && echo $CORE_PEER_ADDRESS && echo $CORE_PEER_LOCALMSPID && echo $CORE_PEER_TLS_ROOTCERT_FILE
(根据fabric目前版本的通道权限策略,谁创建谁就是通道管理员。所以mychannel
的管理员应为peer0的管理员) 为创建通道,之前需要创建通道需要的其他设置环境变量:
$ export CHANNEL_NAME=mychannel && export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
$ peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f \
./channel-artifacts/channel.tx --tls --cafile $ORDERER_CA
上面命令将包含在channel-artifacts/channel.tx
中的配置信息发送给orderer,并在当前目录下生成新通道(mychannel
)的创世区块文件mychannel.block
。
通道创建成功后,需要将当前peer(即peer0)加入到通道mychannel
:
$ peer channel join -b mychannel.block
如果你弄丢了mychannel.block
(例如你重启了peer0容器),还可以用下列命令重新获取:
$ peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
改变锚点 peer 定义
回忆一下,工件Org1MSPanchors.tx
是之前生成的。下面利用这个Org1MSPanchors.tx
对通道定义进行变更,将peer0.org1.example.com定义为Org1的锚点peer。
$ peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile $ORDERER_CA
(当初犯过一个错误,现在明白了:工件属于peer,与orderer无关。工件可以视为peer对配置进行修改的一个参数。)
链码安装、实例化和使用
链码安装
将fabric-samples
自带的例子链码安装到peer0(u1601)上:
$ peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
如果不配置peer0对orderer的extra_hosts
依赖,上面的链码安装会失败。
链码实例化
下面是对将链码在peer0(u1601)上实例化:
$ peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
在实测中一开始没有定义byfn
这个网络,导致了链码实例化失败。
链码使用
查询:
$ peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
Query Result: 100
调用(即a减少10,b增加10):
$ peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
Chaincode invoke successful. result: status:200
重新查询一下a的值:
$ peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
Query Result: 90
建立 peer1(u1602)
在u1602上部署org1的第二个peer节点,即peer1。
首先,从u1603(排序服务所在节点)上将加密材料复制过来:
$ ssh root@u1602
$ cd /opt/fabric-samples/first-network
$ scp -r root@u1603:/opt/fabric-samples/first-network/crypto-config .
$ scp root@u1601:/opt/fabric-samples/first-network/cli.yaml .
上面将peer0节点的docker-compose配置文件cli.yaml
也复制过来了。
对cli.yaml
进行适当的编辑,成下面的样子:
version: '2'
networks:
byfn:
services:
peer1.org1.example.com:
container_name: peer1.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org1.example.com
extra_hosts:
- "orderer.example.com:192.168.16.103"
- "peer0.org1.example.com:192.168.16.101"
networks:
- byfn
cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer1.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY} ${LANG}; sleep $TIMEOUT'
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- peer1.org1.example.com
extra_hosts:
- "orderer.example.com:192.168.16.103"
networks:
- byfn
另外还需要修改u1602节点的first-network/base/docker-compose-base.yaml
文件,原来peer1的暴露端口是8051,现在改成7051:
peer1.org1.example.com:
(略)
ports:
- 7051:7051
- 7053:7053
(extra_hosts: - "peer0.org1.example.com:192.168.16.101"
这一条必须要,否则会报错) 启动容器::
$ TIMEOUT=10000 CHANNEL_NAME=mychannel docker-compose -f cli.yaml up -d
将 peer1 加入通道
peer1的操作同peer0相比就比较简单了。它不是组织org1
在通道mychannel
的锚peer,仅需要加入通道即可。
$ docker exec -it cli bash
$ export CHANNEL_NAME=mychannel && export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
$ peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
$ peer channel join -b mychannel.block
peer1 链码测试
链码安装
将fabric-samples
自带的例子链码安装到peer1(u1602)上:
$ peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
链码查询
对于通道中的同一组织的新peer,链码不用实例化直接调用(原理不明):
$ peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
Query Result: 90
Org3 及其 peer 加入网络
在节计划启用一个新的虚拟机u1604。在这个虚拟机中将部署org3的一个peer:peer0.org3.example.com
。
在开始本节前,请先阅读重新配置首个网络(First-Network)。本节将遵循这篇文章的步骤,将Org3添加到系统通道,并将Org3的peer0节点加入应用通道mychannel
中。 在准备阶段,需要生成Org3的加密材料和事务文件。准备阶段将在u1601上进行,等完成后,再把加密材料和事务文件复制到u1604。
为 Org3 准备加密材料和事务文件
首先,生成加密材料。
$ ssh root@u1601
$ cd /opt/fabric-samples/first-network/org3-artifacts
$ ../../bin/cryptogen generate --config=./org3-crypto.yaml
$ export FABRIC_CFG_PATH=$PWD && ../../bin/configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json
$ cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/
然后进入u1601的cli容器。
$ docker exec -it cli bash
$ apt update && apt install jq
$ configtxlator start &
$ CONFIGTXLATOR_URL=http://127.0.0.1:7059
$ export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel
$ peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
$ curl -X POST --data-binary @config_block.pb "$CONFIGTXLATOR_URL/protolator/decode/common.Block" | jq . > config_block.json
$ jq .data.data[0].payload.data.config config_block.json > config.json
$ jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1] } } } }}' config.json ./channel-artifacts/org3.json >& updated_config.json
$ curl -X POST --data-binary @config.json "$CONFIGTXLATOR_URL/protolator/encode/common.Config" > config.pb
$ curl -X POST --data-binary @updated_config.json "$CONFIGTXLATOR_URL/protolator/encode/common.Config" > updated_config.pb
$ curl -X POST -F channel=$CHANNEL_NAME -F "original=@config.pb" -F "updated=@updated_config.pb" "${CONFIGTXLATOR_URL}/configtxlator/compute/update-from-configs" > org3_update.pb
$ curl -X POST --data-binary @org3_update.pb "$CONFIGTXLATOR_URL/protolator/decode/common.ConfigUpdate" | jq . > org3_update.json
$ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2 } },"data":{"config_update":'$(cat org3_update.json)' } }}' | jq . > org3_update_in_envelope.json
$ curl -X POST --data-binary @org3_update_in_envelope.json "$CONFIGTXLATOR_URL/protolator/encode/common.Envelope" > org3_update_in_envelope.pb
$ peer channel signconfigtx -f org3_update_in_envelope.pb
$ peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
关于上述操作的解释,请参阅重新配置首个网络(First-Network)。
这时,Org3的配置信息已经进入了系统通道的配置中。
下面该到u1604虚拟机去启动Org3的peer了。
为 Org3 准备 docker-compose 配置
从u1601将Org3的加密材料复制到u1604:
$ ssh root@u1604
$ cd /opt/fabric-samples/first-network
$ scp -r root@u1601:/opt/fabric-samples/first-network/org3-artifacts .
编辑BYFN自带的Org3的docker-compose配置文件docker-compose-org3.yaml
为以下内容:
version: '2'
networks:
byfn:
services:
peer0.org3.example.com:
container_name: peer0.org3.example.com
extends:
file: base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org3.example.com
- CORE_PEER_ADDRESS=peer0.org3.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:7051
- CORE_PEER_LOCALMSPID=Org3MSP
volumes:
- /var/run/:/host/var/run/
- ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp
- ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls
ports:
- 7051:7051
- 7053:7053
extra_hosts:
- "peer0.org1.example.com:192.168.16.101"
- "peer1.org1.example.com:192.168.16.102"
- "orderer.example.com:192.168.16.103"
networks:
- byfn
Org3cli:
container_name: Org3cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=Org3cli
- CORE_PEER_ADDRESS=peer0.org3.example.com:7051
- CORE_PEER_LOCALMSPID=Org3MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash -c 'sleep 10000'
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./org3-artifacts/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
depends_on:
- peer0.org3.example.com
# - peer1.org3.example.com
extra_hosts:
- "orderer.example.com:192.168.16.103"
networks:
- byfn
启动Org3的容器:
$ docker-compose -f docker-compose-org3.yaml up -d
进入Org3cli容器:
$ docker exec -it Org3cli bash
下面的操作分别是设置环境变量、获取mychannel
的创世区块、将当前peer(peer0.org3.example.com
)加入到mychannel
:
$ export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel
$ peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
$ peer channel join -b mychannel.block
安装链码和升级背书策略
在peer0.org3.example.com
(u1604)上安装链码mycc
,指定版本号为2.0是为了升级背书策略。
$ peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
回到u1601。由于通道mychannel
是u1601上的peer0创建的,peer0的管理员就是通道的管理员,所以升级链码的操作应在u1601上进行。
$ ssh root@u1601
$ docker exec -it cli bash
$ peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
$ peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "OR ('Org1MSP.member','Org3MSP.member')"
在 u1601 的 cli 容器中升级链码时,注意 export 上面的环境变量(如 $ORDERER_CA
)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论