Module 4: Network Deployment and Management

4.3 Network Deployment

After configuring your Hyperledger Fabric network, the next step is to deploy it. This section covers the deployment process, from starting the network to creating channels and deploying chaincode.

Starting the Network

The first step in deploying a Hyperledger Fabric network is to start the containers defined in your Docker Compose files.

Starting the Certificate Authorities

If you're using Fabric CA for a production environment, start the CA containers first:

# Create directories for CA
mkdir -p fabric-ca/org1 fabric-ca/org2 fabric-ca/orderer

# Start the CA containers
docker-compose -f docker-compose-ca.yaml up -d

Generating Cryptographic Material with Fabric CA

Once the CA containers are running, you can generate the cryptographic material:

# Register and enroll the orderer organization admin
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/ordererOrganizations/example.com/
fabric-ca-client enroll -u https://admin:adminpw@localhost:9054 --caname ca.orderer.example.com --tls.certfiles ${PWD}/organizations/fabric-ca/orderer/tls-cert.pem

# Register and enroll orderer nodes
fabric-ca-client register --caname ca.orderer.example.com --id.name orderer --id.secret ordererpw --id.type orderer --tls.certfiles ${PWD}/organizations/fabric-ca/orderer/tls-cert.pem
fabric-ca-client enroll -u https://orderer:ordererpw@localhost:9054 --caname ca.orderer.example.com -M ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp --csr.hosts orderer.example.com --tls.certfiles ${PWD}/organizations/fabric-ca/orderer/tls-cert.pem

# Register and enroll the peer organization admin
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/peerOrganizations/org1.example.com/
fabric-ca-client enroll -u https://admin:adminpw@localhost:7054 --caname ca.org1.example.com --tls.certfiles ${PWD}/organizations/fabric-ca/org1/tls-cert.pem

# Register and enroll peer nodes
fabric-ca-client register --caname ca.org1.example.com --id.name peer0 --id.secret peer0pw --id.type peer --tls.certfiles ${PWD}/organizations/fabric-ca/org1/tls-cert.pem
fabric-ca-client enroll -u https://peer0:peer0pw@localhost:7054 --caname ca.org1.example.com -M ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp --csr.hosts peer0.org1.example.com --tls.certfiles ${PWD}/organizations/fabric-ca/org1/tls-cert.pem

# Repeat for other organizations and peers

Starting the Orderers and Peers

Once the cryptographic material is generated, start the orderer and peer containers:

# Start the network
docker-compose -f docker-compose.yaml up -d

Verifying Network Startup

Verify that all containers are running correctly:

# Check container status
docker ps

# Check container logs
docker logs orderer.example.com
docker logs peer0.org1.example.com

Creating and Joining Channels

After the network is up and running, the next step is to create channels and have peers join them.

Creating a Channel

Use the CLI container to create a channel:

# Enter the CLI container
docker exec -it cli bash

# Set environment variables
export CHANNEL_NAME=channel1
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

# Create the channel
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/channel1.tx --tls --cafile $ORDERER_CA

Joining Peers to the Channel

Have each peer join the channel:

# Join peer0.org1 to the channel
peer channel join -b channel1.block

# Switch to peer0.org2
export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

# Join peer0.org2 to the channel
peer channel join -b channel1.block

Updating Anchor Peers

Update the channel configuration to define anchor peers:

# Switch back to peer0.org1
export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

# Update anchor peers for Org1
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org1MSPanchors.tx --tls --cafile $ORDERER_CA

# Switch to peer0.org2
export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

# Update anchor peers for Org2
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org2MSPanchors.tx --tls --cafile $ORDERER_CA

Deploying Chaincode

The final step in network deployment is to deploy chaincode to the channel.

Packaging Chaincode

Package the chaincode using the peer lifecycle commands:

# Create a chaincode package
peer lifecycle chaincode package mycc.tar.gz --path /opt/gopath/src/github.com/chaincode/mycc/ --lang golang --label mycc_1.0

Installing Chaincode on Peers

Install the chaincode package on each peer:

# Install on peer0.org1
peer lifecycle chaincode install mycc.tar.gz

# Get the package ID
peer lifecycle chaincode queryinstalled

# Set the package ID as an environment variable
export CC_PACKAGE_ID=mycc_1.0:hash

# Switch to peer0.org2
export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

# Install on peer0.org2
peer lifecycle chaincode install mycc.tar.gz

Approving Chaincode Definition

Each organization must approve the chaincode definition:

# Approve for Org1
export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name mycc --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1

# Approve for Org2
export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name mycc --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1

Committing Chaincode Definition

Once enough organizations have approved, commit the chaincode definition to the channel:

peer lifecycle chaincode commit -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name mycc --version 1.0 --sequence 1 --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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

Invoking Chaincode

Initialize the chaincode and test it with an invoke transaction:

# Initialize the chaincode (if needed)
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'

# Invoke a transaction
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateAsset","Args":["asset1", "blue", "5", "tom", "100"]}'

# Query the ledger
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"function":"ReadAsset","Args":["asset1"]}'

Deployment Automation

For production environments, it's recommended to automate the deployment process using scripts or tools.

Deployment Scripts

Create shell scripts to automate the deployment process:

#!/bin/bash
# network.sh - Script to deploy a Hyperledger Fabric network

# Function to generate crypto material
function generateCrypto() {
  echo "Generating crypto material..."
  cryptogen generate --config=./crypto-config.yaml --output=./crypto-config
}

# Function to generate genesis block and channel transactions
function generateGenesisBlock() {
  echo "Generating genesis block..."
  configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block

  echo "Generating channel transaction..."
  configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel1.tx -channelID channel1

  echo "Generating anchor peer updates..."
  configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID channel1 -asOrg Org1MSP
  configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID channel1 -asOrg Org2MSP
}

