-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Koushik Gavini <koushikgavini@koushiks-mbp.jerboa-altered.ts.net>
- Loading branch information
Koushik Gavini
committed
Aug 28, 2024
1 parent
bbf2300
commit f80735e
Showing
1 changed file
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
# Operational Runbook: Migrating from Raft to BFT in Hyperledger Fabric | ||
|
||
## Prerequisites | ||
|
||
- A running Fabric network with Raft consensus | ||
- Administrative access to the ordering service | ||
- Fabric version 3.0.0 or higher on all nodes | ||
- Backup of the current system | ||
|
||
## Step 1: Prepare the Environment | ||
|
||
```bash | ||
export FABRIC_CFG_PATH=$PWD/config | ||
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 | ||
export CHANNEL_NAME=mychannel | ||
``` | ||
|
||
## Step 2: Verify Current Consensus Type and Consenter Mapping | ||
|
||
```bash | ||
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA | ||
|
||
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > current_config.json | ||
|
||
# Check current consensus type | ||
jq '.channel_group.groups.Orderer.values.ConsensusType.value.type' current_config.json | ||
|
||
# Check current consenter mapping | ||
jq '.channel_group.groups.Orderer.values.Orderers.value.consenter_mapping' current_config.json | ||
``` | ||
|
||
## Step 3: Enter Maintenance Mode | ||
|
||
```bash | ||
cp current_config.json modified_config.json | ||
|
||
jq '.channel_group.groups.Orderer.values.ConsensusType.value.state = "STATE_MAINTENANCE"' modified_config.json > updated_config.json | ||
|
||
configtxlator proto_encode --input current_config.json --type common.Config --output current_config.pb | ||
configtxlator proto_encode --input updated_config.json --type common.Config --output updated_config.pb | ||
configtxlator compute_update --channel_id $CHANNEL_NAME --original current_config.pb --updated updated_config.pb --output config_update.pb | ||
|
||
peer channel signconfigtx -f config_update.pb | ||
peer channel update -f config_update.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA | ||
``` | ||
|
||
## Step 4: Backup the System | ||
|
||
```bash | ||
docker stop $(docker ps -q --filter name=orderer) | ||
tar -czf orderer_backup.tar.gz /var/hyperledger/production/orderer | ||
docker start $(docker ps -aq --filter name=orderer) | ||
``` | ||
|
||
## Step 5: Switch to BFT and Update Consenter Mapping | ||
|
||
```bash | ||
# Prepare the new consenter mapping | ||
cat << EOF > consenter_mapping.json | ||
[ | ||
{ | ||
"id": 1, | ||
"host": "orderer1.example.com", | ||
"port": 7050, | ||
"msp_id": "OrdererMSP", | ||
"identity": "base64_encoded_identity", | ||
"client_tls_cert": "base64_encoded_client_cert", | ||
"server_tls_cert": "base64_encoded_server_cert" | ||
}, | ||
{ | ||
"id": 2, | ||
"host": "orderer2.example.com", | ||
"port": 7050, | ||
"msp_id": "OrdererMSP", | ||
"identity": "base64_encoded_identity", | ||
"client_tls_cert": "base64_encoded_client_cert", | ||
"server_tls_cert": "base64_encoded_server_cert" | ||
}, | ||
{ | ||
"id": 3, | ||
"host": "orderer3.example.com", | ||
"port": 7050, | ||
"msp_id": "OrdererMSP", | ||
"identity": "base64_encoded_identity", | ||
"client_tls_cert": "base64_encoded_client_cert", | ||
"server_tls_cert": "base64_encoded_server_cert" | ||
}, | ||
{ | ||
"id": 4, | ||
"host": "orderer4.example.com", | ||
"port": 7050, | ||
"msp_id": "OrdererMSP", | ||
"identity": "base64_encoded_identity", | ||
"client_tls_cert": "base64_encoded_client_cert", | ||
"server_tls_cert": "base64_encoded_server_cert" | ||
} | ||
] | ||
EOF | ||
|
||
# Update the config with new consensus type, metadata, and consenter mapping | ||
jq --slurpfile mapping consenter_mapping.json ' | ||
.channel_group.groups.Orderer.values.ConsensusType.value.type = "BFT" | | ||
.channel_group.groups.Orderer.values.ConsensusType.value.metadata = { | ||
"options": { | ||
"election_tick": 10, | ||
"heartbeat_tick": 1, | ||
"max_inflight_blocks": 5, | ||
"snapshot_interval_size": 16777216 | ||
} | ||
} | | ||
.channel_group.groups.Orderer.values.Orderers.value.consenter_mapping = $mapping[0] | ||
' updated_config.json > bft_config.json | ||
|
||
# Create and submit the config update | ||
configtxlator proto_encode --input current_config.json --type common.Config --output current_config.pb | ||
configtxlator proto_encode --input bft_config.json --type common.Config --output updated_config.pb | ||
configtxlator compute_update --channel_id $CHANNEL_NAME --original current_config.pb --updated updated_config.pb --output config_update.pb | ||
|
||
peer channel signconfigtx -f config_update.pb | ||
peer channel update -f config_update.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA | ||
``` | ||
|
||
## Step 6: Restart and Validate | ||
|
||
```bash | ||
docker restart $(docker ps -q --filter name=orderer) | ||
|
||
# Check logs for all orderers | ||
for orderer in orderer1 orderer2 orderer3 orderer4; do | ||
echo "Checking logs for $orderer" | ||
docker logs -f $orderer 2>&1 | grep -E "SmartBFT-v3 is now servicing chain|Message from leader" | ||
done | ||
``` | ||
|
||
## Step 7: Exit Maintenance Mode | ||
|
||
```bash | ||
jq '.channel_group.groups.Orderer.values.ConsensusType.value.state = "STATE_NORMAL"' bft_config.json > normal_config.json | ||
|
||
configtxlator proto_encode --input bft_config.json --type common.Config --output current_config.pb | ||
configtxlator proto_encode --input normal_config.json --type common.Config --output updated_config.pb | ||
configtxlator compute_update --channel_id $CHANNEL_NAME --original current_config.pb --updated updated_config.pb --output config_update.pb | ||
|
||
peer channel signconfigtx -f config_update.pb | ||
peer channel update -f config_update.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA | ||
``` | ||
|
||
## Step 8: Verify Migration | ||
|
||
```bash | ||
peer channel fetch config latest_config.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA | ||
|
||
configtxlator proto_decode --input latest_config.pb --type common.Block | jq '.data.data[0].payload.data.config.channel_group.groups.Orderer.values.ConsensusType, .data.data[0].payload.data.config.channel_group.groups.Orderer.values.Orderers' | ||
``` | ||
|
||
## Notes: | ||
|
||
1. Ensure all ordering nodes are running Fabric v3.0.0 or higher before migration. | ||
2. This process should be performed during a maintenance window to minimize disruption. | ||
3. The migration is irreversible. Ensure you have a proper backup before proceeding. | ||
4. The number of consenters in the BFT configuration should be 3f + 1, where f is the number of tolerated failures. In this example, we use 4 consenters, tolerating 1 failure. | ||
5. Test this process in a non-production environment first. |