Bài 7. Triển khai Hyperledger Fabric lên Kubernetes.

1. Giới thiệu

Như chúng ta đã biết, các thành phần trong network của Hyperledger Fabric đều chạy trên môi trường docker, nên phải luôn đảm bảo rằng các container vẫn đang trong trạng thái hoạt động, vì chỉ cần một thành phần trong đó "chết" thì cả network có thể tê liệt hoàn toàn.

Điều này bắt buộc ta phải có cơ chế để quản lý tốt các container, khi có một container chết thì phải up nó lên ngay lập tức. Thật may là Kubernetes có thể làm được điều đó.

Ở bài này mình sẽ không đi sâu vào tìm hiểu về Kubernetes, nên trước khi đọc bài này mình khuyên các bạn hãy tự tìm hiểu sơ qua về các khái niệm và thành phần của kubernetes trước.

Để có thể test được ở máy cá nhân thì bạn nên cài đặt minikube (môi trường kubernetes) và kubectl (công cụ để tương tác được với môi trường kubernetes) trên máy của mình.

Sau khi cài đặt xong, các bạn chạy:

$ minikube start

để start môi trường kubernetes. Sau đó chạy lệnh sau để terminal nhảy vào môi trường kubernetes:

$ eval $(minikuber docker-env)

Kết thúc bài này các bạn chạy:

$ minikube stop

để stop minikube cho đỡ lag máy. Yên tâm là tất cả những gì bạn làm sẽ không bị mất đi.

2. Thực hiện

2.1 Chuẩn bị

Bạn clone project mẫu mà mình đã chuẩn bị để thực hành cho dễ.
hyperledger-fabric-k8s
Kiểm tra xem môi trường minikube đã hoạt động chưa, chạy:

$ kubectl get nodes

Kết quả sẽ trả về các nodes đang chạy. Nếu không bạn sẽ phải chạy:

$ minikube start
$ cd hyperledger-fabric-k8s/network

2.2 Tạo Persistent Volume cho Network

Như chúng ta đã biết hạn chế của môi trường docker thông thường là các container có thể chết bất cứ lúc nào, chỉ cần chết một thành phần nào đó thì network có thể tê liệt, việc backup và restore bằng tay dường như là không hiểu quả, container trong k8s cũng hay chết, thậm chí tần suất chết còn cao hơn cả môi trường docker bình thường, nhưng trong k8s có một khái niệm là persistent volume giúp chúng lưu trữ dữ liệu quan trọng của các container, để khi một container nào đó chết và tự động được start lại, nó sẽ vẫn có đủ dữ liệu vốn trước khi chết nó có. PersistentVolume được lưu trong shared filesystem. Nghĩa là miễn là container nào có quyền thì nó đều có thể truy cập vào persistem volume đó.

Chúng ta sẽ apply một PersistentVolume với nội dung là file kubernetes/fabric-pv.yaml, persistentvolume có chức năng bảo vệ dữ liệu tuyệt đối để backup-restore cho các pods:

kind: PersistentVolume
apiVersion: v1
metadata:
  name: fabric-pv
  labels:
    type: local
    name: fabricfiles
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /nfs/fabric  #Thư mục được bảo vệ trong server NFS
    server: storage.local.parisi.biz
    readOnly: false


Thư mục /nfs/fabric lưu trữ những dữ liệu quan trọng. Xem thêm tại docs
Thực hiện lệnh sau để apply:

$ kubectl apply -f kubernetes/fabric.pv.yaml

Kiểm tra bằng cách:

$ kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
fabric-pv   10Gi       RWX            Retain           Available                                   32s

Lúc này nếu thực hiện kubectl get pv bạn sẽ thấy có trong danh sách có fabric-pv

Tiếp theo cần phải apply một PersistentVolumeClaim (pvc) cho PersistentVolume (pv) vừa mới apply, có PersistentVolumeClaim thì PersistentVolume mới có thể hoạt động. Nội dung file kubernetes/fabric-pvc.yaml:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: fabric-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Mi
  selector:
    matchLabels:
      name: fabricfiles


Bạn có thể điểu chỉnh mức storage sao cho phù hợp với tài nguyên máy tính của mình. Lưu ý trong Kubernetes các resources đều match với nhau bằng labels của chúng, labels có chức năng như một định danh, nên cần phải cẩn thận để labels được match chính xác. Ở pv và pvc được match với nhau bằng labelfabricfiles

