有了上一篇的基础,这一篇就尝试将fabric部署在k8s上,以下的操作的前提条件是自己已经对docker-compose部署fabric比较熟悉了,可以先搞清楚fabricase目录下的fabric_raft项目。
1.修改DNS
在真正开始部署之前,需要先解决一个问题,就是下面会使用到将unix:///var/run/docker.sock挂载进peer容器中,因为在1.4.X版本peer 容器需要调用 Docker 引擎的接口来构建和创建 chaincode 容器,但通过 docker.sock 创建的容器脱离在 k8s的体系之外,这会导致chaincode容器通过宿主机的DNS无法找到运行在k8s体系上的peer节点容器,所以这里需要先解决DNS的问题,解决方式参考网上的教程,在每个worker节点上的/etc/default/docker
文件中添加DOCKER_OPTS参数,具体操作如下:
cat /etc/resolv.conf # 我这里是127.0.0.53
kubectl get svc -n kube-system
vim /etc/default/docker
DOCKER_OPTS="--dns=10.96.0.10 --dns=127.0.0.53 --dns-search default.svc.cluster.local --dns-search svc.cluster.local --dns-opt ndots:2 --dns-opt timeout:2 --dns-opt attempts:2"
systemctl daemon-reload
systemctl restart docker
2.生成证书与启动fabric网络所需的配置文件
git clone https://github.com/Jalins/fabricase.git
cd fabricase/fabric-on-k8s
bash fabricOps.sh start
注意:因为网络的问题,自己去GitHub上将fabric的cryptogen、configtxgen二进制文件下载下来放在/usr/local/bin
目录下。
3.部署orderer节点
文件在orderer-service目录下,总共有六个文件,只需要搞清楚orderer0-deployment.yaml与orderer0-svc.yaml这两个文件即可,其他的四个文件都以此类推,这里就不细讲k8s的yaml文件格式,有兴趣自己上网搜一下其他教程,简单看一下orderer0-deployment.yaml文件,大部分的声明跟写docker-compose的yaml文件差不多,挂载卷不再是通过":"来指定,而是通过声明的方式来指定,如:
稍微不同,但还是好理解,这里稍微要注意的就是因为pod是运行在worker节点上且不确定是运行在哪个worker节点的,所以每个worker节点上一定要存在该路径,不然启动的时候会报找不到文件的错误,建议可以使用nfs来统一管理目录文件。
文件中还有另外一处是关于节点的亲和性。
这里的意思是根据节点上的标签来约束 pod 可以调度到哪些节点,意思就是希望orderer0、orderer1和orderer2都调度到同一个worker节点上,但因为这里声明了preferredDuringSchedulingIgnoredDuringExecution
,意思是调度器将尝试执行但不能保证的最终所指定的节点会调度到同一个节点上,如果要硬性规定的话可以使用requiredDuringSchedulingIgnoredDuringExecution
字段来声明。
关于orderer0-svc.yaml文件看一下大概就明白是怎么回事了,这个文件的作用就只是发现后端的pod服务,并提供负载均衡的能力,不懂可以看一下这篇 浅谈 kubernetes service 那些事
大概明白这些文件的含义之后,在master节点上可以一次性执行下面的命令:
kubectl apply -f orderer-service/
这个命令会将所有的orderer节点跟相对应的service服务都启动起来,也可以一个文件一个文件执行。
kubectl apply -f orderer-service/orderer0-deployment.yaml
...
4.部署peer节点
peer的yaml文件有几点注意的,首先是couchdb跟peer是运行在同一个pod中,这样做的好处是peer容器可以直接使用localhost访问到couchdb的容器。
再者就是链码的监听地址要为0.0.0.0:7052,不然在实例化链码的时候会出现链码容器连接不上peer的错误。
还有就是service的yaml文件中需要使用到NodePort,主要是为了后续让SDK访问到peer容器,可以与k8s上的fabric网络进行交互。
这样sdk可以使用grpcs://worker节点的ip:30001访问到该节点。
部署:
kubectl apply -f org1/org1-peer0-deployment.yaml
kubectl apply -f org1/org1-peer0-svc.yaml
kubectl apply -f org2/org2-peer0-deployment.yaml
kubectl apply -f org2/org2-peer0-svc.yaml
5.部署CA
将CA服务器的根证书与私钥指定为组织的根证书与私钥,这样由CA服务器签发出来的证书才能通过fabric网络的认证,只需在yaml文件中修改替换成相对应的即可。
挂载路径要指定正确,还有就是service的也要使用NodePort,这样sdk才能连接到。
部署:
kubectl apply -f org1/org1-ca-deployment.yaml
kubectl apply -f org1/org1-ca-svc.yaml
kubectl apply -f org2/org2-ca-deployment.yaml
kubectl apply -f org2/org2-ca-svc.yaml
6.部署cli
因为是部署在同一个k8s体系下的namespace,可以直接通过域名的方式访问到pod。
上面通过NodePort是为了让k8s系统外的服务能连接进来,但在k8s内部就简单多了,可以直接通过域名访问,这是因为k8s有自己的一套域名解析。
kubectl apply -f org1/org1-cli-deployment.yaml
因为是演示,这里就只部署一个cli,下面就使用这个cli来创建通道与安装实例化链码。
7.通道与链码操作
kubectl exec -it cli-org1-xxx bash -n hyperledger
CHANNEL_NAME=mychannel
CHAINCODE_NAME=mycc
peer channel create -o orderer0:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls true --cafile $ORDERER_CA
peer channel join -b channel.block
peer channel update -o orderer0:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1Anchors.tx --tls --cafile $ORDERER_CA
peer chaincode install -n $CHAINCODE_NAME -v 1.0 -p github.com/hyperledger/fabric/peer/chaincodes/ccexample
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2/peers/peer0-org2/tls/server.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2/peers/peer0-org2/tls/server.key
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2/peers/peer0-org2/tls/ca.crt
CORE_PEER_ADDRESS=peer0-org2:7051
CORE_PEER_LOCALMSPID=Org2MSP
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2/users/Admin@org2/msp
操作跟上面一样的,就直接一笔带过了。
peer channel join -b mychannel.block
peer channel update -o orderer0:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2Anchors.tx --tls --cafile $ORDERER_CA
peer chaincode install -n $CHAINCODE_NAME -v 1.0 -p github.com/hyperledger/fabric/peer/chaincodes/ccexample
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1/peers/peer0-org1/tls/server.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1/peers/peer0-org1/tls/server.key
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1/peers/peer0-org1/tls/ca.crt
CORE_PEER_ADDRESS=peer0-org1:7051
CORE_PEER_LOCALMSPID=Org1MSP
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1/users/Admin@org1/msp
peer chaincode instantiate -o orderer0:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
peer chaincode invoke -o orderer0:7050 --tls --cafile $ORDERER_CA -n $CHAINCODE_NAME -c '{["invoke","a","b","10"]}' -C $CHANNEL_NAME
peer chaincode query -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{"Args":["query","a"]}'