在Kubernetes上运行区块链服务(BaaS)

931 阅读21分钟

笔者注:本文是在2018年11月15日由Linux基金会CNCF主办的KubeCon & CloudNativeCon China 2018大会的“Running Blockchain as a Service (BaaS) on Kubernetes”演讲内容基础上整理而成,从技术上介绍了阿里云如何将基于区块链Hyperledger Fabric的BaaS和容器集群技术Kubernetes进行结合的设计理念和实践经验分享。


大家好!我是来自于阿里云区块链团队的余珊,今天给大家分享的是《在Kubernetes上运行区块链服务(BaaS)》这个主题。


以上是今天分享的内容大纲,其中重点在第三部分,我们将对BaaS结合Kubernetes的一些典型问题进行深入探讨。


首先我们分享一下在我们眼中的区块链和BaaS的定义是什么。

从狭义上来说,区块链是一种分布式共享账本技术,基于智能合约,在各参与方之间达成对交易的共识,并实现账本交易历史的不可篡改。这个定义是大家所熟知的,并且是从技术和功能上进行的概括。

而从广义上来说,我们认为,区块链也是一种在机构、个人、机器之间,构建分布式信任网络、连接可信数据、实现价值流动的新的架构和协作模式。这也是跳出技术和功能维度,从更高维度去进行的理解和总结。

对于另一个概念"BaaS",即"Blockchain as a Service", 我们认为,是云平台之上的区块链平台服务,提供了区块链系统的部署、运维、治理能力,以及提供了区块链应用运行和管理的能力。

区块链从其类型上可分为私有链、公有链、联盟链三种类型,而从系统拓扑上我们可以将其对应为下述三种模式。对于传统的中心化系统或私有链来说,它基本属于一种星型中心化系统。对于公有链来说,是一种将所有参与企业和个人都对等连接在一起的完全去中心化系统。而对于联盟链来说,是一种带分层结构的多中心化系统。而阿里云今天主要关注的是面向企业场景的联盟链技术类型。


下面我们来探讨一下为什么将区块链与容器技术以及Kubernetes进行结合。

首先,我们来分析一下区块链的特点。我们将其分为区块链系统和区块链业务应用两类。

  • 区块链系统是以数据为核心、高度分布式、Full-Mesh网络拓扑、Long-Running、复杂系统类型。

    • 数据为核心:其中最重要的是账本上的数据。
    • 高度分布式:因为区块链节点可能部署于不同机房、不同region、不同国家等等。
    • Full-Mesh: 区块链节点之间要依赖全连通的网络以实现共识、账本同步等过程。
    • Long-Running:区块链服务和节点是长时间运行,而不是像Web应用或批处理任务那样短生命周期的。
    • 复杂系统类型:区块链系统不是一两个模块构成的简单应用,而是往往一整天解决方案或系统的形式。
  • 区块链业务应用:没有统一的标准,可能包含各种应用类型,包括无状态应用、有状态应用、Web应用、数据型应用等等类型。

接下来,我们分析一下区块链结合容器技术会带来哪些优势:

  • 容器技术为区块链系统和业务应用提供了标准化的软件打包、分发的能力。
  • 容器技术实现了区块链运行环境的一致性,以及与底层基础架构的解耦,使得区块链系统和业务应用可以很方便地移植和运行在各种平台之上。

进一步的,我们发现,区块链使用Kubernetes集群技术可获得以下几方面的优势:

  • Kubernetes提供了灵活的区块链所需要的底层资源的调度能力,如计算、存储、网络等。
  • Kubernetes强大的运维管理能力,使得我们的区块链服务的产品上线速度以及运维的效率大大提升。
  • Kubernetes支持各种应用类型以及微服务架构,因此对于上面区块链系统和区块链业务应用各自的需求都能很好地满足。
  • 使用Kubernetes,可以更好地跟云平台进行集成,因为今天在业界它已经成为了各大云厂商云原生应用的标准底座了。
  • Kubernetes还提供了丰富的安全和隔离功能,这对我们区块链的安全防护体系是很大的增强。
  • 另外,围绕Kubernetes有着非常活跃的社区和丰富的技术和业务生态,因此为结合区块链的研发提供了强大的技术支持和资源。

