Hyperledger Fabric 多机环境部署

前言

本文主要基于 Hyperledger Fabric v1.0 的单机环境部署文档来搭建多机环境。其中对于Fabric 的基础环境的配置都是一样的,也就是前 6 步都是一样的。配置好基础环境之后将配置好的虚拟机镜像复制 4 份,作为其他节点的镜像,该环境包括 5 个节点,是 4 Peer + 1 Orderer的架构,如下表:

主机名 IP地址
orderer.example.com 192.168.1.130
peer0.org1.example.com 192.168.1.188
peer1.org1.example.com 192.168.1.186
peer0.org2.example.com 192.168.1.193
peer1.org2.example.com 192.168.1.112

环境部署

1. 更换 apt 源

先备份 sources.list 文件:

1
$ sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

再修改 sources.list 文件,换成阿里云的国内源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ sudo vim /etc/apt/sources.list
deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties
deb http://archive.canonical.com/ubuntu xenial partner
deb-src http://archive.canonical.com/ubuntu xenial partner
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse

最后更新一下源:

1
$ sudo apt-get update

2. 安装 curl

Ubuntu 16.04 一般默认是安装了 curl 的,可以通过以下命令验证:

1
2
3
4
$ curl -V
curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

如果没有安装,则通过 apt-get 安装:

1
$ sudo apt-get install curl

3. 安装 Docker

  • 由于 apt 源使用HTTPS以确保软件下载过程中不被篡改。因此,我们首先需要添加使用HTTPS传输的软件包以及CA证书。

    1
    2
    3
    4
    5
    $ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
  • 为了确认所下载软件包的合法性,需要添加软件源的 GPG 秘钥

    1
    $ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
  • 然后,我们需要向 sources.list 中添加 Docker 软件源

    1
    2
    3
    4
    $ sudo add-apt-repository \
    "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
    $(lsb_release -cs) \
    stable"

    以上命令会添加稳定版本的Docker CE apt 镜像源。

  • 更新 apt 软件包缓存,并安装 docker-ce:

    1
    2
    3
    $ sudo apt-get update

    $ sudo apt-get install docker-ce
  • 查看 Docker 版本:

    1
    2
    $ docker -v
    Docker version 18.06.0-ce, build 0ffa825

    满足官方文档中 Docker version 17.06.2-ce or greater is required 的要求。

  • 启动 Docker CE

    1
    2
    $ sudo systemctl enable docker
    $ sudo systemctl start docker
  • 建立 docker 用户组

    默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

    1
    $ sudo groupadd docker

    其实一般按照上面的方法安装 Docker 后就已经创建好 docker 用户组了,可以使用 $ cat /etc/group | grep docker 命令来验证,所以就不需要再建立 docker 用户组了,再建立也会报错提示用户组已存在的。

  • 将当前用户加入 docker 用户组:

    1
    $ sudo usermod -aG docker $USER

    下次登录时即可方便的使用 docker 命令。

  • 测试 Docker 是否安装正确

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    $ docker run hello-world
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    9db2ca6ccae0: Pull complete
    Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc
    Status: Downloaded newer image for hello-world:latest

    Hello from Docker!
    This message shows that your installation appears to be working correctly.

    To generate this message, Docker took the following steps:
    1. The Docker client contacted the Docker daemon.
    2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
    3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
    4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

    To try something more ambitious, you can run an Ubuntu container with:
    $ docker run -it ubuntu bash

    Share images, automate workflows, and more with a free Docker ID:
    https://hub.docker.com/

    For more examples and ideas, visit:
    https://docs.docker.com/engine/userguide/
  • 配置镜像加速器

    国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如:

    当配置某一个加速器地址之后,若发现拉取不到镜像,请切换到另一个加速器地址。

    国内各大云服务商均提供了 Docker 镜像加速服务,建议根据运行 Docker 的云平台选择对应的镜像加速服务。

    我们以 Docker 官方加速器 https://registry.docker-cn.com 为例进行介绍。

    /etc/docker/daemon.json 中写入如下内容(如果文件不存在则创建)

    1
    2
    3
    4
    5
    {
    "registry-mirrors": [
    "https://registry.docker-cn.com"
    ]
    }

    之后重新启动服务

    1
    2
    $ sudo systemctl daemon-reload
    $ sudo systemctl restart docker

    4. 安装 Docker Compose

  • 通过二进制包来安装,从 官方 GitHub Release 处直接下载编译好的二进制文件即可。

    1
    2
    3
    $ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

    $ sudo chmod +x /usr/local/bin/docker-compose
  • 查看 Docker compose 版本

    1
    2
    $ docker-compose --version
    docker-compose version 1.22.0, build f46880fe

    满足官方文档中 Docker Compose version 1.14.0 or greater 的要求。

