一、准备工作

1.1环境准备:

首先要安装好go、docker、docker compose等。具体请参考前文Hyperledger Fabric V1.0 在Ubuntu16.04+中的环境搭建

1.2单机运行4+1 Fabric实例,确保脚本和镜像正常:

然后需要确保每台机子上e2e__cli的单机环境能跑起来。
进入e2e_cli文件夹,运行

./network_setup.sh up

这个命令可以在本机启动4+1的Fabric网络并且进行测试,跑Example02这个ChainCode。我们可以看到每一步的操作,最后确认单机没有问题。确认我们的镜像和脚本都是正常的,我们就可以关闭Fabric网络,继续我们的多机Fabric网络设置工作。关闭Fabric命令:

./network_setup.sh down

注意:测试完单机一定要关闭,否则docker容器等会有残留,影响下一步工作。
具体请参考前文单机部署e2e_cli

e2e_cli架构是4Peer+1Orderer的架构,5台主机分别是orderer.example.com、peer0.org1.example.com、peer1.org1.example.com、peer0.org2.example.com、peer1.org2.example.com。但是博主只有三台主机,因此精简为

角色id
orderer.example.com192.168.3.221
peer0.org1.example.com192.168.3.222
peer1.org1.example.com192.168.3.223

在Fabric的源码中,提供了单机部署4Peer+1Orderer的示例,在Example/e2e_cli文件夹中。我们可以在其中一台机器上运行单机的Fabric实例,确认无误后,在该机器上,生成公私钥,修改该机器中的Docker-compose配置文件,然后把这些文件分发给另外4台机器。我们就以orderer.example.com这台机器为例。

二、生成公私钥、证书、创世区块等

2.1 orderer.example.com上生成公私钥、证书、创世区块等

方法一:直接通过系统脚本一键生成
公私钥和证书是用于Server和Server之间的安全通信,另外要创建Channel并让其他节点加入Channel就需要创世区块,这些必备文件都可以一个命令生成,官方已经给出了脚本:

./generateArtifacts.sh mychannel

在三台服务器分别运行这个命令后,系统会创建channel-artifacts文件夹,里面包含了mychannel这个通道相关的文件,另外还有一个crypto-config文件夹,里面包含了各个节点的公私钥和证书的信息。
本人采取的是这种方式,比较简单快捷。
方法二:手动一步步的生成
其实手动的步骤只是把generateArtifacts.sh这个脚本中的步骤拆分来,不过这样能对整个业务逻辑更熟悉
1 编译生成cryptogen

make -C ../.. release

2 配置crypto-config.yaml
这个暂时不用配置,默认就行。
3 生成证书

../../release/linux-amd64/bin/cryptogen generate --config=./crypto-config.yaml

代码执行后会在当前目录生成crypto-config目录,里面含有crypto-config.yaml刚刚配置好的组织及成员证书
4 编译生成configtxgen

make -C ../.. release

5 配置configtx.yaml
官方提供的examples/e2e_cli/configtx.yaml这个文件里面配置了由2个Org参与的Orderer共识配置TwoOrgsOrdererGenesis,以及由2个Org参与的Channel配置:TwoOrgsChannel。Orderer可以设置共识的算法是Solo还是Kafka,以及共识时区块大小,超时时间等,我们使用默认值即可,不用更改。而Peer节点的配置包含了MSP的配置,锚节点的配置。如果我们有更多的Org,或者有更多的Channel,那么就可以根据模板进行对应的修改。
6 生成创世区块

../../release/linux-amd64/bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

执行后会生成genesis.block区块并保存到本地channel-artifacts文件夹中
7 生成Channel配置区块

../../release/linux-amd64/bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel

8 更新锚节点

../../release/linux-amd64/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
../../release/linux-amd64/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $mychannel -asOrg Org2MSP

最终,我们在channel-artifacts文件夹中,应该是能够看到4个文件。

channel-artifacts/
├── channel.tx
├── genesis.block
├── Org1MSPanchors.tx
└── Org2MSPanchors.tx

2.2 分发配置文件