这里解答图中的一个疑问,微服务架构是否适合区块链,这要结合上面的区块链特点分析来看待:

  • 对区块链系统来说,内部组件之间是强耦合、强依赖的关系,比较难解耦,内部各组件本身不是通用化的服务定位,也不是REST化服务接口,更多是例如gRPC调用,因此不是太适合微服务架构。
  • 但是对区块链业务应用来说,则很适合考虑与微服务架构进行结合。

上面这幅图展示了阿里云区块链产品形态的演进历史,同时也可以看出我们在区块链结合容器以及Kubernetes方面所在的工作。

在2017年10月,我们开始提供基于容器服务的区块链解决方案,支持Hyperledger Fabric,为企业提供一键式的区块链自动部署能力,当时是基于Docker Swarm集群技术。紧接着在2017年12月,我们推出了支持Kubernetes的容器服务区块链解决方案,并且在业界也是较早开始使用Helm Chart部署区块链的。在今年7月底,我们正式推出了阿里云区块链服务BaaS,支持Hyperledger Fabric,同样也是基于Kubernetes。而在今年9月杭州云栖大会上,阿里云BaaS也正式支持了蚂蚁区块链,在这背后蚂蚁区块链也通过适配改造工作实现了在Kubernetes上的部署运行。


这一页展示的是阿里云BaaS的产品架构大图。其中最核心的是BaaS,目前已经支持Hyperledger Fabric和蚂蚁区块链。它们的运行实例底座都是基于阿里云容器服务Kubernetes集群。今天的演讲内容主要是围绕Hyperledger Fabric跟Kubernetes结合这方面展开讨论的。


上面这一页展示了阿里云容器服务Kubernetes版的产品架构图。


这里我们展示了一套跨region的Hyperledger Fabric联盟链的部署架构图。在联盟管理方的Kubernetes集群上部署了Orderer organization和Peer Organization, 而在其他业务参与方所在region的Kubernetes上部署了各自的Peer Organization. 这里的CA、Peer、Orderer、Kafka、ZooKeeper的每个实例都是用了Kubernetes的Service和Deployment类型对象来定义。

此外区块链的业务应用可以部署在Kubernetes上或者其他环境上,通过SLB映射到集群worker节点的NodePort上,来访问区块链的各个service。


接下来我们进入重点的第三部分,对于实现BaaS运行在Kubernetes的过程,我们曾经遇到的一些有代表性的问题,以及我们的解决思路和实践经验。

首先是关于区块链BaaS的打包、发布、服务编排等方面的问题。

对于以Hyperledger Fabric为代表的区块链系统来说,这方面面临的主要问题是:区块链系统本身较为复杂,在一套典型部署里可能涉及到三十多个容器、近二十个服务、十来个容器镜像;而且这些服务相互之间有较强的依赖。

对于这个问题,我们的解决思路是:

  • 在打包部署方面,从一开始我们便选用了容器镜像以及Kuberentes的Helm Chart作为标准的格式和工具。这里尤其提一下,为了保证联盟链各组织创建的独立性和灵活性,我们采用的是一类组织(例如Orderer Org或Peer Org)使用一套chart的方式。
  • 在存储库管理方面,目前使用的是阿里云OSS作为Chart Repo(当然可以使用功能更丰富的如ChartMuseum等工具),使用阿里云容器镜像服务作为镜像仓库。这里我们还采用了region化的镜像仓库配置,加快大体积镜像的下载速度,同时采用imagePullSecret保护镜像的安全。
  • 在配置方式方面,我们采用了Kubernetes的ConfigMap和Secrets来存储主要的配置和安全信息,以及使用Chart Values来让管控可以根据客户的输入去定制BaaS联盟链实例。
  • 在服务编排方面,为了满足服务的依赖性需求,我们结合了Chart Template,Chart的Hook(钩子)机制,以及Kubernetes的Init Container加上Shell脚本方式,实现各种服务尤其在启动过程中的依赖和顺序保证。

对于企业来说,业务系统的高可用性是非常重要的,尤其是对生产环境的系统运行和应用访问。这里我们分享一下在BaaS的每一个层面上的高可用设计思路,以及Kubernetes在其中起到怎样的帮助。

首先在云基础架构和云资源服务层,我们通过云数据中心的多可用区、所依赖的云服务本身的高可用性和高可靠性来提供保障。

