RAFT 오더링 서비스 기반 멀티호스트 환경

min71·2021년 11월 3일
0

하이퍼레저

목록 보기
12/12

Raft 분산 합의

Raft는 분산 합의를 구현하기 위한 프로토콜이다

노드는 3가지 상태 중, 한 가지 상태를 가짐
1. Follwer
2. Candidate
3. Leader

리더 선출 과정

1. 모든 리더는 Follower 상태에서 시작됨

Follower는 Leader로부터 일정시간 신호를 못 받으면 Candidate 상태가 된다

2. Candidate는 자기 자신에게 투표 후 다른 노드에게 투표 요청을 보내 자신에게 투표하기를 요청

3. 아직 투표를 하지 않은 노드들은 투표 요청에 응답을 한다(투표는 한 텀에 한 번만 가능)

4. Candidate가 과반수 이상의 응답을 받으면 Leader가 된다

어떤 Candidate도 과반수 이상의 응답을 받지 못하면 1번으로 돌아가 새 투표 시작

5. 이제 모든 변화는 Leader노드를 통해 이루어 진다

데이터 동기화

1. Leader는 Client로부터 데이터를 수신한다.(모든 데이터는 노드의 로그에 저장됨)

2. Leader는 Follower에게 수신한 데이터를 복사해 전송한 다음 Follower들의 응답을 기다린다.
(Append Entries 메시지에 데이터가 덧붙여져서 전송됨)

Follwer들은 Leader에게 Commit 메세지 받으면 Leader에게 Acknowledge 메시지 전송

3. 과반수 이상의 Follower에게 응답을 받으면 데이터를 적용 후 Follower 들에게 commit 되었다는 메시지를 보낸다

Follwer들은 Leader에게 수신한 데이터 반영

리더 선출

각 노드에는 리더 선출을 제어하기 위한 두 가지의 타이머가 존재

1. Election timeout

  • Follower가 Candidate가 되기 위해 기다려야 하는 시간
  • 150ms ~ 300ms의 랜덤한 값을 가짐
  • Election timeout이 된 노드는 Candidate가 되어 다른 노드들에게 투표요청을 보냄
  • 다른 노드의 투표 요청을 받으면 Election Timeout이 초기화 됨
  • Leader노드에게 Append Entries 메시지(Leader와 Follower가 주기적으로 주고 받는 메세지)를 받으면 Election Timeout이 초기화 됨

2. HeartBeat Timeout

  • Leader가 된 노드는 Follower 들에게 HeartBeat Timeout 간격으로 Append Entries 메시지를 보냄

Follower들이 Append Entries 메시지 받지 못하면 새로운 텀이 시작되고 새로운 리더를 선출함

장애 복구

Leader와 Follower가 네트워크 장애로 인해 나뉘어진 경우 일관성을 유지하는 과정

1. 두 그룹으로 분리된 노드들은 각 그룹에서 새로운 Leader를 선출함

  • 서로 다른 텀을 가진 그룹이 생성됨(기존 Leader가 포함된 그룹은 더 낮은 수의 텀을 가짐)

2. 두 그룹의 Leader는 Client로부터 각각 다른 데이터를 수신함

  • 한 그룹의 Leader는 과반수 이상의 Acknowledge 메시지를 받지 못해 수신 받은 데이터를 commit하지 못함

  • 다른 그룹의 Leader는 과반수 이상의 Acknowledge 메시지를 받아 수신 받은 데이터를 commit함

3. 네트워크 장애가 해결되서 두 그룹이 하나로 뭉쳐짐

  • 텀이 더 낮은 로그는 더 높은 텀의 로그로 갱신됨

  • 두 그룹의 Leader는 uncommit된 데이터를 롤백 후 텀이 더 높은 그룹의 Leader의 데이터로 노드에 저장된 값 일치시킴

RAFT 오더링 서비스 기반 멀티호스트 환경

네트워크 구조

Host1

  • peer0.org1.example.com
  • peer1.org1.example.com
  • orderer.example.com
  • orderer2.example.com
  • orderer5.example.com
  • orderer7.example.com

Host2

  • peer0.org2.example.com
  • peer1.org2.example.com
  • orderer3.example.com
  • orderer4.example.com
  • orderer6.example.com

