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

38次阅读

共计 8936 个字符,预计需要花费 23 分钟才能阅读完成。

笔者注:本文是在 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 容器生成过程的示意图:

Peer 通过 Docker Client 发起对 Docker Daemon 的调用,以 fabric-ccenv 为基础镜像创建出一个 chaincode 构建容器(chaincode builder container)
Peer 将 chaincode 源代码传入 chaincode 构建容器,在里面完成智能合约编译
Peer 再调用 Docker Daemon 创建以 fabric-baseos 为基础镜像的 chaincode 镜像,并将在第 2 步编译好的 chaincode 二进制文件内置在 chaincode 镜像中。
启动运行 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 的思路有如下一些优点:

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

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

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

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

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

2.2 适合事前清理的可选位置是在 initContainer 中运行上述清理命令。
采用 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,通过扫描图中的两个二维码可快速访问相关产品主页,申请开通免费公测试用,以及访问产品文档获得更多使用和开发指南。
以上就是我今天跟大家分享的全部内容,谢谢大家!

本文作者:余珊阅读原文
本文为云栖社区原创内容,未经允许不得转载。

正文完
 0