在BaaS管控层,通过管控组件的多实例化部署避免单点故障。

在容器服务的Kubernetes集群,采用3个master节点和多个worker节点的方式提供应用底座的高可用。

在Hyperledger Fabric这一层,它的Orderer、Peer、Kafka、ZooKeeper、CA等类型节点均有集群或高可用互备的设计,比如任一节点挂掉的话,其他节点依然能正常提供服务。但这里有一个关键的点,就是在Kubernetes集群上部署的时候,为了避免这些本应高可用互备的Fabric节点的pod被调度到同一个worker node上,我们采用了Kubernetes Pod Anti-Affinity的功能区将高可用集群的pod调度到不同的worker上,这样保证了真正高可用的部署,提高了对故障的容忍度。

在区块链业务应用层,则需要各个企业客户对应用进行周全的高可用设计和实现。在运行时,应用访问Fabric各个服务的这一环节,我们BaaS内置了云平台的SLB负载均衡能力(包含对服务端口的健康检查),以及Fabric的Service Discovery,来保证即使后端部分节点或服务不可用时,应用的调用链路都会被调度到可用的节点或服务上。


下面我们谈谈BaaS数据持久化存储的问题。虽然上面已经介绍了BaaS的高可用性设计,但我们仍需考虑如何将链上账本数据、区块链关键配置等重要内容持久化保存到可靠的外部存储而不是容器内部,这样便可以在服务器节点全部发生故障,或者系统重启、备份恢复等场合依然可以实现对系统和数据的恢复。

首先,作为背景,我们分析了如果使用本地盘方式可能存在的问题:

  • Kubernetes本身对pod的调度默认并没有限定worker节点,因此如果使用本地盘,就会因为在重启或恢复过程中调度导致的pod漂移而无法读取原来worker节点上的本地盘。
  • 对于第一个问题,Kubernetes提供了NodeSelector的机制可以让pod可以绑定worker节点进行部署,不会调度到其他worker节点上,这样就可以保证能始终访问到一个本地盘。但这又带来另一个问题,即在容灾的场景,如果这个节点包括其本地盘受到损坏无法恢复时,会导致整个pod也无法恢复。

因此,我们在设计BaaS中的选择是阿里云的NAS文件系统存储、以及阿里云的云盘。在数据可靠性方面,NAS和云盘可以分别提供99.999999999%和99.9999999%的数据可靠性。此外,我们都选用了SSD类型以保证I/O性能。

在Kubernetes部署的时候,Fabric的节点通过Persistent Volume和Persistent Volume Claim挂载上相应的存储,并且这些存储是为每一个Fabric的业务organization独立分配的,保证了业务数据的隔离性。

在和参加KubeCon大会的一些区块链用户交流的时候,有朋友提到随着账本数据的持续增长,可以怎样解决存储问题。在我们的实践中,我们发现阿里云的NAS有一些很适合区块链账本存储的一些特点:

  • 首先,阿里云NAS可提供存储容量动态无缝扩容,在这过程中Fabric节点或区块链业务应用均无需重启或停机,对存储扩容过程完全无感知。
  • 其次,有用户担心随着存储数据量的增大,存储的性能是否会明显下降。恰恰相反的是,在阿里云NAS随着所使用的数据量变得越大,NAS所提供的吞吐性能会变得更高,这样可以打消企业用户在长期生产运行方面的顾虑。

在上图的右边是Fabric不同类型的区块链节点使用不同类型存储的一个示意图。


接下来我们探讨一下在设计搭建BaaS联盟链跨企业的网络方面遇到的挑战。

对于大多数区块链技术而言,包括Hyerpedger Fabric, 在网络上要求区块链节点之间形成Full Mesh全连通网络,以实现节点间的账本数据同步、区块广播、节点发现、交易背书等过程,同时企业也要求保障跨企业链路的安全性。对于这些需求,我们梳理了业界目前常见的几类解决方案如下,并进一步分析它们存在的一些不足之处。

方案一是采用单一VPC的联盟链网络方案,在这种模式下,联盟链的所有区块链节点均被部署到一套Kubernetes集群网络或VPC内。这种方案实质上是一种私有链的模式,失去了联盟链的各方自治的价值。