네트워크 설정

Docker Swarm을 사용한 멀티호스트 환경

cd fabric-samples/first-network

오버레이 네트워크 생성

# Host1
docker swarm init --advertise-addr <Host1 아이피>
docker swarm join-token manager
docker network create --attachable --driver overlay first-network

# Host2
<join-token manager 출력 > --advertise-addr <Host2 아이피>

파일 수정

crypto-config.yaml 수정

configtx.yaml 수정

base/docker-compose-base.yaml 수정

.env 생성

host1.yaml 생성

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

version: '2'

volumes:
    orderer.example.com:
    orderer2.example.com:
    orderer5.example.com:
    orderer7.example.com:
    peer0.org1.example.com:
    peer1.org1.example.com:

networks:
    byfn:
        external:
            name: first-network

services:

    orderer.example.com:
        extends:
            file: base/docker-compose-base.yaml
            service: orderer.example.com
        container_name: orderer.example.com
        networks:
            - byfn

    orderer5.example.com:
        extends:
            file: base/peer-base.yaml
            service: orderer-base
        container_name: orderer5.example.com
        networks:
            - byfn
        volumes:
            - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/msp:/var/hyperledger/orderer/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/:/var/hyperledger/orderer/tls
            - orderer5.example.com:/var/hyperledger/production/orderer
        ports:
            - 8050:7050

    orderer2.example.com:
        extends:
            file: base/peer-base.yaml
            service: orderer-base
        container_name: orderer2.example.com
        networks:
            - byfn
        volumes:
            - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp:/var/hyperledger/orderer/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/:/var/hyperledger/orderer/tls
            - orderer2.example.com:/var/hyperledger/production/orderer
        ports:
            - 9050:7050

    orderer7.example.com:
        extends:
            file: base/peer-base.yaml
            service: orderer-base
        container_name: orderer7.example.com
        networks:
            - byfn
        volumes:
            - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer7.example.com/msp:/var/hyperledger/orderer/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer7.example.com/tls/:/var/hyperledger/orderer/tls
            - orderer7.example.com:/var/hyperledger/production/orderer
        ports:
            - 10050:7050

    peer0.org1.example.com:
        container_name: peer0.org1.example.com
        extends:
            file: base/docker-compose-base.yaml
            service: peer0.org1.example.com
        networks:
            - byfn
            
    peer1.org1.example.com:
        container_name: peer1.org1.example.com
        extends:
            file: base/docker-compose-base.yaml
            service: peer1.org1.example.com
        networks:
            - byfn

    cli:
        container_name: cli
        image: hyperledger/fabric-tools:$IMAGE_TAG
        tty: true
        stdin_open: true
        environment:
            - SYS_CHANNEL=$SYS_CHANNEL
            - GOPATH=/opt/gopath
            - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
            #- FABRIC_LOGGING_SPEC=DEBUG
            - FABRIC_LOGGING_SPEC=INFO
            - 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
        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:
            - orderer.example.com
            - peer0.org1.example.com
        networks:
            - byfn

host2.yaml 생성

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

version: '2'

volumes:
    orderer3.example.com:
    peer0.org2.example.com:
    orderer4.example.com:
    orderer6.example.com:
    peer1.org2.example.com:

networks:
    byfn:
        external:
            name: first-network

services:

    orderer3.example.com:
        extends:
            file: base/peer-base.yaml
            service: orderer-base
        container_name: orderer3.example.com
        networks:
            - byfn
        volumes:
            - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/msp:/var/hyperledger/orderer/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/:/var/hyperledger/orderer/tls
            - orderer3.example.com:/var/hyperledger/production/orderer
        ports:
            - 7050:7050

    peer0.org2.example.com:
        container_name: peer0.org2.example.com
        extends:
            file: base/docker-compose-base.yaml
            service: peer0.org2.example.com
        networks:
            - byfn

    orderer4.example.com:
        extends:
            file: base/peer-base.yaml
            service: orderer-base
        container_name: orderer4.example.com
        networks:
            - byfn
        volumes:
            - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/msp:/var/hyperledger/orderer/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/:/var/hyperledger/orderer/tls
            - orderer4.example.com:/var/hyperledger/production/orderer
        ports:
            - 9050:7050

    peer1.org2.example.com:
        container_name: peer1.org2.example.com
        extends:
            file: base/docker-compose-base.yaml
            service: peer1.org2.example.com
        networks:
            - byfn

    orderer6.example.com:
        extends:
            file: base/peer-base.yaml
            service: orderer-base
        container_name: orderer6.example.com
        networks:
            - byfn
        volumes:
            - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer6.example.com/msp:/var/hyperledger/orderer/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer6.example.com/tls/:/var/hyperledger/orderer/tls
            - orderer6.example.com:/var/hyperledger/production/orderer
        ports:
            - 8050:7050