前面的操作,都是在orderer.example.com上完成的,接下来我们需要将这些文件分发到另外2台服务器上(注意:一定要复制,三台机子上的文件必须一样,不能分别由generateArtifacts.sh生成,否则会报错!)。Linux之间的文件传输,我们可以使用scp命令。
首先登录peer0.org1.example.com,退回到examples文件夹,修改本地的e2e_cli文件夹的权限使之可写入(注意:否则进行下一步拷贝的时候SCP命令会报Permission denied):

chmod 777 e2e_cli

然后再登录到orderer服务器上,将e2e_cli文件夹下的channel-artifacts和crypto-config文件夹通过scp命令传到peer0.org1.example.com(192.168.3.222)上

scp -r channel-artifacts crypto-config fabric-a@192.168.3.222:/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli

peer1.org1.example.com同理。

三、更改docker-compose 配置文件

3.1 配置docker-compose-orderer

进入Orderer服务器(192.168.3.221),e2e_cli中提供了多个yaml文件,我们可以基于docker-compose-cli.yaml文件创建:

cp docker-compose-cli.yaml docker-compose-orderer.yaml

orderer服务器上我们只需要保留order设置,其他peer和cli设置都可以删除。orderer可以不设置extra_hosts。修改后的配置如下:


   # Copyright IBM Corp. All Rights Reserved.
   #
   # SPDX-License-Identifier: Apache-2.0
   #

   version: '2'

   services:

    orderer.example.com:
      extends:
        file:   base/docker-compose-base.yaml
        service: orderer.example.com
      container_name: orderer.example.com
3.2 配置docker-compose-peer

进入peer0.org1.example.com(192.168.3.222)服务器,同样的,我们可以基于docker-compose-cli.yaml文件创建:

cp docker-compose-cli.yaml docker-compose-peer.yaml

然后修改docker-compose-peer.yaml,去掉orderer的配置,只保留一个peer和cli,因为我们要多级部署,节点与节点之前又是通过主机名通讯,所以需要修改容器中的host文件,也就是extra_hosts设置。同样,cli也需要能够和各个节点通讯,所以cli下面也需要添加extra_hosts设置,去掉无效的依赖,并且去掉command这一行,因为我们是每个peer都会有个对应的客户端,也就是cli,所以我只需要去手动执行一次命令,而不是自动运行。修改后的配置如下:

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

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.3.221"
#     - "peer0.org1.example.com:192.168.3.222" #不要这句
     - "peer1.org1.example.com:192.168.3.223"

  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=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}; sleep $TIMEOUT'
    volumes:
        - /var/run/:/host/var/run/
        - ../chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
        - ./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.3.221"
     - "peer0.org1.example.com:192.168.3.222"
     - "peer1.org1.example.com:192.168.3.223"

在单机模式下,4个peer会映射主机不同的端口,但是我们在多机部署的时候是不需要映射不同端口的,所以需要修改base/docker-compose-base.yaml文件,将所有peer的端口映射都改为相同的:

ports: 
  - 7051:7051 
  - 7052:7052 
  - 7053:7053

(这里我好像没有改,原本就是这样的)
进入peer1.org1.example.com(192.168.3.223)服务器,同理,修改后的配置如下:

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

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.3.221"
     - "peer0.org1.example.com:192.168.3.222"

  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}; sleep $TIMEOUT'
    volumes:
        - /var/run/:/host/var/run/
        - ../chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
        - ./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.3.221"
     - "peer0.org1.example.com:192.168.3.222"

四、启动fabric

4.1启动orderer

让我们首先来启动orderer节点,在orderer服务器上运行:

docker-compose -f docker-compose-orderer.yaml up –d

运行完毕后我们可以使用docker ps看到运行了一个名字为orderer.example.com的节点。

4.2启动peer

然后我们切换到peer0.org1.example.com和peer1.org1.example.com服务器,分别启动本服务器的peer节点和cli,命令为:

docker-compose -f docker-compose-peer.yaml up –d