Chạy lệnh sau để apply:

$ kubectl apply -f kubernetes/fabric-pvc.yaml

Kiểm tra bằng cách

$ kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
fabric-pvc   Bound    pvc-9b477960-f0a1-460a-a330-27a555eddc2b   10Gi       RWX            standard       80s

2.3 Tạo Persistent Volume cho các peers

Nếu trước đây khi chạy một network Fabric ở môi trường bình thường, bạn chịu khó mày mò, bạn sẽ thấy được rằng toàn bộ thông tin quan trọng của một peer nào đó đều được lưu trữ trong thư mục /var trên container đang chạy peer đó.

Vì thế, chúng ta sẽ sử dụng persistent volume cho thư mục /var của mỗi peer để bảo vệ dữ liệu của chúng.

Nội dung của một cặp pv, pvc cho org1peer0 sẽ như sau:

File kubernetes/backup-org1peer0-pv.yaml:

kind: PersistentVolume
apiVersion: v1
metadata:
  name: org1peer0-pv
  labels:
    type: local
    name: org1peer0files
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /nfs/org1peer0/var
    server: storage.local.parisi.biz
    readOnly: false

File kubernetes/backup-org1peer0-pvc.yaml:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: org1peer0-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      name: org1peer0files

Sau đó chạy các lệnh sau:

$ kubectl apply -f kubernetes/backup-org1peer0-pv.yaml
$ kubectl apply -f kubernetes/backup-org1peer0-pvc.yaml


Các peer còn lại cũng tương tự, bạn có thể tham khảo thêm trong repos git hub mình đã dẫn linhk ở trên.

2.4 Apply một Fabric Tools

Nếu như bạn nhớ lại ở bài trước, với môi trường docker thông thường thì network Fabric luôn cần có một container là cli để thông qua nó ta thực hiện các cấu hình ban đầu cho network. Container này sẽ chạy một image là hyperledger/fabric-tools:1.4.4 (có thể là phiên bản khác) như một hệ điều hành cho nó.

Trong môi trường Kubernetes (k8s) cũng vậy, sẽ có một container fabrictools ( trong một pod fabric-tools) chạy image hyperledger/fabric-tools:1.4.4 để thông qua nó ta connect các container khác lại với nhau thành network.

Cần lưu ý container ở đây vẫn là khái niệm container ta đã biết trước đây, còn pod chỉ là một đơn vị quản lý container, có thể có nhiều container trong một pod.

apiVersion: v1
kind: Pod
metadata:
  name: fabric-tools
spec:
  volumes:
    - name: fabricfiles
      persistentVolumeClaim:
        claimName: fabric-pvc
    - name: dockersocket
      hostPath:
        path: /var/run/docker.sock
  containers:
    - name: fabrictools
      image: hyperledger/fabric-tools:1.4.4
      imagePullPolicy: IfNotPresent # Nếu trong môi trường k8s vẫn chưa có image này, nó sẽ tự động pull về
      command: ['sh', '-c', 'sleep 48h']
      env:
        - name: TZ
          value: 'America/Sao_Paulo'
        - name: FABRIC_CFG_PATH
          value: '/fabric'
        - name: FABRIC_LOGGING_LEVEL
          value: debug
        - name: SYS_CHANNEL
          value: byfn-sys-channel
        - name: CHANNEL_NAME
          value: certificatechannel
      volumeMounts:
        - mountPath: /fabric
          name: fabricfiles
        - mountPath: /host/var/run/docker.sock
          name: dockersocket

Bạn có thể đặt là cli hay fabric-tools tùy bạn, nhưng ở đây mình thích đặt là fabric-tools.

Để ý bạn thấy container này có ít hơn biến môi trường so với cli thông thường, vì các biến đấy thay đổi theo từng câu lệnh nên mình không đặt vào đây làm gì cho mất công.

Một điều nữa là ở pod này ta đã dùng đến pvlabelfabricfiles cho container có tên là fabrictools. Giá trị mountPath: /fabic sẽ giúp mount thư mục /nfs/fabric của pv và thư mục /fabric của container lại với nhau, từ đây, các thay đổi trong thư mực /fabric của container sẽ được backup về cho pv fabricfiles.