네트워크 실행

암호자료 생성

# 암호자료 생성
../bin/cryptogen generate --config=./crypto-config.yaml

제네시스 블록 생성

# 제네시스 블록 생성
export FABRIC_CFG_PATH=$PWD
mkdir channel-artifacts
../bin/configtxgen -profile SampleMultiNodeEtcdRaft -outputBlock ./channel-artifacts/genesis.block

채널 트랜잭션 생성

# 채널 트랜잭션 생성
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel

조직별 앵커피어 트랜잭션 생성

# 조직별 앵커피어 트랜잭션 생성
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP

다른 호스트에게 디렉터리 복사

# 다른 호스트에게 디렉터리 복사
# Host1
cd ..
tar -czf raft-4node-swarm.tar raft-4node-swarm

# Host2
scp hyperledger@<Host1 아이피>:/home/hyperledger/fabric-samples/raft-4node-swarm.tar /home/hyperledger/fabric-samples
tar -xzf raft-4node-swarm.tar

피어노드 실행

# 피어노드 실행
# Host1
docker-compose -f host1.yaml up -d

# Host2
docker-compose -f host2.yaml up -d

채널 생성

# peer0.org1.example.com
docker exec -it cli bash
peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

채널 가입 & 앵커피어 업데이트

# peer0.org1.example.com
export CHANNEL_NAME=mychannel
peer channel join -b mychannel.block
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

#peer1.org1.example.com
docker exec -it -e CORE_PEER_ADDRESS=peer1.org1.example.com:8051 -e 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 cli bash
peer channel join -b mychannel.block

#peer0.org2.example.com
docker exec -it -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e 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 cli bash
export CHANNEL_NAME=mychannel
peer channel join -b mychannel.block
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

#peer1.org2.example.com
docker exec -it -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer1.org2.example.com:8051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt cli bash
peer channel join -b mychannel.block

체인코드 실행

체인코드 설치

# peer0.org1.example.com
# peer1.org1.example.com
# peer0.org2.example.com
# peer1.org2.example.com
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/

체인코드 초기화

# peer0.org1.example.com
peer chaincode instantiate -o orderer.example.com:7050 --tls --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 -n mycc -v 1.0 -c '{"Args":[]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

체인코드 실행

# 체인코드 실행
# peer0.org1.example.com
peer chaincode invoke -o orderer.example.com:7050 --tls true --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 -n mycc --peerAddresses peer0.org1.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 --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["initLedger"]}'

# 체인코드 질의
# peer0.org1.example.com
peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'

# peer0.org2.example.com
peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'

# 체인코드 실행( orderer7.example.com 사용)
# peer0.org1.example.com
peer chaincode invoke -o orderer7.example.com:7050 --tls true --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 -n mycc --peerAddresses peer0.org1.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 --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["changeCarOwner","CAR0","KC"]}'

# 체인코드 실행( orderer4.example.com 사용)
# peer0.org2.example.com
peer chaincode invoke -o orderer4.example.com:7050 --tls true --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 -n mycc --peerAddresses peer0.org1.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 --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["changeCarOwner","CAR0","KC2"]}'

profile
한 줄 소개

4개의 댓글

comment-user-thumbnail
2021년 11월 4일
답글 달기
comment-user-thumbnail
2021년 11월 6일

잘 읽고 갑니다!!

답글 달기
comment-user-thumbnail
2022년 1월 30일

잘 읽고 갑니다

답글 달기
comment-user-thumbnail
2022년 4월 11일

요새 글이 안 올라오네요?

답글 달기

관련 채용 정보