方案二是基于公网的联盟链网络方案,区块链节点分布式部署在不同区域,通过公网IP对外提供服务以及实现互相通信。这种方案可以较灵活、较低成本低满足大多数基本需求,但对于高级需求如企业级安全网络则不能很好地满足。

方案三是基于专线互联的联盟链网络方案,它采用运营商专线方式将不同网络或数据中心进行两两互联,在业界一些企业中得到了采用。但这里面主要存在两方面的问题,首先是如果联盟链参与企业采用了不同电信运营商的专线方案的话,项目实施的复杂性和成本都会很高;其次,如果几家企业已经建好了这样一个联盟网络,对于新来的参与企业,它的接入复杂度和成本也是一个不小的问题。


针对上述各种问题,我们在阿里云BaaS基础之上,结合了CEN云企业网,提供了一种安全的联盟链网络方案,主要面向高端需求的企业用户。

方案的核心,是采用CEN云企业网打通不同企业的VPC网络,就像一张跨企业的环网,这样不同企业不同的VPC内的网络就可以在CEN内实现全连通。

在实现网络连通之后,因为阿里云BaaS联盟链中的Peer,Orderer,CA等服务是通过域名来访问的,目的是提升应用访问的灵活性,而在CEN的这套方案中,我们可以结合云解析PrivateZone,来实现企业环网内各企业VPC之间的统一域名解析。而且上述的网络连通性和域名解析仅限于联盟内部,不会暴露到外网。

除了在公共云环境之外,对于那些将区块链节点部署于本地IDC的企业来说,他们也可以通过VPN或者专线方式,接入到云上已和CEN打通的任一VPC中,便可实现和联盟任意节点的通信。

作为一个小提醒,在方案实施环节,需要注意提前规划好不同VPC内的内网地址分配,避免在环网中发生冲突。

这样我们便形成了一套真正跨企业、跨账户,打通各个VPC的安全联盟链网络方案。


下面我们将探讨一个非常有挑战性的问题。众所周知,智能合约是区块链的一个核心。Hyperledger Fabric中的智能合约即chaincode是运行于容器当中。在上面这幅图里我们总结了Hyperledger Fabric的chaincode容器生成过程的示意图:

  1. Peer通过Docker Client发起对Docker Daemon的调用,以fabric-ccenv为基础镜像创建出一个chaincode构建容器(chaincode builder container)
  2. Peer将chaincode源代码传入chaincode构建容器,在里面完成智能合约编译
  3. Peer再调用Docker Daemon创建以fabric-baseos为基础镜像的chaincode镜像,并将在第2步编译好的chaincode二进制文件内置在chaincode镜像中。
  4. 启动运行chaincode容器。

从上述过程我们分析一下这里面存在的一些问题:

  • 由于该过程是独立于Kubernetes体系之外运行的,难以对chaincode容器进行生命周期管理。
  • 无法基于Kubernetes的namaspace隔离、NetworkPolicy等机制实现对chaincode容器的安全管理。

针对上面分析发现的问题,我们研究了几种问题解决的思路。

第一种思路,是将chaincode容器纳入到Kubernete的体系(如pod)进行管理。

这在我们的角度看来,其实是最理想的方案。因为它不仅可以实现chaincode容器全生命周期与Fabric其他类型节点一致的管理方式,并且可以结合Kubernetes的NetowrkPolicy控制chaincode容器的网络访问策略。

其实此前Hyperledger Fabric社区已经创建了一个相关的需求即JIRA(FAB-7406),但目前仍未实现。

假设未来在此功能实现之后,我们进一步展望一下,还可以将智能合约的容器调度运行于Serverless Kubernetes之上,提供kernal级别的隔离,保证应用容器之间的安全隔离。


第二种思路,如社区和网上的一些观点所提到的,将chaincode容器放入Docker-in-Docker(DIND)环境运行。

这个思路背后的出发点,主要是为了降低对宿主机Docker Daemon的依赖以及动态生成chaincode镜像和容器的不可管理性。

对于这个思路,我们也基于Hyperledger Fabric和Kubernetes进行了试验,在右边的这部分Kubernetes部署模板yaml代码里,绿色框的部分是用于配置DIND的容器作为peer pod的一个sidecar,同时将DIND容器内的Docker Daemon通过本地端口2375以环境变量的形式配置到peer的参数中,使得peer可以将chaincode创建相关请求发送到DIND内。