Muốn sử dụng pv cho một container nào đó trong một pod ta phải khai báo nó đầy đủ ở 2 nơi:

spec.volumes[i] ( nhìn file trên ). Dòng này để khai báo pv cho pod.

spec.containers[i].volumeMounts[j] (cũng nhìn file trên). Dòng này khai báo pv cho mỗi container trong pod

Như vậy một pod có thể có nhiều containers, một pod cũng có thể có nhiều pv và mỗi container trong pod đó có thể sử dụng tùy chọn các pv mà nó cần, miễn sao pv đó đã được khai báo trong pod.

Chạy lệnh sau để apply pod fabric-tools :

$ kubectl apply -f kubernetes/fabric-tools.yaml

Để chắc chắn rằng pod fabric-tools đã hoạt động, bạn chạy lệnh:

$ kubectl get pods

Tạo thư mục cấu hình trong shared filesystem thông qua container fabrictools trong pod fabric-tools. Có 2 cách:

  • Cách 1. Truy cập vào container + tạo + thoát khỏi container:
$ kubectl exec -it fabric-tools -- bin/bash #Vì pod fabric-tools chỉ có một container fabrictools duy nhất nên nó sẽ mặc định vào container này
[email protected]: mkdir /fabric/config 
[email protected]: exit
  • Cách 2. Thực hiện trong một câu lệnh duy nhất:
$ kubectl exec -it fabric-tools -- mkdir /fabric/config

2.5 Copy các file config từ máy vào container

Mình đã chuẩn bị 2 file config/configtx.yamlconfig/crypto-config. Nội dung bạn có thể xem trong repos.

Bây giừ mình sẽ copy 2 file đấy vào trong thư mục nfs/fabric/config của shared filesystem bằng cách copy chúng vào thư mục /fabric/config của container fabrictools:

$ kubectl cp config/configtx.yaml fabric-tools:/fabric/config/
$ kubectl cp config/crypto-config.yaml fabric-tools:/fabric/config/


Copy luôn thư chaincode:

$ kubectl cp config/chaincode/ fabric-tools:/fabric/config/


Copy các package cần thiết để chaincode có thể thự thi, ở bước này bắt buộc trong máy bạn bắt buộc phải có các package đó:

$ kubectl exec -it fabric-tools -- mkdir -p /opt/gopath/src/github.com/hyperledger
$ kubectl cp ~/go/src/github.com/hyperledger/fabric  fabric-tools:/opt/gopath/src/github.com/hyperledger/
$ kubectl cp ~/go/src/github.com/golang  fabric-tools:/opt/gopath/src/github.com/
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# cp -r /opt/gopath/src/github.com/hyperledger/fabric/core/chaincode/lib/cid /opt/gopath/src/github.com/hyperledger/fabric/core/chaincode/
[email protected]-tools:/# exit

2.6 Tạo các cấu hình cần thiết

  1. crytogen. Bước này tạo thư mục crypto-config:
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# cryptogen generate --config /fabric/config/crypto-config.yaml
[email protected]-tools:/# cp -r crypto-config /fabric/
[email protected]-tools:/# exit
  1. configtxgen. Bước này tạo các file genesis.block, mychannel.tx, Org1MSPanchors.tx, Org2MSPanchors.tx:
kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# cp /fabric/config/configtx.yaml /fabric/
[email protected]-tools:/# cd /fabric
[email protected]-tools:/# configtxgen -profile TwoOrgsOrdererGenesis -channelID $SYS_CHANNEL -outputBlock genesis.block
[email protected]-tools:/# configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ${CHANNEL_NAME}.tx -channelID $CHANNEL_NAME
[email protected]-tools:/# configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
[email protected]-tools:/# configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
[email protected]-tools:/# exit
  1. Config đã xong, chúng ta cần giới hạn quyền truy cập vào /fabric:
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# chmod a+rx /fabric/* -R
[email protected]:/# exit

2.7 Apply các Fabric CA:

Nội dung 2 file kubernetes/org1-ca_deploy.yamlkubernetes/org2-ca_deploy.yaml đã có sãn trong repos. Nhiệm vụ của bạn là thay đôpr giá trị các env FABRIC_CA_SERVER_CA_KEYFILEFABRIC_CA_SERVER_TLS_KEYFILE sao cho đúng với cấu hình bạn vừa gen ra, bằng cách

