Create a sample network with CRDs, fabric-operator, and the Kube API server:
- Apply
kustomization
overlays to install the Operator - Apply
kustomization
overlays to construct a Fabric Network - Call
peer
CLI and channel participation SDKs to administer the network - Deploy Chaincode-as-a-Service smart contracts
- Develop Gateway Client applications on a local workstation
Feedback, comments, questions, etc. at Discord : #fabric-kubernetes
- kubectl
- jq
- envsubst (
brew install gettext
on OSX) - k9s (recommended)
- Fabric binaries (peer, osnadmin, etc.) will be installed into the local
bin
folder. Add these to your PATH:
export PATH=$PWD:$PWD/bin:$PATH
If you do not have access to a Kubernetes cluster, create a local instance with KIND and Docker (+ resources to 8 CPU / 8GRAM):
network kind
For additional cluster options, see the detailed guidelines for:
- Rancher Desktop: k3s
- fabric-devenv: vagrant VM
- IKS
- EKS
- OCP
The operator utilizes Kubernetes Ingress
resources to expose Fabric services at a common DNS wildcard domain
(e.g. *.test-network.example.com
). For convenience, the sample network includes an Nginx ingress controller,
pre-configured with ssl-passthrough
for TLS termination at the node endpoints.
For local clusters, set the ingress wildcard domain to the host loopback interface (127.0.0.1):
export TEST_NETWORK_INGRESS_DOMAIN=localho.st
For cloud-based clusters, set the ingress wildcard domain to the public DNS A record:
export TEST_NETWORK_INGRESS_DOMAIN=test-network.example.com
For additional guidelines on configuring ingress and DNS, see Considerations for Kubernetes Distributions.
Install the Nginx controller and Fabric CRDs:
network cluster init
Launch the operator and kustomize
a network of CAs, peers, and orderers:
network up
Explore Kubernetes Pods
, Deployments
, Services
, Ingress
, etc.:
kubectl -n test-network get all
In the examples below, the peer
binary will be used to invoke smart contracts on the org1-peer1 ledger. Set the CLI context with:
export FABRIC_CFG_PATH=${PWD}/temp/config
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_ADDRESS=test-network-org1-peer1-peer.${TEST_NETWORK_INGRESS_DOMAIN}:443
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_MSPCONFIGPATH=${PWD}/temp/enrollments/org1/users/org1admin/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/temp/channel-msp/peerOrganizations/org1/msp/tlscacerts/tlsca-signcert.pem
The operator is compatible with sample Chaincode-as-a-Service smart contracts and the ccaas
external builder.
When using the ccaas builder, the chaincode pods must be started and running in the cluster
before the contract can be approved on the channel.
Clone the fabric-samples git repository:
git clone https://github.com/hyperledger/fabric-samples.git /tmp/fabric-samples
Create a channel:
network channel create
Deploy a sample contract:
network cc deploy asset-transfer-basic basic_1.0 /tmp/fabric-samples/asset-transfer-basic/chaincode-java
network cc metadata asset-transfer-basic
network cc invoke asset-transfer-basic '{"Args":["InitLedger"]}'
network cc query asset-transfer-basic '{"Args":["ReadAsset","asset1"]}' | jq
Or use the native peer
CLI to query the contract installed on org1 / peer1:
peer chaincode query -n asset-transfer-basic -C mychannel -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}'
The operator can also be configured for use with fabric-builder-k8s,
providing smooth and immediate Chaincode Right Now! deployments. With the k8s
builder, the peer node will directly
manage the lifecycle of the chaincode pods.
Reconstruct the network with the "k8s-fabric-peer" image:
network down
export TEST_NETWORK_PEER_IMAGE=ghcr.io/hyperledgendary/k8s-fabric-peer
export TEST_NETWORK_PEER_IMAGE_LABEL=v0.6.0
network up
network channel create
Download a "k8s" chaincode package:
curl -fsSL https://github.com/hyperledgendary/conga-nft-contract/releases/download/v0.1.1/conga-nft-contract-v0.1.1.tgz -o conga-nft-contract-v0.1.1.tgz
Install the smart contract:
peer lifecycle chaincode install conga-nft-contract-v0.1.1.tgz
export PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid conga-nft-contract-v0.1.1.tgz) && echo $PACKAGE_ID
peer lifecycle \
chaincode approveformyorg \
--channelID mychannel \
--name conga-nft-contract \
--version 1 \
--package-id ${PACKAGE_ID} \
--sequence 1 \
--orderer test-network-org0-orderersnode1-orderer.${TEST_NETWORK_INGRESS_DOMAIN}:443 \
--tls --cafile $PWD/temp/channel-msp/ordererOrganizations/org0/orderers/org0-orderersnode1/tls/signcerts/tls-cert.pem \
--connTimeout 15s
peer lifecycle \
chaincode commit \
--channelID mychannel \
--name conga-nft-contract \
--version 1 \
--sequence 1 \
--orderer test-network-org0-orderersnode1-orderer.${TEST_NETWORK_INGRESS_DOMAIN}:443 \
--tls --cafile $PWD/temp/channel-msp/ordererOrganizations/org0/orderers/org0-orderersnode1/tls/signcerts/tls-cert.pem \
--connTimeout 15s
Inspect chaincode pods:
kubectl -n test-network describe pods -l app.kubernetes.io/created-by=fabric-builder-k8s
Query the smart contract:
peer chaincode query -n conga-nft-contract -C mychannel -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}'
Invariably, something in the recipe above will go awry. Look for additional diagnostics in network-debug.log and reset the stage with:
network down
or
network unkind
Launch the Fabric Operations Console:
network console
- open
https://test-network-hlf-console-console.${TEST_NETWORK_INGRESS_DOMAIN}
- Accept the self-signed TLS certificate
- Log in as
admin:password
- Build a network
An excellent alternative for local development is the k3s distribution bundled with Rancher Desktop.
- Increase cluster resources to 8 CPU / 8GRAM
- Select mobyd or containerd runtime
- Disable the Traefik ingress
- Restart Kubernetes
For use with mobyd / Docker container:
export TEST_NETWORK_CLUSTER_RUNTIME="k3s"
export TEST_NETWORK_STAGE_DOCKER_IMAGES="false"
export TEST_NETWORK_STORAGE_CLASS="local-path"
For use with containerd:
export TEST_NETWORK_CLUSTER_RUNTIME="k3s"
export TEST_NETWORK_CONTAINER_CLI="nerdctl"
export TEST_NETWORK_CONTAINER_NAMESPACE="--namespace k8s.io"
export TEST_NETWORK_STAGE_DOCKER_IMAGES="false"
export TEST_NETWORK_STORAGE_CLASS="local-path"
For installations at IBM Cloud, use the following configuration settings:
export TEST_NETWORK_CLUSTER_RUNTIME="k3s"
export TEST_NETWORK_COREDNS_DOMAIN_OVERRIDE="false"
export TEST_NETWORK_STAGE_DOCKER_IMAGES="false"
export TEST_NETWORK_STORAGE_CLASS="ibm-file-gold"
To determine the external IP address for the Nginx ingress controller:
- Run
network cluster init
to create the Nginx resources - Determine the IP address for the Nginx EXTERNAL-IP:
INGRESS_IPADDR=$(kubectl -n ingress-nginx get svc/ingress-nginx-controller -o json | jq -r .status.loadBalancer.ingress[0].ip)
- Set a virtual host domain resolving
*.EXTERNAL-IP.nip.io
or a public DNS wildcard resolver:
export TEST_NETWORK_INGRESS_DOMAIN=$(echo $INGRESS_IPADDR | tr -s '.' '-').nip.io
For additional guidelines on configuring ingress and DNS, see Considerations for Kubernetes Distributions.
For installations at Amazon's Elastic Kubernetes Service, use the following settings:
export TEST_NETWORK_CLUSTER_RUNTIME="k3s"
export TEST_NETWORK_COREDNS_DOMAIN_OVERRIDE="false"
export TEST_NETWORK_STAGE_DOCKER_IMAGES="false"
export TEST_NETWORK_STORAGE_CLASS="gp2"
As an alternative to registering a public DNS domain with Route 54, the Dead simple wildcard DNS for any IP Address
service may be used to associate the Nginx external IP with an nip.io
domain.
To determine the external IP address for the ingress controller:
- Run
network cluster init
to create the Nginx resources. - Wait for the ingress to come up and the hostname to propagate through public DNS (this will take a few minutes.)
- Determine the IP address for the Nginx EXTERNAL-IP:
INGRESS_HOSTNAME=$(kubectl -n ingress-nginx get svc/ingress-nginx-controller -o json | jq -r .status.loadBalancer.ingress[0].hostname)
INGRESS_IPADDR=$(dig $INGRESS_HOSTNAME +short)
- Set a virtual host domain resolving
*.EXTERNAL-IP.nip.io
to the ingress IP:
export TEST_NETWORK_INGRESS_DOMAIN=$(echo $INGRESS_IPADDR | tr -s '.' '-').nip.io
For additional guidelines on configuring ingress and DNS, see Considerations for Kubernetes Distributions.
The fabric-devenv project will create a local development Virtual Machine, including all required prerequisites for running a KIND cluster and the sample network.
To work around an issue resolving the kube DNS hostnames in vagrant, override the internal DNS name for Fabric services with:
export TEST_NETWORK_KUBE_DNS_DOMAIN=test-network
- The
network
script prints output and progress to anetwork-debug.log
file. In a second shell:
tail -f network-debug.log
- Tail the operator logging output:
kubectl -n test-network logs -f deployment/fabric-operator
-
On OSX, there is a bug in the Golang DNS resolver (Fabric #3372 and Golang #43398), causing the Fabric binaries to occasionally stall out when querying DNS. This issue can cause
osnadmin
/ channel join to time out, throwing an error when joining the channel. Fix this by turning a build of fabric binaries and copying the build outputs fromfabric/build/bin/*
-->sample-network/bin
-
Both Fabric and Kubernetes are complex systems. On occasion, things don't always work as they should, and it's impossible to enumerate all failure cases that can come up in the wild. When something in kube doesn't come up correctly, use the k9s (or another K8s navigator) to browse deployments, pods, services, and logs. Usually hitting
d
(describe) on a stuck resource in thetest-network
namespace is enough to determine the source of the error.