# Function to start the network
function networkUp() {
  echo "Starting the network..."
  docker-compose -f docker-compose.yaml up -d
}

# Function to create and join channel
function createChannel() {
  echo "Creating channel..."
  docker exec cli peer channel create -o orderer.example.com:7050 -c channel1 -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/channel1.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

  echo "Joining peer0.org1 to channel..."
  docker exec cli peer channel join -b channel1.block

  echo "Joining peer0.org2 to channel..."
  docker exec -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 -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:9051 cli peer channel join -b channel1.block

  echo "Updating anchor peers..."
  docker exec cli peer channel update -o orderer.example.com:7050 -c channel1 -f /opt/gopath/src/github.com/hyperledger/fabric/peer/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

  docker exec -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 -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:9051 cli peer channel update -o orderer.example.com:7050 -c channel1 -f /opt/gopath/src/github.com/hyperledger/fabric/peer/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
}

# Function to deploy chaincode
function deployChaincode() {
  echo "Packaging chaincode..."
  docker exec cli peer lifecycle chaincode package mycc.tar.gz --path /opt/gopath/src/github.com/chaincode/mycc/ --lang golang --label mycc_1.0

  echo "Installing chaincode on peer0.org1..."
  docker exec cli peer lifecycle chaincode install mycc.tar.gz

  echo "Installing chaincode on peer0.org2..."
  docker exec -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 -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:9051 cli peer lifecycle chaincode install mycc.tar.gz

  echo "Getting package ID..."
  CC_PACKAGE_ID=$(docker exec cli peer lifecycle chaincode queryinstalled | grep mycc_1.0 | awk '{print $3}' | sed 's/,//')

  echo "Approving chaincode for Org1..."
  docker exec cli peer lifecycle chaincode approveformyorg -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 --channelID channel1 --name mycc --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1

  echo "Approving chaincode for Org2..."
  docker exec -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 -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:9051 cli peer lifecycle chaincode approveformyorg -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 --channelID channel1 --name mycc --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1

  echo "Committing chaincode definition..."
  docker exec cli peer lifecycle chaincode commit -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 --channelID channel1 --name mycc --version 1.0 --sequence 1 --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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

  echo "Initializing chaincode..."
  docker exec cli peer chaincode invoke -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 channel1 -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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'
}

# Function to stop the network
function networkDown() {
  echo "Stopping the network..."
  docker-compose -f docker-compose.yaml down --volumes --remove-orphans
}

# Main script logic
case "$1" in
  "up")
    generateCrypto
    generateGenesisBlock
    networkUp
    createChannel
    deployChaincode
    ;;
  "down")
    networkDown
    ;;
  *)
    echo "Usage: $0 [up|down]"
    ;;
esac

Using Ansible for Deployment

For more complex deployments, consider using Ansible:

# playbook.yml
---
- name: Deploy Hyperledger Fabric Network
  hosts: fabric_nodes
  become: yes
  tasks:
    - name: Install prerequisites
      apt:
        name:
          - docker.io
          - docker-compose
          - golang-go
          - git
        state: present
        update_cache: yes

    - name: Create fabric directory
      file:
        path: /opt/fabric
        state: directory
        mode: '0755'

    - name: Copy configuration files
      copy:
        src: "{{ item }}"
        dest: /opt/fabric/
      with_items:
        - crypto-config.yaml
        - configtx.yaml
        - docker-compose.yaml

    - name: Download Fabric binaries
      shell: |
        cd /opt/fabric
        curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.5.0 1.5.5
      args:
        creates: /opt/fabric/bin/peer

    - name: Generate crypto material
      shell: |
        cd /opt/fabric
        ./bin/cryptogen generate --config=./crypto-config.yaml --output=./crypto-config
      args:
        creates: /opt/fabric/crypto-config

    - name: Generate genesis block
      shell: |
        cd /opt/fabric
        export FABRIC_CFG_PATH=/opt/fabric
        ./bin/configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
      args:
        creates: /opt/fabric/system-genesis-block/genesis.block

    - name: Start the network
      shell: |
        cd /opt/fabric
        docker-compose -f docker-compose.yaml up -d
      args:
        creates: /var/lib/docker/volumes/fabric_orderer.example.com

Deployment Considerations for Production

When deploying a Hyperledger Fabric network in production, consider the following:

High Availability

  • Deploy multiple orderer nodes with Raft consensus
  • Use load balancers for client connections
  • Implement peer redundancy across organizations
  • Set up database replication for CouchDB
  • Use container orchestration platforms like Kubernetes

Security

  • Use Hardware Security Modules (HSMs) for key management
  • Implement network segmentation and firewalls
  • Enable TLS for all communications
  • Regularly rotate TLS certificates
  • Implement proper access control with MSPs
  • Use private data collections for sensitive information

Monitoring and Logging

  • Set up centralized logging with ELK stack or similar
  • Implement metrics collection with Prometheus
  • Create dashboards with Grafana
  • Set up alerts for critical issues
  • Monitor resource usage and performance

Backup and Recovery

  • Regularly backup cryptographic material
  • Create snapshots of the ledger
  • Document recovery procedures
  • Test recovery processes
  • Implement disaster recovery plans

Scalability

  • Design for horizontal scaling
  • Optimize batch size and timeout for transaction throughput
  • Use appropriate hardware for orderers and peers
  • Implement proper caching strategies
  • Consider channel design for data isolation

By following these deployment guidelines, you can create a robust, secure, and scalable Hyperledger Fabric network that meets your production requirements. In the next section, we'll explore how to manage and maintain this network over time.