Hyperledger Fabric 멀티호스트 환경 구축하기 - Cryptogen기반
시작하기 전에
본 블로그는
Virtualbox 를 이용하여 하이퍼레저 패브릭 네트워크 환경을 구축하는 방법 및 예시를 설명하기 위함입니다.
구성환경으로 Guest OS는 Ubuntu 18.04 사용하였으며, 하이퍼레저 패브릭을 설치된 상태에서 시작합니다.
하이퍼레져 패브릭 설치하는 방법은 아래 주소를 참고하시기 바랍니다.
https://leejonggun.tistory.com/13
[목표 구성도]
상기와 같은 구성을 목표로 진행합니다.
1. 멀티호스트 구축을 위한 사전 작업
1) 사전 작업
Virtualbox 에 ubuntu 18.04와 Hyperledger Fabric 1.3을 설치
(머신의 램메모리는 2GB, 하드디스크는 40GB로 설정)
멀티호스트 간에 통신하기 위한 네트워크 어댑터 설정
Virtualbox 설정 > 네트워크 > network adaptor를 추가 > 호스트 전용 어댑터로 설정
2) 설정파일 복사 및 path 설정
패브릭 설치시에 설정된 환경 변수($GOPATH, $GOROOT, $FABRIC_HOME)
gun@gun-fabric:~$ echo $GOPATH
/home/gun/MyProjects
gun@gun-fabric:~$ echo $FABRIC_HOME
/home/gun/MyProjects/src/github.com/hyperledger/fabric
gun@gun-fabric:~/MyProjects/testnet$ echo $GOROOT
/usr/local/go
테스트네트워크 구축을 위한 디렉토리 생성 및 설정 파일 복사
mkdir $GOPATH/testnet
cp $FABRIC_HOME/sampleconfig/core.yaml $GOPATH/testnet
cp $FABRIC_HOME/sampleconfig/orderer.yaml $GOPATH/testnet
.profile 파일에 추가
export FABRIC_CFG_PATH=$GOPATH/testnet
source .profile
3) hosts 파일에 호스트 등록
/etc/hosts
10.0.1.11 peer0
10.0.1.21 peer1
10.0.1.31 orderer
10.0.1.32 kafka-zookeeper
10.0.1.41 client
4) virtualbox 머신 복제
설치된 머신을 다음 이름으로 복제
peer0, peer1, orderer, kafka-zookeeper, client
5) 머신별 ip 설정 및 호스트명 변경
상기 '목표구성도'에 맞추어서 머신별로 추가된 네트워크 어댑터에 IP를 수동 설정 후 어댑터 off/on하면 반영됩니다.
아래는 peer0의 예시입니다.
추가로, 각 머신의 /etc/hostname 을 생성된 머신의 호스트명으로 변경합니다.
2. MSP 생성
client 머신에서 실행합니다.
MSP 설정파일을 아래와 같이 생성합니다.
$GOPAHT/testnet/crypto-config.yaml
# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: OrdererOrg
Domain: ordererorg
Specs:
- Hostname: orderer
# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
# ---------------------------------------------------------------------------
# Org0
# ---------------------------------------------------------------------------
- Name: Org0
Domain: org0
# ---------------------------------------------------------------------------
# "Template"
# ---------------------------------------------------------------------------
# Allows for the definition of 1 or more hosts that are created sequentially
# from a template. By default, this looks like "peer%d" from 0 to Count-1.
# You may override the number of nodes (Count), the starting index (Start)
# or the template used to construct the name (Hostname).
#
# Note: Template and Specs are not mutually exclusive. You may define both
# sections and the aggregate nodes will be created for you. Take care with
# name collisions
# ---------------------------------------------------------------------------
Template:
Count: 1
# ---------------------------------------------------------------------------
# "Users"
# ---------------------------------------------------------------------------
# Count: The number of user accounts _in addition_ to Admin
# ---------------------------------------------------------------------------
Users:
Count: 1
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
- Name: Org1
Domain: org1
Template:
Count: 1
Start: 1
Users:
Count: 1
# MSP 생성 명령 실행
cryptogen generate --config=./crypto-config.yaml
# 내용 확인
$tree crypto-config
crypto-config
├── ordererOrganizations
│ └── ordererorg
│ ├── ca
│ │ ├── ca.ordererorg-cert.pem
│ │ └── ec0c2e24ebb2b65daad4cb63028b8af676165b458d3c6f31043977042c50a4ac_sk
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@ordererorg-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.ordererorg-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.ordererorg-cert.pem
│ ├── orderers
│ │ └── orderer.ordererorg
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@ordererorg-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.ordererorg-cert.pem
│ │ │ ├── keystore
│ │ │ │ └── d5c3f1b257d1b0be27cb669bdaa513dba5f9b9123f1b9fcb357bdcb2380dd668_sk
│ │ │ ├── signcerts
│ │ │ │ └── orderer.ordererorg-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.ordererorg-cert.pem
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── server.crt
│ │ └── server.key
│ ├── tlsca
│ │ ├── 1d14d8e117c144a31fb091ea0e42c0fb63edada779ff4c68778fe8d8951ef19a_sk
│ │ └── tlsca.ordererorg-cert.pem
│ └── users
│ └── Admin@ordererorg
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@ordererorg-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.ordererorg-cert.pem
│ │ ├── keystore
│ │ │ └── 8afe1ad34bd484a02a20492e1a899e43970e8f3389b8f8d57fabd88760bca52f_sk
│ │ ├── signcerts
│ │ │ └── Admin@ordererorg-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.ordererorg-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
└── peerOrganizations
├── org0
│ ├── ca
│ │ ├── 46ba8ec5714d645ea9641cb30bf507be7ef1dd1da1cb0ed17f5bf8e1ac59f12d_sk
│ │ └── ca.org0-cert.pem
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@org0-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.org0-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.org0-cert.pem
│ ├── peers
│ │ └── peer0.org0
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@org0-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.org0-cert.pem
│ │ │ ├── keystore
│ │ │ │ └── 6b49c479bb36c41586811b7d55dd0eb226700af8792510a14e4648606e8b11d0_sk
│ │ │ ├── signcerts
│ │ │ │ └── peer0.org0-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.org0-cert.pem
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── server.crt
│ │ └── server.key
│ ├── tlsca
│ │ ├── ca482f84fccb3c47f8e22c0885d0a39044b9ac1d08293b52b4d627accb217726_sk
│ │ └── tlsca.org0-cert.pem
│ └── users
│ ├── Admin@org0
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@org0-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.org0-cert.pem
│ │ │ ├── keystore
│ │ │ │ └── 42944b3c66caa836fdeda68c42781f6b725569fb7b9887208db5a7a32eac5e2e_sk
│ │ │ ├── signcerts
│ │ │ │ └── Admin@org0-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.org0-cert.pem
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── client.crt
│ │ └── client.key
│ └── User1@org0
│ ├── msp
│ │ ├── admincerts
│ │ │ └── User1@org0-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.org0-cert.pem
│ │ ├── keystore
│ │ │ └── 368511cf8b35babfc9675c689bd5a8b6cbb7e6c1e54ad56c54afb032ba9203a8_sk
│ │ ├── signcerts
│ │ │ └── User1@org0-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.org0-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
└── org1
├── ca
│ ├── a69dc9c87d722a7fe9557bfbca31bb3760eeaee8457d1f59ccf4555f40a17815_sk
│ └── ca.org1-cert.pem
├── msp
│ ├── admincerts
│ │ └── Admin@org1-cert.pem
│ ├── cacerts
│ │ └── ca.org1-cert.pem
│ └── tlscacerts
│ └── tlsca.org1-cert.pem
├── peers
│ └── peer1.org1
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@org1-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.org1-cert.pem
│ │ ├── keystore
│ │ │ └── c53ca32e68de8d74a5c85ec81d76b7e4bacdef2778b261fe3664d47b9704d395_sk
│ │ ├── signcerts
│ │ │ └── peer1.org1-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.org1-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── server.crt
│ └── server.key
├── tlsca
│ ├── 7c760e64fcdc6a4c6220d53fdc3e4a5bb690be5e549a1f88feca34bf4d06f711_sk
│ └── tlsca.org1-cert.pem
└── users
├── Admin@org1
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@org1-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.org1-cert.pem
│ │ ├── keystore
│ │ │ └── 16b0a0edfac4a501906c312b8ec22f99f83e514c4492363a861249bf921e71c2_sk
│ │ ├── signcerts
│ │ │ └── Admin@org1-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.org1-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
└── User1@org1
├── msp
│ ├── admincerts
│ │ └── User1@org1-cert.pem
│ ├── cacerts
│ │ └── ca.org1-cert.pem
│ ├── keystore
│ │ └── c4b2a553e008754eb19b5e71ef9bfa7e4f804e0f9dc43ecde50db25b5d8dfed2_sk
│ ├── signcerts
│ │ └── User1@org1-cert.pem
│ └── tlscacerts
│ └── tlsca.org1-cert.pem
└── tls
├── ca.crt
├── client.crt
└── client.key
시간을 좀 내셔서 생성된 MSP의 트리구조를 분석하시기 바랍니다
3. Genesis block 생성
client 머신에서 실행
$GOPAHT/testnet/configtx.yaml 설정 파일 생성
################################################################################
#
# ORGANIZATIONS
#
# This section defines the organizational identities that can be referenced
# in the configuration profiles.
#
################################################################################
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererOrgMSP
MSPDir: crypto-config/ordererOrganizations/ordererorg/msp/
- &Org0
Name: Org0MSP
ID: Org0MSP
MSPDir: crypto-config/peerOrganizations/org0/msp/
AnchorPeers:
- Host: peer0
Port: 7051
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1/msp/
AnchorPeers:
- Host: peer1
Port: 7051
################################################################################
#
# ORDERER
#
# This section defines the values to encode into a config transaction or
# genesis block for orderer related parameters.
#
################################################################################
Orderer: &OrdererDefaults
OrdererType: kafka
Addresses:
- orderer:7050
BatchTimeout: 1s
BatchSize:
MaxMessageCount: 30
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
MaxChannels: 0
Kafka:
Brokers:
- kafka-zookeeper:9092
Organizations:
################################################################################
#
# APPLICATION
#
# This section defines the values to encode into a config transaction or
# genesis block for application-related parameters.
#
################################################################################
Application: &ApplicationDefaults
# Organizations lists the orgs participating on the application side of the
# network.
Organizations:
################################################################################
#
# PROFILES
#
# Different configuration profiles may be encoded here to be specified as
# parameters to the configtxgen tool. The profiles which specify consortiums
# are to be used for generating the orderer genesis block. With the correct
# consortium members defined in the orderer genesis block, channel creation
# requests may be generated with only the org member names and a consortium
# name.
#
################################################################################
Profiles:
TwoOrgsOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org0
- *Org1
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org0
- *Org1
# genesis.block 파일 생성
$ configtxgen -profile TwoOrgsOrdererGenesis -outputBlock genesis.block
#genesis.block 파일 이동
$ mv genesis.block $GOPATH/testnet/crypto-config/ordererOrganizations/ordererorg/orderers/orderer.ordererorg/
4. 채널 설정
#TwoOrgsChannel 참조하여 채널 구축을 위한 트랜잭션 생성(client 머신에서 실행)
$ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ch1.tx -channelID ch1
# Anchor peer 설정하는 트랜잭션 생성
$ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate Org0MSPanchors.tx -channelID ch1 -asOrg Org0MSP
$ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate Org1MSPanchors.tx -channelID ch1 -asOrg Org1MSP
5. MSP 디렉토리 배포
#peer 와 order 노드의 fabric home 노드로 전송 (client 노드에서 실행)
$ scp -rq * gun@peer0:/home/gun/MyProjects/testnet/
$ scp -rq * gun@peer1:/home/gun/MyProjects/testnet/
$ scp -rq * gun@orderer:/home/gun/MyProjects/testnet/
6. Peer 구동
각 peer 노드에서 실행
구동 스크립트 생성
$gedit $FABRIC_CFG_PATH/runPeer.sh
#!/bin/bash
# arg1 <= The number of Org
# arg2 <= The number of peer
help()
{
echo "Usage: $0 [org] [peer]"
}
if [ $# -ne 2 ]
then
help
exit 0
fi
FABRIC_PATH=/home/gun/MyProjects/testnet
echo $FABRIC_PATH
CORE_PEER_ENDORSER_ENABLED=true \
CORE_PEER_ADDRESS=peer$2:7051 \
CORE_PEER_CHAINCODELISTENADDRESS=peer$2:7052 \
CORE_PEER_ID=org$1-peer$2 \
CORE_PEER_LOCALMSPID=Org$1MSP \
CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer$2:7051 \
CORE_PEER_GOSSIP_USELEADERELECTION=true \
CORE_PEER_GOSSIP_ORGLEADER=false \
CORE_PEER_TLS_ENABLED=false \
CORE_PEER_TLS_KEY_FILE=$FABRIC_PATH/crypto-config/peerOrganizations/org$1/peers/peer$2.org$1/tls/server.key \
CORE_PEER_TLS_CERT_FILE=$FABRIC_PATH/crypto-config/peerOrganizations/org$1/peers/peer$2.org$1/tls/server.crt \
CORE_PEER_TLS_ROOTCERT_FILE=$FABRIC_PATH/crypto-config/peerOrganizations/org$1/peers/peer$2.org$1/tls/ca.crt \
CORE_PEER_TLS_SERVERHOSTOVERRIDE=peer$2 \
CORE_PEER_MSPCONFIGPATH=$FABRIC_PATH/crypto-config/peerOrganizations/org$1/peers/peer$2.org$1/msp \
/home/gun/MyProjects/src/github.com/hyperledger/fabric/.build/bin/peer node start
실행권한 부여 및 실행
$ chmod +x runPeer.sh
$ sudo ./runPeer.sh 0 0
$ sudo ./runPeer.sh 1 1
/var 디렉토리를 사용하기 때문에 root 권한 필요하여, sudo로 실행
7. Kafka-Zookeeper 구동
kafka-zookeeper 머신에서 실행
$FABRIC_CFG_PATH/docker-compose.yaml 파일 생성
version: '2'
services:
zookeeper:
image: hyperledger/fabric-zookeeper
ports:
- "2181:2181"
kafka0:
image: hyperledger/fabric-kafka
ports:
- "9092:9092"
environment:
- KAFKA_ADVERTISED_HOST_NAME=10.0.1.32
- KAFKA_ADVERTISED_PORT=9092
- KAFKA_BROKER_ID=0
- KAFKA_MESSAGE_MAX_BYTES=103809024 # 99*1024*1024
- KAFKA_REPLICA_FETCH_MAX_BYTES=103809024
- KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false
- KAFKA_NUM_REPLICA_FETCHERS=1
- KAFKA_DEFAULT_REPLICATION_FACTOR=1
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
depends_on:
- zookeeper
# kafka-Zookeeper 구동(image 다운로드를 위하여 인터넷 연결 필요)
$ docker-compose up
Kafka-zookeeper 구동 화면
8. Orderer 구동
orderer 머신 실행
$FABRIC_CFG_PATH/runOrderer.sh 파일 생성
FABRIC_PATH=/home/gun/MyProjects/testnet
echo $FABRIC_PATH
ORDERER_GENERAL_LOGLEVEL=info \
ORDERER_GENERAL_LISTENADDRESS=orderer \
ORDERER_GENERAL_GENESISMETHOD=file \
ORDERER_GENERAL_GENESISFILE=$FABRIC_PATH/crypto-config/ordererOrganizations/ordererorg/orderers/orderer.ordererorg/genesis.block \
ORDERER_GENERAL_LOCALMSPID=OrdererOrgMSP \
ORDERER_GENERAL_LOCALMSPDIR=$FABRIC_PATH/crypto-config/ordererOrganizations/ordererorg/orderers/orderer.ordererorg/msp \
ORDERER_GENERAL_TLS_ENABLED=false \
ORDERER_GENERAL_TLS_PRIVATEKEY=$FABRIC_PATH/crypto-config/ordererOrganizations/ordererorg/orderers/orderer.ordererorg/tls/server.key \
ORDERER_GENERAL_TLS_CERTIFICATE=$FABRIC_PATH/crypto-config/ordererOrganizations/ordererorg/orderers/orderer.ordererorg/tls/server.crt \
ORDERER_GENERAL_TLS_ROOTCAS=[$FABRIC_PATH/crypto-config/ordererOrganizations/ordererorg/orderers/orderer.ordererorg/tls/ca.crt,$FABRIC_PATH/crypto-config/peerOrganizations/org0/peers/peer0.org0/tls/ca.crt,$FABRIC_PATH/crypto-config/peerOrganizations/org1/peers/peer1.org1/tls/ca.crt] \
CONFIGTX_ORDERER_BATCHTIMEOUT=1s \
CONFIGTX_ORDERER_ORDERERTYPE=kafka \
CONFIGTX_ORDERER_KAFKA_BROKERS=[kafka-zookeeper:9092] \
/home/gun/MyProjects/src/github.com/hyperledger/fabric/.build/bin/orderer
# 권한부여 및 실행 (/var 디렉토리에 파일 생성을 위해서 root 권한 필요)
$ chmod +x runOrderer.sh
$ sudo ./runOrderer
9. 채널 생성
client 노드에서 실행
$FABRIC_CFG_PATH/create-channel.sh 파일 생성
FABRIC_PATH=/home/gun/MyProjects/testnet
echo $FABRIC_PATH
CORE_PEER_LOCALMSPID="Org0MSP" \
CORE_PEER_TLS_ROOTCERT_FILE=$FABRIC_PATH/crypto-config/peerOrganizations/org0/peers/peer0.org0/tls/ca.crt \
CORE_PEER_MSPCONFIGPATH=$FABRIC_PATH/crypto-config/peerOrganizations/org0/users/Admin@org0/msp \
CORE_PEER_ADDRESS=peer0:7051 \
peer channel create -o orderer:7050 -c ch1 -f ch1.tx
# 권한부여 및 실행
chmod +x create-channle.sh
./create-channel.sh
14. 분산원장 테스트
client 머신에서 실행
[분산원장 읽기]
$FABRIC_CFG_PATH/query.sh
FABRIC_PATH=/home/gun/MyProjects/testnet
echo $FABRIC_PATH
export CORE_PEER_LOCALMSPID="Org0MSP"
export CORE_PEER_MSPCONFIGPATH=$FABRIC_PATH/crypto-config/peerOrganizations/org0/users/Admin@org0/msp
export CORE_PEER_ADDRESS=peer0:7051
peer chaincode query -C ch1 -n testnetCC -c '{"Args":["query","a"]}'
#권한부여 및 실행
$ chmod +x query.sh
./query.sh
[분산원장 쓰기]
$FABRIC_CFG_PATH/invoke.sh
FABRIC_PATH=/home/gun/MyProjects/testnet
echo $FABRIC_PATH
export CORE_PEER_LOCALMSPID="Org0MSP"
export CORE_PEER_MSPCONFIGPATH=$FABRIC_PATH/crypto-config/peerOrganizations/org0/users/Admin@org0/msp
export CORE_PEER_ADDRESS=peer0:7051
peer chaincode invoke -o orderer0:7050 -C ch1 -n testnetCC -c '{"Args":["invoke","a","b","50"]}'
해당 invoke 함수는 a에서 50을 빼서 b에 50을 더하는 함수이다
#권한부여 및 실행
$ chmod +x invoke.sh
./invoke.sh
#실행 결과 확인
./query.sh
a 값에서 50을 제하고 b값에 50을 더한 뒤에 분산원장 조회 결과를 확인할 수 있습니다.
마치며,
기다긴 실습 내용을 따라와 주셔서 감사합니다.
현재까지는 패브릭 네트워크 구축 및 설정이 다소 복잡할 수 있습니다.
하지만 하이퍼레져 패브릭도 계속 발전하면서 편리한 도구도 출현할 것이고, 점점 더 편해지지 않을까 생각됩니다.
즐거운 블록체인 되세요~~!!
[참고문헌]
하이퍼레저 패브릭으로 배우는 블록체인 (윤대근 지음, 제이펍)