K8s无法感知到Fabric Chaincode容器的解决方案
文章目录事情起因解决方案事情起因相信在使用k8s进行fabric部署的时候,很多人克服了重重困难,最终倒在了dns解析下的悲剧。在使用k8s的时候,通过flannel网络能够在pod容器内进行内部local访问,也可以使用NodePort或者ClusterIP进行外部的访问。然而,在启动fabric-peer的的env里,通过CORE_VM_ENDPOINT=unix:///var/run/...
事情起因
相信在使用k8s进行fabric部署的时候,很多人克服了重重困难,最终倒在了dns解析下的悲剧。
在使用k8s的时候,通过flannel网络能够在pod容器内进行内部local访问,也可以使用NodePort或者ClusterIP进行外部的访问。然而,在启动fabric-peer的的env里,通过CORE_VM_ENDPOINT=unix:///var/run/docker.sock
能够让peer节点创建并启动fabric chaincode容器(链码容器的启动是通过Docker API启动的)。
在使用单机docker-compose的情况下,使用CORE_VM_HOSTCONFIG_DNS
加之本机docker的桥接模式,能够让启动无碍。然而,chaincode容器是docker创建的,在k8s感知之外,是无法通过NodePort抑或是ClusterIP访问peer或者orderer节点的。
解决方案
其中一种解决方案是:修改docker的dns
通过修改docker文件来使得启动的chaincode容器自带dns(该方法不知是我配置出错还是其他原因,我没有成功,网上有成功案例)。
本文主要的讲的解决方案不是上面这种,毕竟是偏方,这里说的是IBM自己实现的Baas里的方案——dind。
dind也就是Docker in Docker,在使用Gitlab-ci的时候,曾经在CI/CD服务器的Docker container里面来构建(build)与运行(run)我们的Docker镜像。
很多不使用dind的人,替代做法就是将docker.sock文件volume进容器里,然后在容器里调用容器外的docker daemon来创建新的容器。所以这个做法与peer节点的做法如出一辙。所以,我们逆过程,直接使用dind也是可以的。
IBM的部署方案,就是上述的思路,进一步的它使用了Docker in Docker(dind)的方案,即K8s中运行一个Docker Pod,然后将链码在这个Docker环境中启动进程, 这样的好处是:我们所能看到的都在k8s环境中;dind在k8s环境,所以链码容器可以直接利用k8s的dns系统,无需再手动配置。
缺点是:
- 链码容器放在了dind中,k8s环境是无法直接管理链码容器的,不利于我们的外部监控。
- 至于链码容器的存活,链码增多,dind负担也将增加,崩溃的可能性增大。虽然可以通过持久化存储实现dind重启后Pod重启,然而fabric虽然通过心跳机制感知到了chaincode容器的崩溃,但是k8s不能知道dind里嵌套的后一个docker的崩溃,所以fabric 无法重启chaincode,k8s也无法重启Pod。
在dind中运行链码容器还是存在较多问题的,主要是它仍没有完全纳入k8s环境,那我们能不能将dind接受的链码启动命令转化为k8s中pod创建命令,将链码部署到pod中,这样就将链码纳入到k8s环境中。这个改动有两个方向:
- fabric的链码实例化源码改动,让其支持k8s启动;
- 从dind入手,拦截创建链码容器的命令,然后通过k8s api创建pod,这其实相当于做了一个代理。
第一种方式,需要fabric源码作出改动,这是真正的治标治本的方案,因为第二种方案我们已经分析了其缺点。
我们这里主要分析第二种方式:
我们看下IBM-BLOCKCHAIN-NETWORK-ON-K8S的链码部署流程
- 正常的各组件启动
- jobs:安装链码
- jobs:实例化链码
- Peer接收到实例化链码请求,共识通过后,连接CORE_VM_ENDPOINT参数配置的远程Docker(实际是dind),发送部署链码容器消息
- Docker in Docker(dind),启动链码容器
这里追踪一下yaml:
下面是dind的配置。
---
apiVersion: v1
kind: Service
metadata:
name: docker #docker的域名,k8s的dns可以将域名docker解析为ip
labels:
run: docker
spec:
selector:
name: docker
ports:
- protocol: TCP
targetPort: 2375
port: 2375
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: docker-dind
spec:
replicas: 1
template:
metadata:
labels:
name: docker
spec:
volumes:
- name: dockervolume
persistentVolumeClaim:
claimName: docker-pvc
containers:
- name: docker
securityContext:
privileged: true
image: "docker:stable-dind"
ports:
- containerPort: 2375
volumeMounts:
- mountPath: /var/lib/docker
name: dockervolume
重头戏来了(CORE_VM_ENDPOINT
),接下来是peer的配置:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: blockchain-org1peer1
spec:
replicas: 1
template:
metadata:
labels:
name: org1peer1
spec:
volumes:
- name: sharedvolume
persistentVolumeClaim:
claimName: shared-pvc
- name: dockersocket
hostPath:
path: /var/run/docker.sock
containers:
- name: org1peer1
image: hyperledger/fabric-peer:1.4
command: ["sh", "-c", "sleep 1 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; peer node start"]
env:
- name: CORE_PEER_ADDRESSAUTODETECT
value: "true"
- name: CORE_PEER_NETWORKID
value: nid1
- name: CORE_PEER_ID
value: org1peer1
- name: CORE_PEER_ADDRESS
value: blockchain-org1peer1:30110
- name: CORE_PEER_LISTENADDRESS
value: 0.0.0.0:30110
...
- name: CORE_PEER_COMMITTER_ENABLED
value: "true"
- name: CORE_PEER_PROFILE_ENABLED
value: "true"
- name: CORE_VM_ENDPOINT #重点是这里,接收到链码实例化请求,Peer向此地址的Docker发送启动链码容器命令/api调用
value: tcp://docker:2375
- name: CORE_PEER_LOCALMSPID
value: Org1MSP
- name: CORE_PEER_MSPCONFIGPATH
value: /shared/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/
- name: FABRIC_LOGGING_SPEC
value: debug
...
配置到这里,一目了然。
参考:
https://github.com/IBM/blockchain-network-on-kubernetes
https://blog.csdn.net/scylhy/article/details/94635655
更多推荐
所有评论(0)