5. 安装 Go 语言环境

Hyperledger Fabric 在很多组件中使用了 Go 语言,并且 Hyperledger fabric 1.2.0 要求使用的是 GO version 1.10.x ,所以需要在我们的环境中安装对应的 Go 语言。

  • 从官网下载 1.10.x 版本的 Linux 平台的源码包

    1
    $ wget https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
  • 解压到指定目录

    1
    $ sudo tar zxvf go1.10.3.linux-amd64.tar.gz -C /usr/local/
  • 先创建 Go 的工作目录

    1
    $ mkdir ~/go
  • 配置环境变量

    1
    2
    3
    4
    5
    $ vi ~/.bashrc
    添加
    export GOROOT=/usr/local/go
    export GOPATH=/home/user1/go
    export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

    保存并使生效:

    1
    $ source ~/.bashrc
  • 测试 Go 的 demo 程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ cd ~/go

    $ vi hello.go
    package main

    import "fmt"

    func main() {
    fmt.Printf("hello world\n")
    }

    $ go build hello.go

    $ ls
    hello hello.go

    $ ./hello
    hello world

    6. Fabric 源码下载

  • 首先创建存放源码的文件夹:

    1
    $ mkdir -p ~/go/src/github.com/hyperledger
  • 使用 Git 下载完整源码:

    1
    $ git clone https://github.com/hyperledger/fabric.git
  • 进入 fabric 目录查看版本分支并切换分支:

    1
    2
    3
    4
    $ cd fabric
    $ git branch
    * release-1.2
    $ git checkout v1.0.0
  • 最后再解决 examples/e2e_cli/base/peer-base.yaml 文件中的一个小 bug:

    CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE 环境变量的值修改为 e2e_cli_default,而不是原来的 e2ecli_default

    1
    - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=e2e_cli_default

    不然在启动 Fabric 网络时会出现问题。

7. 启动其他节点

将刚才配置好的虚拟机镜像拷贝四份,并基于这些镜像启动 5 台虚拟机,主机名分别设置为:

  • orderer.example.com
  • peer0.org1.example.com
  • peer1.org1.example.com
  • peer0.org2.example.com
  • peer1.org2.example.com

8. docker-compose 配置文件准备

在 fabric 的源码中,提供了单机部署的 4 Peer+1 Orderer的示例,在 example/e2e_cli 文件夹下。我们将登录到 orderer.example.com 节点,生成公私钥,修改 docker-compose 配置文件,然后将 e2e_cli 整个文件夹分发到 Peer 节点,再分别登录到不同的 Peer 节点完成少部分的个性化配置工作。

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

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

1
$ ./generateArtifacts.sh mychannel

运行这个命令后,系统会创建 channel-artifacts 文件夹,里面包含了 mychannel 这个通道相关的文件,另外还有一个 crypto-config 文件夹,里面包含了各个节点的公私钥和证书的信息。

8.2 设置 Peer 节点的 docker-compose 文件

e2e_cli 中提供了多个yaml文件,我们可以基于docker-compose-cli.yaml文件创建:

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

