事情起因

相信在使用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系统,无需再手动配置。

缺点是:

  1. 链码容器放在了dind中,k8s环境是无法直接管理链码容器的,不利于我们的外部监控。
  2. 至于链码容器的存活,链码增多,dind负担也将增加,崩溃的可能性增大。虽然可以通过持久化存储实现dind重启后Pod重启,然而fabric虽然通过心跳机制感知到了chaincode容器的崩溃,但是k8s不能知道dind里嵌套的后一个docker的崩溃,所以fabric 无法重启chaincode,k8s也无法重启Pod

在dind中运行链码容器还是存在较多问题的,主要是它仍没有完全纳入k8s环境,那我们能不能将dind接受的链码启动命令转化为k8s中pod创建命令,将链码部署到pod中,这样就将链码纳入到k8s环境中。这个改动有两个方向:

  1. fabric的链码实例化源码改动,让其支持k8s启动;
  2. 从dind入手,拦截创建链码容器的命令,然后通过k8s api创建pod,这其实相当于做了一个代理

第一种方式,需要fabric源码作出改动,这是真正的治标治本的方案,因为第二种方案我们已经分析了其缺点。
我们这里主要分析第二种方式:
我们看下IBM-BLOCKCHAIN-NETWORK-ON-K8S的链码部署流程

  1. 正常的各组件启动
  2. jobs:安装链码
  3. jobs:实例化链码
  4. Peer接收到实例化链码请求,共识通过后,连接CORE_VM_ENDPOINT参数配置的远程Docker(实际是dind),发送部署链码容器消息
  5. 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

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