运行完毕后我们使用docker ps应该可以看到2个正在运行的容器。
现在我们整个Fabric2+1服务器网络已经成型,接下来是创建channel和运行ChainCode。

4.3创建Channel测试ChainCode

首先切换到peer0.org1.example.com服务器上,使用该服务器上的cli来运行创建Channel和运行ChainCode的操作。首先进入cli容器:

docker exec -it cli bash

进入容器后我们可以看到命令提示变为:

root@b41e67d40583:/opt/gopath/src/github.com/hyperledger/fabric/peer#

说明我们已经以root的身份进入到cli容器内部。官方已经提供了完整的创建Channel和测试ChainCode的脚本,并且已经映射到cli容器内部,所以我们只需要在cli内运行如下命令:

./scripts/script.sh mychannel

那么该脚本就可以一步一步的完成创建通道,将其他节点加入通道,更新锚节点,创建ChainCode,初始化账户,查询,转账,再次查询等链上代码的各个操作都可以自动化实现。直到最后,系统提示:

===================== All GOOD, End-2-End execution completed =====================

说明我们的2+1的Fabric多级部署成功了。
但本人这一步出错了因为原本为5台机子,本例中改为了三台,没有peer2节点,因此script.sh运行过程中报错

peer2安装链码错误

于是我进入scripts/script.sh把peer2相关的函数调用都注释掉,然后又报错:

Error: Error endorsing invoke: rpc error: code = Unknown desc = could
not find chaincode with name ‘mycc’ - make sure the chaincode mycc has
been successfully instantiated and try again

于是把报错之后的函数都注释掉,此时通过脚本已经把节点加入通道,但script.sh依然不能成功运行,尝试各种方法解决,无果。于是本人采取的措施是手动进行后续步骤:安装链码并实例化。(scripts/script.sh中前面的步骤如创建通道、加入通道、更新锚节点等也可以手动执行)
安装链码:

peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

实例化:

peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  -C mychannel -nmycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR('Org1MSP.member','Org2MSP.member')"

查询:

peer chaincode query -C mychannel -nmycc -v 1.0 -c '{"Args":["query","a"]}'

调用:

peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  -C mychannel -nmycc -v 1.0 -c '{"Args":["invoke","a","b","10"]}'

在peer0.org1中初始化和调用,在peer1.org1中能查询出调用结果,以及docker ps能看到新的容器,因为ChainCode会创建一个容器:
这里写图片描述
即说明多节点部署成功。

五、可能出现的问题

1.运行docker exec -it cli bash时报错

Error response from daemon: Container
10ff1671451580ed87f9e32c632f7ac643604df42b79d9d7d9d3fd217f31035a is
not running

原因:docker-compose-peer.yaml中的command这一行没有注释掉。

2.可能出现证书密钥不能识别,这个问题本人也无法彻底解决,没有完全理解其过程,只能重新生成证书等资料。

3.可能出现通道文件或者chancode相关文件没有找到,这个可以通过去对应路径寻找文件是否存在,要特别注意文件名字,注意上述代码中channel_name和chancode_name分别是通道名和链码实例名,因为过程中产生的文件都与这两个名字相关,产生文件的路径为,不同peer节点容器中的/var/hyperledger/production目录下。

4.节点必须使用同一个generateArtifacts的生成文件,否则报错。

5.运行./scripts/script时报错

Error: Got unexpected status: BAD_REQUEST

因为mychannel已经创建,再创建时会报错。
解决:依次关闭和删除三个服务器的docker容器,然后重新启动。
docker-compose -f docker-compose-peer.yaml down(必须三个同时关!)
或者参考这篇博文Hyperledger Fabric 1.0 从零开始(九)——Fabric多节点集群生产启动的 7.4.1、注意事项-必读

参考:
Fabric 1.0的多机部署(深蓝大大的这个系列写的非常好,评论区里也有很多常见问题的解决思路)
深入理解Fabric环境搭建的详细过程
Hyperledger Fabric 1.0 从零开始(八)——Fabric多节点集群生产部署
fabric多节点集群部署(4+1)详解(非常详细!)
hyperledger-fabric多机部署体验

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