mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-18 07:55:10 +00:00
* Run the fabric test network on Kubernetes Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * Re-LINT Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>
206 lines
No EOL
9.3 KiB
Markdown
206 lines
No EOL
9.3 KiB
Markdown
# Channels
|
|
|
|
Once the test network peers and orderers have been started, and the network identities have been registered
|
|
and enrolled with the ECert CA, we can construct a channel linking the participants of the test network
|
|
blockchain.
|
|
|
|
## TL/DR :
|
|
|
|
```shell
|
|
$ export TEST_NETWORK_CHANNEL_NAME="mychannel"
|
|
|
|
$ ./network channel create
|
|
Creating channel "mychannel":
|
|
✅ - Creating channel MSP ...
|
|
✅ - Aggregating channel MSP ...
|
|
✅ - Launching admin CLIs ...
|
|
✅ - Creating channel "mychannel" ...
|
|
✅ - Joining org1 peers to channel "mychannel" ...
|
|
✅ - Joining org2 peers to channel "mychannel" ...
|
|
🏁 - Channel is ready.
|
|
```
|
|
|
|
## Process Overview
|
|
|
|
In order to construct a communication channel, the following steps must be performed:
|
|
|
|
1. TLS and MSP public certificates must be aggregated and distributed to all participants in the network.
|
|
|
|
2. Each organization will launch a command-line pod with the MSP environment such that all fabric binaries are
|
|
executed as the Admin user.
|
|
|
|
3. The channel genesis block is constructed from `configtx.yaml`, and `osnadmin` is used to distribute the new
|
|
channel configuration block to all orderers in the network.
|
|
|
|
4. The network peers fetch the genesis block from the orderers, and use the configuration to join the channel.
|
|
|
|
|
|
## Distributing Channel MSP
|
|
```shell
|
|
✅ - Creating channel MSP ...
|
|
✅ - Aggregating channel MSP ...
|
|
```
|
|
|
|
One of the responsibilities of a Hyperledger Fabric _Consortium Organizer_ is to distribute the public MSP and
|
|
TLS certificates to organizations participating in a blockchain. In the Docker composed based test network, or
|
|
systems bootstrapped with the `cryptogen` command, all of the public certificates will be available on a common
|
|
file system or volume share. In our Kubernetes test network, each organization maintains the cryptographic
|
|
assets on a distinct persistent volume, invisible to other the other participants in the network.
|
|
|
|
To distribute the TLS and MSP _public_ certificates, the test network emulates the responsibilities of the
|
|
consortium organizer by constructing a [Channel MSP](https://hyperledger-fabric.readthedocs.io/en/latest/membership/membership.html#channel-msps)
|
|
structure, extracting the relevant certificate files into a single `msp-{org}.tar.gz` archive. This MSP
|
|
archive is then relayed to network participants, where it can be extracted and used to set the MSP context
|
|
in which the peer executes administrative commands.
|
|
|
|
The kube-specific techniques employed in MSP [construction](link) and [distribution](link) are:
|
|
|
|
- Channel MSP is generated by piping shell commands into each org's ECert CA pod.
|
|
- Channel MSP is extracted to the local system by piping the output of `tar` through `kubectl` (equivalent
|
|
to the [kubectl cp command](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#cp)).
|
|
MSP archives are saved locally in `/build/msp-{org}.tar.gz` archives.
|
|
- Channel MSP is distributed across network participants by transferring the MSP archive files from
|
|
`build/msp/msp-{org}.tgz` into the cluster as a config map.
|
|
- An `initContainer` is launched in each organization's Admin CLI pod, unfurling the MSP context from the
|
|
`msp-config` config map into the local volume.
|
|
|
|
Despite this additional complexity, this technique allows us to carefully target the MSP context in which
|
|
remote peer commands execute. The construct of an _MSP Archive_ may be extended to other circumstances
|
|
in which a consortium organizer transfers the _public_ certificates in an out-of-band fashion to
|
|
participants of a blockchain network.
|
|
|
|
Aggregating the certificates as a local MSP archive is accomplished by piping a `tar` archive from the output
|
|
of a remote `kubectl` into a local archive files. These files are then mounted into the Kube namespace by
|
|
constructing the `msp-config` config map:
|
|
|
|
```shell
|
|
kubectl -n $NS exec deploy/org0-ecert-ca -- tar zcvf - -C /var/hyperledger/fabric organizations/ordererOrganizations/org0.example.com/msp > msp/msp-org0.example.com.tgz
|
|
kubectl -n $NS exec deploy/org1-ecert-ca -- tar zcvf - -C /var/hyperledger/fabric organizations/peerOrganizations/org1.example.com/msp > msp/msp-org1.example.com.tgz
|
|
kubectl -n $NS exec deploy/org2-ecert-ca -- tar zcvf - -C /var/hyperledger/fabric organizations/peerOrganizations/org2.example.com/msp > msp/msp-org2.example.com.tgz
|
|
|
|
kubectl -n $NS delete configmap msp-config || true
|
|
kubectl -n $NS create configmap msp-config --from-file=msp/```
|
|
```
|
|
|
|
|
|
## `Admin` Commands
|
|
```shell
|
|
✅ - Launching admin CLIs ...
|
|
```
|
|
|
|
After the channel MSP archives have been constructed and loaded into the `msp-config` ConfigMap, a series
|
|
of kubernetes pods are launched in the namespace with an environment suitable for running the Fabric
|
|
`peer` commands as the organization Administrator. Before starting the CLI admin container, an `initContainer`
|
|
reads the MSP archives and unfurls them into a location on the org's persistent volume:
|
|
|
|
```yaml
|
|
# This init container will unfurl all of the MSP archives listed in the msp-config config map.
|
|
initContainers:
|
|
- name: msp-unfurl
|
|
image: busybox
|
|
command:
|
|
- sh
|
|
- -c
|
|
- "for msp in $(ls /msp/msp-*.tgz); do echo $msp && tar zxvf $msp -C /var/hyperledger/fabric; done"
|
|
volumeMounts:
|
|
- name: msp-config
|
|
mountPath: /msp
|
|
- name: fabric-volume
|
|
mountPath: /var/hyperledger
|
|
```
|
|
|
|
Once the MSP archives are extracted, the CLI is launched and the environment set such that `peer` commands
|
|
will be executed with the organization's Administrative role.
|
|
|
|
```shell
|
|
cat kube/org0/org0-admin-cli.yaml | sed 's,{{FABRIC_VERSION}},'${FABRIC_VERSION}',g' | kubectl -n $NS apply -f -
|
|
cat kube/org1/org1-admin-cli.yaml | sed 's,{{FABRIC_VERSION}},'${FABRIC_VERSION}',g' | kubectl -n $NS apply -f -
|
|
cat kube/org2/org2-admin-cli.yaml | sed 's,{{FABRIC_VERSION}},'${FABRIC_VERSION}',g' | kubectl -n $NS apply -f -
|
|
```
|
|
|
|
## Create the Channel
|
|
```shell
|
|
✅ - Creating channel "mychannel" ...
|
|
```
|
|
|
|
As the _consortium leader_ org0, we create the channel's genesis block and use the orderer admin REST
|
|
services to register the channel genesis block configuration on the ordering nodes:
|
|
|
|
```shell
|
|
configtxgen -profile TwoOrgsApplicationGenesis -channelID '${CHANNEL_NAME}' -outputBlock genesis_block.pb
|
|
|
|
osnadmin channel join --orderer-address org0-orderer1:9443 --channelID '${CHANNEL_NAME}' --config-block genesis_block.pb
|
|
osnadmin channel join --orderer-address org0-orderer2:9443 --channelID '${CHANNEL_NAME}' --config-block genesis_block.pb
|
|
osnadmin channel join --orderer-address org0-orderer3:9443 --channelID '${CHANNEL_NAME}' --config-block genesis_block.pb
|
|
```
|
|
|
|
|
|
## Join Peers
|
|
|
|
```shell
|
|
✅ - Joining org1 peers to channel "mychannel" ...
|
|
✅ - Joining org2 peers to channel "mychannel" ...
|
|
```
|
|
|
|
After the channel configurations have been registered with the network orderers, we will join the peers to the channel
|
|
by retrieving the genesis block from the orderers and then joining the channel:
|
|
|
|
```shell
|
|
# Fetch the genesis block from an orderer
|
|
peer channel \
|
|
fetch oldest \
|
|
genesis_block.pb \
|
|
-c '${CHANNEL_NAME}' \
|
|
-o org0-orderer1:6050 \
|
|
--tls --cafile /var/hyperledger/fabric/organizations/ordererOrganizations/org0.example.com/msp/tlscacerts/org0-tls-ca.pem
|
|
|
|
# Join peer1 to the channel.
|
|
CORE_PEER_ADDRESS='${org}'-peer1:7051 \
|
|
peer channel \
|
|
join \
|
|
-b genesis_block.pb \
|
|
-o org0-orderer1:6050 \
|
|
--tls --cafile /var/hyperledger/fabric/organizations/ordererOrganizations/org0.example.com/msp/tlscacerts/org0-tls-ca.pem
|
|
|
|
# Join peer2 to the channel.
|
|
CORE_PEER_ADDRESS='${org}'-peer2:7051 \
|
|
peer channel \
|
|
join \
|
|
-b genesis_block.pb \
|
|
-o org0-orderer1:6050 \
|
|
--tls --cafile /var/hyperledger/fabric/organizations/ordererOrganizations/org0.example.com/msp/tlscacerts/org0-tls-ca.pem
|
|
```
|
|
|
|
|
|
## Set Anchor Peers (Optional)
|
|
```shell
|
|
$ ./network anchor peer2
|
|
✅ - Updating anchor peers to "peer2" ...
|
|
```
|
|
|
|
In the test network, the configtx.yaml sets the organization [Anchor Peers](https://hyperledger-fabric.readthedocs.io/en/latest/glossary.html?highlight=anchor#anchor-peer)
|
|
to "peer1" in the genesis block. As such, no additional configuration is necessary for neighboring
|
|
organizations to discover additional peers in the network.
|
|
|
|
However, the process of setting the anchor peers on a channel requires a more complicated scripting process, so we
|
|
have included in the test network a mechanism to illustrate how anchor peers may be set on a network after a
|
|
channel has been constructed.
|
|
|
|
Up to this point in the network configuration, the shell scripts orchestrating the remote volumes, peers, and
|
|
admin commands have all been executed by piping a sequence of commands into an existing pod directly
|
|
into the input of a `kubectl` command. For small command sets this is adequate, but for the more complicated
|
|
process of registering a channel anchor peer, we have elected to use a different approach to launch the peer
|
|
update scripts on the kubernetes cluster.
|
|
|
|
When updating anchor peers, the `./network` script will:
|
|
|
|
1. Transfer the shell scripts from `/scripts/*.sh` into the remote organization's persistent volume.
|
|
2. Issue a `kubectl exec -c "script-name.sh {args}"` on the org's admin CLI pod.
|
|
|
|
For non-trivial Fabric administative tasks, this approach of uploading a script into the cluster and then
|
|
executing in an admin pod works well.
|
|
|
|
|
|
## Next Steps
|
|
|
|
### [Working with Chaincode](CHAINCODE.md) |