然后修改 docker-compose-peer.yaml,去掉 orderer 的配置,只保留一个 peer 和 cli,因为我们要多机部署,节点与节点之前又是通过主机名通讯,所以需要修改容器中的host文件,也就是 extra_hosts 设置,修改后的peer配置如下:

1
2
3
4
5
6
7
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.1.130"

同样,cli也需要能够和各个节点通讯,所以cli下面也需要添加 extra_hosts 设置,去掉无效的依赖,并且去掉command 这一行,因为我们是每个 peer 都会有个对应的客户端,也就是 cli,所以我只需要去手动执行一次命令,而不是自动运行。修改后的cli配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
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.1.130"
- "peer0.org1.example.com:192.168.1.188"
- "peer1.org1.example.com:192.168.1.186"
- "peer0.org2.example.com:192.168.1.193"
- "peer1.org2.example.com:192.168.1.112"

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

1
2
3
4
ports: 
- 7051:7051
- 7052:7052
- 7053:7053

8.3 设置 Orderer 节点的 docker-compose 文件

与创建peer的配置文件类似,我们也复制一个yaml文件出来进行修改:

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

orderer 服务器上我们只需要保留 order 设置,其他 peer 和 cli 设置都可以删除。orderer 可以不设置 extra_hosts。

8.4 分发配置文件

前面 3 步操作,都是在 orderer.example.com上完成的,接下来我们需要将这些文件分发到另外4台服务器上。Linux 之间的文件传输,我们可以使用 scp 命令。 peer 节点上已经存在了 e2e_cli 文件夹,使用 scp 命令发送时会直接覆盖。在 orderer.example.com 节点的 fabric 的根目录下的 examples 目录下执行以下命令:

1
2
3
4
$ scp -r e2e_cli/ user1@192.168.1.188:/home/user1/go/src/github.com/hyperledger/fabric/examples
$ scp -r e2e_cli/ user1@192.168.1.186:/home/user1/go/src/github.com/hyperledger/fabric/examples
$ scp -r e2e_cli/ user1@192.168.1.193:/home/user1/go/src/github.com/hyperledger/fabric/examples
$ scp -r e2e_cli/ user1@192.168.1.112:/home/user1/go/src/github.com/hyperledger/fabric/examples

8.5 Peer 节点的个性化配置

因为之前配置的就是peer0.org1.example.com 节点,所以复制到peer0.org1.example.com 后不需要做任何修改。

复制到 peer1.org1.example.com 上,我们需要对 docker-compose-peer.yaml 做一个小小的修改,将启动的容器改为 peer1.org1.example.com,并且添加 peer0.org1.example.com 的 IP 映射,对应的 cli 中也改成对 peer1.org1.example.com 的依赖。这是修改后的 peer1.org1.example.com 上的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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.1.130"
- "peer0.org1.example.com:192.168.1.188"

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
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.1.130"
- "peer0.org1.example.com:192.168.1.188"
- "peer1.org1.example.com:192.168.1.186"
- "peer0.org2.example.com:192.168.1.193"
- "peer1.org2.example.com:192.168.1.112"

peer0.org2.example.compeer0.org2.example.com 节点上面的 docker-compose-peer.yaml 也是同理修改。

注意需要修改组织相关的信息。


9. 启动 Fabric

现在所有文件都已经准备完毕,我们可以启动我们的Fabric网络了。

9.1 启动 Orderer

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

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

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

9.2 启动 peer

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

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

运行完毕后我们使用docker ps应该可以看到2个正在运行的容器。

接下来依次在另外 3 台服务器运行启动peer节点容器的命令。

现在我们整个Fabric4+1服务器网络已经成型,接下来是创建channel和运行ChainCode。

9.3 创建 Channel 测试 Chaincode

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

1
$ docker exec -it cli bash

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

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

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

1
./scripts/script.sh mychannel

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

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

说明我们的 4+1 的 Fabric 多机部署成功了。