$ kubectl exec -it fabric-tools -- bin/bash
[email protected]-tools:/# ls fabric/crypto-config/peerOrganizations/org1.example.com/ca/
[email protected]-tools:/# ls fabric/crypto-config/peerOrganizations/org2.example.com/ca/

Copy các gía trị trả vể và thay thế vào 2 file mình nói ở trên.

Sau đó chạy các lệnh sau để apply các CA:

$ kubectl apply -f kubernetes/org1-ca_deploy.yaml
$ kubectl apply -f kubernetes/org1-ca_svc.yaml
$ kubectl apply -f kubernetes/org2-ca_deploy.yaml
$ kubectl apply -f kubernetes/org2-ca_svc.yaml

Bạn có thể kiểm tra bằng câu lệnh quen thuộc:

$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
fabric-tools               1/1     Running   0          54m
org1-ca-5859bd976b-x47sc   1/1     Running   0          15s
org2-ca-5d67ccdf59-fndzg   1/1     Running   0          8s

2.8 Apply Orderer:

Ở bài này minh sử dụng solo cho đơn giản, bạn có thể xem nội dung của kubernetes/example-orderer_deploy.yaml trong repos, appy orderer:

$ kubectl apply -f kubernetes/example-orderer_deploy.yaml
$ kubectl apply -f kubernetes/example-orderer_svc.yaml

Kiểm tra:

$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
example-orderer-75475b948c-bkcvr   1/1     Running   0          3s
fabric-tools                       1/1     Running   0          57m
org1-ca-5859bd976b-x47sc           1/1     Running   0          2m45s
org2-ca-5d67ccdf59-fndzg           1/1     Running   0          2m38s

2.9 Appy các peers của Org1:

Bạn xem nội dung các file kubernetes/org1peer0_deploy.yaml, kubernetes/org1peer0_svc.yaml, kubernetes/org1peer1_deploy.yaml, kubernetes/org1peer1_svc.yaml trong repos: Chạy các lệnh sau để apply các peers:

$ kubectl apply -f kubernetes/org1peer0_deploy.yaml
$ kubectl apply -f kubernetes/org1peer1_deploy.yaml
$ kubectl apply -f kubernetes/org1peer0_svc.yaml
$ kubectl apply -f kubernetes/org1peer1_svc.yaml

Kiểm tra:

$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
example-orderer-75475b948c-bkcvr     1/1     Running   0          4m37s
example-org1peer0-94dbff66f-rpr4g    1/1     Running   0          9s
example-org1peer1-559569c869-dpzh6   1/1     Running   0          8s
fabric-tools                         1/1     Running   0          61m
org1-ca-5859bd976b-x47sc             1/1     Running   0          7m19s
org2-ca-5d67ccdf59-fndzg             1/1     Running   0          7m12s

2.10 Appy các peer của Org2

Tương tự như Org1.

$ kubectl apply -f kubernetes/org2peer0_deploy.yaml
$ kubectl apply -f kubernetes/org2peer1_deploy.yaml
$ kubectl apply -f kubernetes/org2peer0_svc.yaml
$ kubectl apply -f kubernetes/org2peer1_svc.yaml
$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
example-orderer-75475b948c-bkcvr     1/1     Running   0          8m5s
example-org1peer0-94dbff66f-rpr4g    1/1     Running   0          3m37s
example-org1peer1-559569c869-dpzh6   1/1     Running   0          3m36s
example-org2peer0-7466f6754c-t7cfn   1/1     Running   0          4s
example-org2peer1-786b9bc5f-74txp    1/1     Running   0          4s
fabric-tools                         1/1     Running   0          65m
org1-ca-5859bd976b-x47sc             1/1     Running   0          10m
org2-ca-5d67ccdf59-fndzg             1/1     Running   0          10m

2.11 Tạo channel

Mình sẽ sủ dụng container fabrictools trong pod fabric-tools để thực hiện:

$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools: cd /fabric
[email protected]-tools: export ORDERER_URL="example-orderer:31010"
[email protected]-tools: export CORE_PEER_ADDRESSAUTODETECT="false"
[email protected]-tools: export CORE_PEER_NETWORKID="nid1"
[email protected]-tools: export CORE_PEER_LOCALMSPID="Org1MSP"
[email protected]-tools: export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp"
[email protected]-tools: export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools: export CORE_PEER_ADDRESS="example-org1peer0:30110"
[email protected]-tools: peer channel create -o ${ORDERER_URL} -c ${CHANNEL_NAME} -f /fabric/${CHANNEL_NAME}.tx
2020-01-07 00:35:28.195 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:35:28.224 -02 [cli.common] readBlock -> INFO 002 Received block: 0
[email protected]-tools: exit

2.12 Join channel

  • Join các peers của Org1:
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# export CORE_PEER_NETWORKID="nid1"
[email protected]-tools:/# export ORDERER_URL="example-orderer:31010"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org1MSP"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp"

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org1peer0:30110"

[email protected]-tools:/# peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME}
2020-01-07 00:44:05.683 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:44:05.696 -02 [cli.common] readBlock -> INFO 002 Received block: 0

[email protected]-tools:/# peer channel join -b ${CHANNEL_NAME}_newest.block
2020-01-07 00:44:35.054 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:44:35.109 -02 [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

[email protected]-tools:/# rm -rf /${CHANNEL_NAME}_newest.block

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org1peer1:30110"

[email protected]-tools:/# peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME}
2020-01-07 00:46:02.524 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:46:02.525 -02 [cli.common] readBlock -> INFO 002 Received block: 0

[email protected]-tools:/# peer channel join -b ${CHANNEL_NAME}_newest.block
2020-01-07 00:46:38.494 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:46:38.540 -02 [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

[email protected]-tools:/# rm -rf /${CHANNEL_NAME}_newest.block

[email protected]-tools:/# exit
  • Join các peers của Org2:
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# export CORE_PEER_NETWORKID="nid1"
[email protected]-tools:/# export ORDERER_URL="example-orderer:31010"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org2MSP"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp"

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org2peer0:30110"

[email protected]-tools:/# peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME}
2020-01-07 00:50:28.853 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:50:28.855 -02 [cli.common] readBlock -> INFO 002 Received block: 0

[email protected]-tools:/# peer channel join -b ${CHANNEL_NAME}_newest.block
2020-01-07 00:50:57.805 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:50:57.840 -02 [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

[email protected]-tools:/# rm -rf /${CHANNEL_NAME}_newest.block

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org2peer1:30110"

[email protected]-tools:/# peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME}
2020-01-07 00:52:16.889 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:52:16.891 -02 [cli.common] readBlock -> INFO 002 Received block: 0

[email protected]-tools:/# peer channel join -b ${CHANNEL_NAME}_newest.block
2020-01-07 00:52:20.994 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 00:52:21.041 -02 [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

[email protected]-tools:/# rm -rf /${CHANNEL_NAME}_newest.block
[email protected]-tools:/# exit

2.13 Install Chaincode

  • Install chaincode lên các peers Org1:
$ kubectl exec -it fabric-tools -- /bin/bash

[email protected]-tools:/# cp -r /fabric/config/chaincode $GOPATH/src/
[email protected]-tools:/# export CHAINCODE_NAME="mychaincode"
[email protected]-tools:/# export CHAINCODE_VERSION="1.0"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp"
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org1MSP"

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org1peer0:30110"
[email protected]-tools:/# peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode/mychaincode/
2020-01-07 00:56:31.792 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2020-01-07 00:56:31.792 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2020-01-07 00:56:32.884 -02 [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org1peer1:30110"
[email protected]-tools:/# peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode/mychaincode/
2020-01-07 00:56:59.896 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2020-01-07 00:56:59.896 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2020-01-07 00:57:00.242 -02 [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 

[email protected]-tools:/# exit
  • Install chaincode lên các peers của Org2:

$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# cp -r /fabric/config/chaincode $GOPATH/src/
[email protected]-tools:/# export CHAINCODE_NAME="mychaincode"
[email protected]-tools:/# export CHAINCODE_VERSION="1.0"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp"
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org2MSP"

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org2peer0:30110"
[email protected]-tools:/# peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode/mychaincode/
2020-01-07 00:59:40.861 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2020-01-07 00:59:40.861 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2020-01-07 00:59:41.185 -02 [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 

[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org2peer1:30110"
[email protected]-tools:/# peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode/mychaincode/
2020-01-07 01:00:04.290 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2020-01-07 01:00:04.290 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2020-01-07 01:00:04.623 -02 [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 

[email protected]-tools:/# exit

2.14 Instantiate chaincode

Sau khi chanicode đã được cài dặt lên tất cả các peers, mình cần phải instantiate nó:

$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# export CHAINCODE_NAME="mychaincode"
[email protected]-tools:/# export CHAINCODE_VERSION="1.0"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp"
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org1MSP"
[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org1peer0:30110"
[email protected]-tools:/# export ORDERER_URL="example-orderer:31010"
[email protected]-tools:/# export FABRIC_LOGGING_LEVEL=debug

[email protected]-tools:/# peer chaincode instantiate -o ${ORDERER_URL} -C ${CHANNEL_NAME} -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -P "OR ('Org1MSP.peer','Org2MSP.peer') " -c '{"Args":["init","a","300","b","600"]}'
2020-01-07 01:03:31.312 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2020-01-07 01:03:31.312 -02 [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc

[email protected]-tools:/# exit

2.15 Update anchor peer cho các Org:

  • Update anchor peer cho Org1:
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org1MSP"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp"
[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org1peer0:30110"
[email protected]-tools:/# export ORDERER_URL="example-orderer:31010"
[email protected]-tools:/# export FABRIC_LOGGING_LEVEL=debug

[email protected]-tools:/# peer channel update -f /fabric/Org1MSPanchors.tx -c $CHANNEL_NAME  -o $ORDERER_URL
2020-01-07 01:07:23.180 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 01:07:23.193 -02 [channelCmd] update -> INFO 002 Successfully submitted channel update

[email protected]-tools:/# exit
  • Update anchor peer cho Org2
$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org2MSP"
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/[email protected]: config/peerOrganizations/org2.example.com/users/[email protected]/msp"
[email protected]-tools:/# export CORE_PEER_ADDRESS="example-org2peer0:30110"
[email protected]-tools:/# export ORDERER_URL="example-orderer:31010"
[email protected]-tools:/# export FABRIC_LOGGING_LEVEL=debug

[email protected]-tools:/# peer channel update -f /fabric/Org2MSPanchors.tx -c $CHANNEL_NAME  -o $ORDERER_URL
2020-01-07 01:09:30.417 -02 [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-01-07 01:09:30.438 -02 [channelCmd] update -> INFO 002 Successfully submitted channel update

[email protected]-tools:/# exit

2.16 Invoke và query chaincode

Bước trên coi như đã xong một network Hyperledger Fabric trên k8s, mình sẽ invoke, query thử để xem kết quả thế nào:


$ kubectl exec -it fabric-tools -- /bin/bash
[email protected]-tools:/# export FABRIC_CFG_PATH="/etc/hyperledger/fabric"
[email protected]-tools:/# export ORDERER_URL="example-orderer:31010"
[email protected]-tools:/# export CORE_PEER_LOCALMSPID="Org1MSP"
[email protected]-tools:/# export CORE_PEER_MSPCONFIGPATH="/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp"
[email protected]abric-tools:/# export CORE_PEER_ADDRESS="example-org1peer0:30110"

[email protected]-tools:/# peer chaincode invoke --peerAddresses example-org1peer0:30110 -o example-orderer:31010 -C mychannel -n mychaincode -c '{"Args":["invoke","a","b","50"]}'
2020-01-07 01:16:43.589 -02 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 

[email protected]-tools:/# peer chaincode query -C mychannel -n mychaincode -c '{"Args": ["query","a"]}'
250

[email protected]-tools:/# peer chaincode query -C mychannel -n mychaincode -c '{"Args": ["query","b"]}'
650

[email protected]-tools:/# exit

Tổng kết

Sau khi hoàn thành các bước ở trên coi như mình đã xong. Còn phía server nodejs và client (frontend) bạn cũng có thể đưa chúng lên k8s để tạo project chạy hoàn toàn trên k8s. Có thể bài sau mình sẽ viết về vấn đề này. Cảm ơn các bạn đã theo dõi !!!

Link tham khảo: https://github.com/feitnomore/hyperledger-fabric-kubernetes
Link repos mẫu của mình: https://github.com/tantv-918/hyperledger-fabric-k8s

Nếu có gì chưa hiểu, bạn hãy để lại câu hỏi phía dưới nhé.