简介:本资源是一份面向区块链开发工程师与联盟链部署实践者的 Hyperledger Fabric 2.0 分布式集群部署实战指南,聚焦企业级生产环境落地痛点,系统解决多节点协同、共识配置简化与链码生命周期管理等核心问题。文档为单个PDF文件(554KB),内容结构完整,涵盖Fabric 2.0四大关键升级:模块化链码生命周期(打包→安装→批准→提交→升级)、基于EtcdRaft的轻量共识机制、智能合约去中心化治理流程,以及Alpine镜像带来的资源优化;同时提供从CentOS基础环境搭建(Docker/Go/Git/fabric-binaries)、三节点分布式拓扑规划(orderer0/peer0.org1等IP映射与防火墙配置),到证书生成、通道创建及网络启停的全流程实操细节。目前已有6482人学习下载,适合具备Linux与容器基础、正开展Fabric联盟链POC或生产部署的技术人员深度参考。
1. 为什么 Fabric 2.0 分布式集群必须用 EtcdRaft,而不是“先搭起来再说”?
很多团队在部署 Hyperledger Fabric 时,习惯性复用 1.x 的 Solo 或 Kafka 模式——结果在生产环境一上线就卡在共识延迟、节点失联、证书校验失败三连击。Fabric 2.0 的核心转折点不是功能堆叠,而是共识层彻底重构:EtcdRaft 不再依赖外部消息中间件,所有排序节点(orderer)自带 Raft 日志复制与 Leader 选举能力,节点间通过 TLS 双向认证直连通信。这意味着你不再需要单独维护 Kafka 集群、ZooKeeper 服务和复杂的 ACL 策略;三台物理机即可构成高可用排序服务,且故障恢复时间从分钟级压缩到秒级。本文实操的 3 节点集群(192.168.137.100/101/102)正是基于这一设计范式:orderer0–2 构成 Raft 共识组,peer0.org1 和 peer0.org2、peer1.org2 分属两个组织,全部启用 mTLS 双向验证。它不适用于 PoW 公链场景,但对供应链溯源、跨境贸易单证、医疗数据共享等联盟链高频写入+强一致性要求的业务,是当前最轻量、最可控、最易审计的 Fabric 生产部署形态。
2. Fabric 2.0 分布式集群的底层支撑:Docker + EtcdRaft + mTLS 三位一体
Fabric 2.0 分布式集群不是“把容器跑起来就行”,而是三个技术层深度咬合的结果:Docker 提供隔离运行时,EtcdRaft 定义节点协作逻辑,mTLS 则是所有通信的准入凭证。任何一层配置偏差都会导致connection refused、x509: certificate signed by unknown authority或context deadline exceeded这类典型错误。下面从环境准备开始,逐层拆解关键动作与参数含义。
2.1 基础环境统一:CentOS + Docker 24.0.7 + Go 1.14 + docker-compose 1.22.0
Fabric 对基础组件版本有硬性约束:Go 必须 ≥1.13(因 Fabric 2.0 使用 modules 机制),Docker 推荐 ≥20.10(避免 overlay2 驱动兼容问题),docker-compose 必须 ≥1.21(支持extra_hosts在多节点间解析 host 映射)。以下命令在三台服务器上逐条执行并验证输出:
# 关闭防火墙(生产环境应开放特定端口,非直接禁用) sudo systemctl stop firewalld sudo systemctl disable firewalld # 更新 yum 并安装基础工具 sudo yum update -y sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加 Docker 官方源(注意:使用阿里云镜像源可加速) sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装指定版本 Docker(避免自动升级破坏兼容性) sudo yum install -y docker-ce-24.0.7 docker-ce-cli-24.0.7 containerd.io # 启动并设为开机自启 sudo systemctl start docker sudo systemctl enable docker # 验证 Docker 版本及 daemon 状态 docker version | grep "Version:" systemctl is-active docker # 应返回 active提示:若
docker version报错Cannot connect to the Docker daemon,检查是否遗漏sudo systemctl start docker;若docker info显示WARNING: No swap limit support,属 CentOS 内核限制,不影响 Fabric 运行,可忽略。
接着安装 Go 1.14(Fabric 2.0 编译链码和二进制工具链必需):
# 下载并解压 Go(使用国内镜像加速) wget https://golang.google.cn/dl/go1.14.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.14.linux-amd64.tar.gz # 配置全局环境变量(写入 /etc/profile 保证所有用户生效) echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee -a /etc/profile echo 'export GOROOT=/usr/local/go' | sudo tee -a /etc/profile echo 'export GOPATH=/root/go' | sudo tee -a /etc/profile # 生效配置并验证 source /etc/profile go version # 应输出 go version go1.14 linux/amd64最后安装 docker-compose 1.22.0(注意:Fabric 官方脚本bootstrap.sh依赖此版本解析 YAML 中的extra_hosts):
# 下载指定版本(避免使用 pip install 导致权限混乱) 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 --version # 应输出 docker-compose version 1.22.02.2 Fabric 二进制与镜像拉取:bootstrap.sh 的真实作用与替代方案
Fabric 官方bootstrap.sh脚本本质是自动化下载三类资源:
fabric-samples:含first-network、test-network等示例目录,提供crypto-config.yaml和configtx.yaml模板;fabric binaries:configtxgen、cryptogen、peer、orderer等可执行文件,存于fabric-samples/scripts目录;Docker images:hyperledger/fabric-peer、hyperledger/fabric-orderer、hyperledger/fabric-tools等镜像,标签为2.0.0或latest。
但实际部署中,直接运行./bootstrap.sh存在两大风险:一是网络不稳定导致镜像拉取中断(尤其在国内);二是latest标签可能指向非预期版本。更可靠的做法是分步控制:
# 创建标准工作目录结构 mkdir -p ~/fabric-cluster/{channel-artifacts,crypto-config,scripts} cd ~/fabric-cluster # 手动下载 fabric-samples(GitHub Release 页面获取稳定版) wget https://github.com/hyperledger/fabric/archive/refs/tags/v2.0.0.tar.gz tar -xzf v2.0.0.tar.gz mv fabric-2.0.0/scripts ./scripts mv fabric-2.0.0/test-network ./test-network # 备用参考 # 下载并校验二进制文件(官方 SHA256 列表见 fabric GitHub release) cd scripts curl -O https://raw.githubusercontent.com/hyperledger/fabric/v2.0.0/scripts/bootstrap.sh chmod +x bootstrap.sh # 修改 bootstrap.sh:注释掉镜像拉取部分(第 152 行起),保留二进制下载 sed -i '152,170s/^/#/' bootstrap.sh # 执行仅下载二进制(跳过耗时的 docker pull) ./bootstrap.sh -s -d -t 2.0.0 # 将二进制复制到系统路径(便于全局调用) sudo cp ../scripts/* /usr/local/bin/注意:
-s参数跳过 samples 下载(已手动获取),-d跳过 docker 镜像拉取,-t 2.0.0指定版本。执行后/usr/local/bin/下应存在configtxgen、cryptogen等可执行文件,且configtxgen --version输出Fabric 2.0.0。
2.3 EtcdRaft 共识配置的核心:configtx.yaml 中 Consenters 字段的语义与校验
Fabric 2.0 的configtx.yaml文件中,Profiles.SampleMultiNodeEtcdRaft.EtcdRaft.Consenters是集群心跳的命脉。它不是简单罗列 IP,而是定义每个 orderer 节点的身份锚点:Host必须与/etc/hosts中解析的域名一致,Port必须与容器内监听端口匹配,ClientTLSCert和ServerTLSCert必须指向该节点生成的 TLS 证书路径(由cryptogen产出)。任何一项不一致,Raft 组建即失败。
以orderer0.example.com为例,其Consenters条目如下:
- Host: orderer0.example.com Port: 7050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt对应地,/etc/hosts必须包含:
192.168.137.100 orderer0.example.com 192.168.137.101 orderer1.example.com 192.168.137.102 orderer2.example.com且crypto-config/目录下证书路径必须真实存在:
# 在 192.168.137.100 上验证 ls -l crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt # 应输出类似:-r--r--r--. 1 root root 1120 Mar 8 14:22 server.crt关键逻辑说明:
ClientTLSCert用于 orderer 向其他 orderer 发起连接时证明身份;ServerTLSCert用于接收连接时被对方校验。二者必须为同一证书(Fabric 默认复用 server.crt),且server.crt的 Subject Common Name(CN)必须等于Host字段值(即orderer0.example.com)。可通过openssl x509 -in server.crt -text -noout | grep CN验证。
3. 三节点分布式集群实战:证书生成、创世区块构建与跨主机服务编排
Fabric 分布式集群的本质是“证书驱动的网络拓扑”。所有节点启动前,必须完成:① 用cryptogen生成全网统一的 MSP 证书体系;② 用configtxgen构建包含 Raft 成员信息的创世区块;③ 将证书与配置文件同步至各主机;④ 编写适配各节点角色的docker-compose.yaml。这四步缺一不可,且顺序严格。
3.1 证书体系生成:crypto-config.yaml 的组织拓扑与 Count 参数含义
crypto-config.yaml定义了 Fabric 网络的 PKI 结构。本文集群包含 1 个 Orderer 组织(3 个 orderer 节点)和 2 个 Peer 组织(Org1 含 1 个 peer,Org2 含 2 个 peers),对应配置如下:
OrdererOrgs: - Name: Orderer Domain: example.com Specs: - Hostname: orderer0 - Hostname: orderer1 - Hostname: orderer2 PeerOrgs: - Name: Org1 Domain: org1.example.com Template: Count: 1 # 生成 1 个 peer(peer0.org1.example.com) Users: Count: 1 # 生成 1 个普通用户(User1@org1.example.com) - Name: Org2 Domain: org2.example.com Template: Count: 2 # 生成 2 个 peers(peer0.org2.example.com, peer1.org2.example.com) Users: Count: 1执行cryptogen generate --config=./crypto-config.yaml后,生成的目录结构为:
crypto-config/ ├── ordererOrganizations/ │ └── example.com/ │ ├── orderers/ │ │ ├── orderer0.example.com/ # 含 msp、tls 目录 │ │ ├── orderer1.example.com/ │ │ └── orderer2.example.com/ │ └── users/ ├── peerOrganizations/ │ ├── org1.example.com/ │ │ └── peers/ │ │ └── peer0.org1.example.com/ # 含 msp、tls 目录 │ └── org2.example.com/ │ └── peers/ │ ├── peer0.org2.example.com/ │ └── peer1.org2.example.com/参数说明:
Template.Count决定同组织下 peer 节点数量,每个节点生成独立的msp(含私钥、签名证书)和tls(含 server.crt/server.key/ca.crt)目录;Users.Count决定该组织下注册用户的数量,用于后续链码调用的身份认证。切勿将 Count 设为 0,否则peer容器启动时因缺失 MSP 目录报错failed to load local MSP。
3.2 创世区块与通道配置:configtxgen 的 profile 选择与输出路径
Fabric 2.0 引入SampleMultiNodeEtcdRaftprofile 专门适配多 orderer Raft 集群。它与旧版SampleInsecureSolo的根本区别在于:前者在Orderer.EtcdRaft.Consenters中显式声明所有共识节点,后者仅配置单点ORDERER_GENERAL_ORDERERTYPE=solo。生成步骤如下:
# 生成创世区块(-profile 指定 Raft 模式,-outputBlock 指定输出路径) configtxgen -profile SampleMultiNodeEtcdRaft \ -channelID fabric-cluster-channel \ -outputBlock ./channel-artifacts/genesis.block # 生成通道创建交易(-profile 使用 TwoOrgsChannel,-outputCreateChannelTx 指定路径) configtxgen -profile TwoOrgsChannel \ -outputCreateChannelTx ./channel-artifacts/channel.tx \ -channelID mychannel # 为 Org1 生成锚节点更新交易(-asOrg 指定组织名,-outputAnchorPeersUpdate 指定输出) configtxgen -profile TwoOrgsChannel \ -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx \ -channelID mychannel \ -asOrg Org1MSP # 为 Org2 生成锚节点更新交易 configtxgen -profile TwoOrgsChannel \ -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx \ -channelID mychannel \ -asOrg Org2MSP生成的channel-artifacts/目录内容必须完整:
| 文件名 | 用途 | 验证命令 |
|---|---|---|
genesis.block | 排序服务启动所需的创世区块 | configtxgen -inspectBlock genesis.block | head -n 5 |
channel.tx | 创建应用通道的交易文件 | configtxgen -inspectChannelCreateTx channel.tx | grep "channel_id" |
Org1MSPanchors.tx | Org1 锚节点配置更新 | configtxgen -inspectChannelCreateTx Org1MSPanchors.tx | grep "anchor_peers" |
逻辑说明:
genesis.block包含 Raft 共识组初始成员列表(即Consenters),channel.tx定义通道成员(Org1+Org2)和策略,OrgXMSPancho.rs.tx则指定该组织在通道中的代表节点(如peer0.org1.example.com)。三者共同构成 Fabric 网络的“宪法”。
3.3 跨主机文件同步与 docker-compose 角色拆分:为什么不能共用同一份 compose 文件?
Fabric 分布式集群中,每台服务器只运行部分节点:
192.168.137.100:orderer0.example.com+peer0.org1.example.com192.168.137.101:orderer1.example.com+peer0.org2.example.com192.168.137.102:orderer2.example.com+peer1.org2.example.com
因此,docker-compose.yaml必须按节点角色拆分。以192.168.137.100为例,其docker-compose-up.yaml仅定义orderer0和peer0.org1:
version: '2' services: orderer0.example.com: container_name: orderer0.example.com image: hyperledger/fabric-orderer:2.0.0 environment: - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 - ORDERER_GENERAL_BOOTSTRAPFILE=/var/hyperledger/orderer/orderer.genesis.block - ORDERER_GENERAL_LOCALMSPID=OrdererMSP - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp - ORDERER_GENERAL_TLS_ENABLED=true - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] # Raft 集群必需参数 - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] volumes: - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp:/var/hyperledger/orderer/msp - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls:/var/hyperledger/orderer/tls ports: - 7050:7050 extra_hosts: - "orderer0.example.com:192.168.137.100" - "orderer1.example.com:192.168.137.101" - "orderer2.example.com:192.168.137.102" peer0.org1.example.com: container_name: peer0.org1.example.com image: hyperledger/fabric-peer:2.0.0 environment: - CORE_PEER_ID=peer0.org1.example.com - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_LISTENADDRESS=0.0.0.0:7051 - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_TLS_ENABLED=true - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt volumes: - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls ports: - 7051:7051 - 7052:7052 - 7053:7053 extra_hosts: - "orderer0.example.com:192.168.137.100" - "orderer1.example.com:192.168.137.101" - "orderer2.example.com:192.168.137.102"同步命令需在192.168.137.100上执行:
# 将证书和通道文件推送到其他两台机器 scp -r channel-artifacts/ root@192.168.137.101:/root/fabric-cluster/ scp -r channel-artifacts/ root@192.168.137.102:/root/fabric-cluster/ scp -r crypto-config/ root@192.168.137.101:/root/fabric-cluster/ scp -r crypto-config/ root@192.168.137.102:/root/fabric-cluster/ # 在目标机器上创建各自 compose 文件(以 101 为例) ssh root@192.168.137.101 "cat > /root/fabric-cluster/docker-compose-up.yaml << 'EOF' # 此处粘贴 orderer1 + peer0.org2 的 service 定义 EOF"关键点:
extra_hosts确保容器内 DNS 解析正确,volumes映射路径必须与crypto-config.yaml生成的实际路径一致,image标签必须显式指定:2.0.0(避免拉取latest导致版本不一致)。
4. 集群启动与状态验证:从 docker-compose up 到 peer channel list 的全流程诊断
启动 Fabric 分布式集群不是执行一条docker-compose up -d就能完事。由于涉及多节点 TLS 握手、Raft Leader 选举、Gossip 网络发现,必须分阶段验证每个环节是否就绪。以下是经过生产环境验证的标准流程。
4.1 分阶段启动与日志观察:为什么不能所有节点同时启动?
Raft 共识要求至少(N/2)+1个节点在线才能形成多数派(quorum)。对于 3 节点集群,需至少 2 个 orderer 启动成功后,第三个才能加入。因此推荐启动顺序:
先启动
orderer0和orderer1(在 100 和 101 上分别执行):cd ~/fabric-cluster docker-compose -f docker-compose-up.yaml up -d orderer0.example.com # 等待 30 秒,确认无 crash docker logs orderer0.example.com 2>&1 | grep "Raft leader is"再启动
orderer2(在 102 上):docker-compose -f docker-compose-up.yaml up -d orderer2.example.com # 观察日志是否出现 "joined raft cluster" 和 "became leader" docker logs orderer2.example.com 2>&1 | grep -E "(joined|leader)"最后启动所有 peer 节点(100/101/102 同时执行):
# 在各自机器上 docker-compose -f docker-compose-up.yaml up -d peer0.org1.example.com docker-compose -f docker-compose-up.yaml up -d peer0.org2.example.com docker-compose -f docker-compose-up.yaml up -d peer1.org2.example.com
典型错误定位:若
docker logs orderer0.example.com持续输出failed to dial ... context deadline exceeded,检查extra_hosts是否缺失orderer1.example.com解析;若出现x509: certificate is valid for orderer1.example.com, not orderer0.example.com,说明server.crt的 CN 与Host字段不匹配。
4.2 CLI 容器接入与通道操作:使用 tools 镜像执行 peer 命令
Fabric 未提供跨节点的统一管理界面,所有通道操作必须通过hyperledger/fabric-tools容器完成。该容器需挂载所有组织的 MSP 和 TLS 证书,并配置正确的环境变量:
# 在 192.168.137.100 上创建 CLI 容器(复用 peer0.org1 的证书) docker run -it --rm \ --network host \ -v $(pwd)/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto \ -e CORE_PEER_TLS_ENABLED=true \ -e CORE_PEER_LOCALMSPID="Org1MSP" \ -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp \ -e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 \ -e 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 \ -e 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 \ -e 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 \ hyperledger/fabric-tools:2.0.0 \ peer channel create -c mychannel -f ./channel-artifacts/channel.tx -o orderer0.example.com:7050 --outputBlock ./channel-artifacts/mychannel.block成功后,mychannel.block生成,且docker logs orderer0.example.com应出现Received block [0]。
接着加入 peer 节点:
# 加入 Org1 的 peer peer channel join -b ./channel-artifacts/mychannel.block # 加入 Org2 的 peer(需切换到 Org2 的 MSP 路径) CORE_PEER_LOCALMSPID="Org2MSP" \ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \ CORE_PEER_ADDRESS=peer0.org2.example.com:7051 \ CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ peer channel join -b ./channel-artifacts/mychannel.block4.3 最终状态验证表:5 个关键命令及其预期输出
| 命令 | 执行位置 | 预期输出 | 失败含义 |
|---|---|---|---|
| `docker ps | grep -E "(orderer | peer)"` | 所有三台机器 | 每台显示 2 个 UP 容器 |
docker logs orderer0.example.com | grep "Raft leader is" | 100 | Raft leader is orderer0.example.com:7050 | Raft 未选举出 leader |
peer channel list | CLI 容器 | Channels:+mychannel | peer 未加入通道 |
peer channel getinfo -c mychannel | CLI 容器 | "height":1+"currentBlockHash" | 通道未初始化成功 |
peer chaincode list --installed | CLI 容器 | Package ID:+Label: | 链码未安装或路径错误 |
验证技巧:若
peer channel list返回空,检查CORE_PEER_ADDRESS是否指向本机 peer(如peer0.org1.example.com:7051),且该 peer 容器确实在运行;若getinfo报错error getting endorser client,确认CORE_PEER_TLS_*路径下的证书文件存在且可读(ls -l检查权限)。
5. Fabric 2.0 链码生命周期实战:从打包、安装到批准提交的七步闭环
Fabric 2.0 最大变革是链码(智能合约)管理去中心化:不再由单一管理员部署,而是通过package → install → approve → commit四步实现多组织协同治理。这要求每个组织独立安装链码,再共同批准版本,最后由足够多组织提交生效。整个过程需精确控制--peerAddresses和--signature-policy参数,否则approve会因签名不足失败。
5.1 链码打包与安装:packager 与 install 命令的参数组合
以fabcar链码为例(位于fabric-samples/chaincode/fabcar/go),在 CLI 容器中执行:
# 1. 打包链码(生成 .tar.gz,含 metadata.json 和 code) peer lifecycle chaincode package fabcar.tar.gz \ --path github.com/hyperledger/fabric-samples/chaincode/fabcar/go \ --lang golang \ --label fabcar_1.0 # 2. Org1 安装(--peerAddresses 指向本组织 peer) peer lifecycle chaincode install fabcar.tar.gz \ --peerAddresses peer0.org1.example.com:7051 # 3. Org2 安装(需切换环境变量,指向 Org2 peer) CORE_PEER_LOCALMSPID="Org2MSP" \ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \ CORE_PEER_ADDRESS=peer0.org2.example.com:7051 \ CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ peer lifecycle chaincode install fabcar.tar.gz参数说明:
--path是链码源码路径(相对 GOPATH),--label是链码唯一标识(后续 approve 时引用),--peerAddresses必须是本组织已加入通道的 peer 地址。安装成功后,peer lifecycle chaincode queryinstalled会返回Package ID(如cc123...),该 ID 在 approve 阶段必须完全一致。
5.2 批准与提交:背书策略与 Majority 规则的强制执行
Fabric 2.0 要求至少MAJORITY组织批准后才能提交。本集群含 Org1 和 Org2,故需两者都 approve:
# 4. Org1 批准(--sequence 1 表示首个版本,--version 1.0) peer lifecycle chaincode approveformyorg \ -o orderer0.example.com:7050 \ --ordererResponseTimeout 30s \ --channelID mychannel \ --name fabcar \ --version 1.0 \ --package-id cc123... \ --sequence 1 \ --waitForEvent \ --signature-policy "AND('Org1MSP.peer','Org2MSP.peer')" \ --peerAddresses peer0.org1.example.com:7051 # 5. Org2 批准(同样参数,仅改 peer 地址) CORE_PEER_LOCALMSPID="Org2MSP" \ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \ CORE_PEER_ADDRESS=peer0.org2.example.com:7051 \ CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ peer lifecycle chaincode approveformyorg \ -o orderer0.example.com:7050 \ --channelID mychannel \ --name fabcar \ --version 1.0 \ --package-id cc123... \ --sequence 1 \ --signature-policy "AND('Org1MSP.peer','Org2MSP.peer')" \ --peerAddresses peer0.org2.example.com:7051 # 6. 查询批准状态(确认两者都为 true) peer lifecycle chaincode checkcommitreadiness \ --channelID mychannel \ --name fabcar \ --version 1.0 \ --sequence 1 \ --output json # 输出应含 "Org1MSP": {"Approve": true}, "Org2MSP": {"Approve": true} # 7. 提交链码(由任一组织执行,需指定所有批准组织) peer lifecycle chaincode commit \ -o orderer0.example.com:7050 \ --channelID mychannel \ --name fabcar \ --version 1.0 \ --sequence 1 \ --peerAddresses peer0.org1.example.com:7051 \ --peerAddresses peer0.org2.example.com:7051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt关键逻辑:
--signature-policy定义链码调用时的背书策略(此处要求 Org1 和 Org2 的 peer 共同签名),checkcommitreadiness是提交前的强制校验,commit命令中的--peerAddresses必须列出所有已 approve 的组织 peer,且--tlsRootCertFiles需提供对应组织的 CA 证书。提交成功后,peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar
本文还有配套的精品资源,点击获取