通过对结果的观察和分析,我们发现了以下这几点。

DIND的思路有如下一些优点:

  1. 无需依赖宿主节点的/var/run/docker.sock。
  2. 无需专门清理每个Kubernetes worker节点的chaincode镜像。

但DIND有着一些更为明显的不足:

  1. 每次创建部署或恢复peer节点会变得很慢,因为DIND内需要去拉取fabric-ccenv镜像,其大小约1.4GB;而如果用传统部署方式的话,只需在worker节点拉取一次镜像即可。
  2. Chaincode的实例化(instantiate)过程稍微变慢,推测这和DIND容器本身运行所需的开销有一定关系。
  3. 当peer节点或者整个组织(organization)删掉重建之后(复用原有的数据目录),启动速度比起传统方式会慢很多,这背后的原因和第1点相同。
  4. 在业界实践中,DIND方法主要用于CI/CD的场景,但对于生产环境使用的话,则在稳定性等方面仍有较多的挑战。
  5. DIND的思路仍然不能解决chaincode容器的安全访问控制和隔离的问题。

第三种思路,是我们目前在BaaS中采用的方法,即综合各种配置的手段先解决最主要的问题。这包括以下几个方面的工作:

  1. 首先,通过Fabric peer的合理配置(如图中右上角的示例配置)保证chaincode和peer的通信。
  2. 其次,使用docker rm和docker rmi命令清理chaincode容器和镜像(它们均包含“dev-”前缀)。这里面有不同的可选位置。
    2.1 适合事后清理的可选位置是采用DaemonSet结合lifecycle.preStop.exec.command的位置来运行这些清理命令。

2.2 适合事前清理的可选位置是在initContainer中运行上述清理命令。

  1. 采用iptables规则,对chaincode容器进行网络隔离。主要是通过在Helm Chart安装阶段配置Kubernetes worker节点的iptables规则,实现限制chaincode容器对Kubernetes网络和对外部网络的访问(同时也可以限制进入chaincode容器的网络访问)。

通过上述一系列手段,我们得到了对chaincode容器实现生命周期管理、安全隔离和网络访问限制的一个实用的方案。未来我们也会继续朝着思路一这种最理想方式进行更多的探索。


今天阿里巴巴集团的区块链已经在多个行业、多种场景实现了结合以及业务落地,包含了如商品溯源、数字内容版权、供应链金融、数据资产共享、公益慈善、医疗处方等等。我们的客户在生产环境已经达到了百万级的交易规模以及百GB的账本数据,这也为我们提供了很丰富的区块链应用实践经验。


基于这些实践,我们想跟大家分享的是,其实区块链应用设计开发并不复杂,这一页总结了构建于Kubernete之上的区块链系统和应用的基本模式。可以看到,Kubernetes帮我们解决了底层基础架构和资源的复杂性,提供了应用的标准底座;而区块链服务BaaS则帮我们解决了区块链系统配置部署和运维的复杂性,提供了统一的接口,那么对企业来说,便可以聚焦在业务流程和业务逻辑的实现,及业务应用的开发上,以及与业务数据的交互和管理上来,实现核心价值的最大化。


下面,我们将进行阿里云BaaS Hyperledger Fabric的一个demo,主要展示一下几方面的过程:

  • 首先,快速创建跨企业(跨账号)、跨region的联盟链。
  • 接着,动态添加新组织、新通道,完成企业间协同,包括邀请企业,以及企业各自的审批流程。
  • 在一些关键操作点上,BaaS内置了风控保障,强制邀请短信验证才允许完成操作,这看似麻烦的环节实际上是企业对生产安全保障以及审计都非常看重和需要的。
  • 最后,我们在BaaS上部署了经典的Marbles虚拟数字资产交易的应用,包含chaincode的部署和client SDK应用的部署。

最后,欢迎有兴趣的朋友进一步了解和使用阿里云的区块链服务BaaS,通过扫描图中的两个二维码可快速访问相关产品主页,申请开通免费公测试用,以及访问产品文档获得更多使用和开发指南。

以上就是我今天跟大家分享的全部内容,谢谢大家!



本文作者:余珊

阅读原文

本文为云栖社区原创内容,未经允许不得转载。