在 Gopher Meetup 杭州站上,阿里云高级技术专家汤志敏进行了主题为《Serverless Kubernetes 场景和架构剖析》的演讲。
容器和无服务器是当下云原生的火热主题,二者的结合极大降低了容器的使用门槛,减少了总体计算成本,也让用户摆脱了底层基础设施管理的复杂性。然而提供一个规模化和高弹性的 Serverless Container 基础设施不是一件容易的事情,要综合考虑规模、弹性、成本、效率等因素。本次演讲即为针对以上问题的详细讲解。
以下为演讲实录。
01
Serverless Kubernetes 基本介绍
Application Deployment:Toward to Cloud Native
在早期的话,大家都是通过虚拟机或者物理机来部署,你可以通过脚本或者RPM包来安装。到第二阶段时候大家都知道容器出现了,我们可以通过容器去编排应用。在2015年Docker的出现,使得大家可以通过Docker的镜像,去把应用和依赖做一个整体的部署,可以享受到容器的这种敏捷、高密度,可移植性等特性。
在 2017 年底的时候,Kubernetes 赢得了容器编排的三雄争霸的胜利。在 Swarm、Mesos 和 Kubernetes 之中,取得了的大面积的使用。最后,我们来看下现在很多人都在讲 Serverless 无服务器计算,Serverless 最大的好处是我们可以不用对底层的基础设施去更多的了解,可以极大的释放我们的研发效率。整体来看的话,我们整个运维跟开发的习惯已经越来越向云原生方向来演进。从左到右来看,我们作为一个开发者,越来越多的可以减少对底层服务器和基础架构的关心和控制,帮助我们提升效率。从下到上来看,可以让开发聚焦在核心业务逻辑的开发,通过这样的方式能够让我们企业的研发效率能够更高。
接下来看一下Serverless这个词,可能最近一两年讲的特别多,那么到底是什么是 Serverless,每个人有自己不同的见解。有的人说 Serverless是 FaaS 加上 BaaS,通过这样的方式,我们可以快速地做开发。我觉得 Serverless 至少有几个特征或特性。首先从字面意思来讲,Serverless 跟 Serverful是相对的,Serverless不用管服务器。其次,Serverless是可以做到快速的自动扩容和事件驱动。最后来讲的话,Serverless 可以让你做到按量计费或者按照使用次数来计费。在 Serverless 时代,我们每个开发者对自身的研发或者架构能力的要求是什么?可能是需要我们进一步去思考。
Serverless Runtime
接下来我们从 Serverless runtime 的角度,来看一下我们对 Serverless 的理解。
简单来讲可以分为三种, Serverless 的交付可以分为面向容器、面向应用和面向函数。这三种形态可以解决不同的问题,他们在灵活性和在研发效率上是不一样的。我们可以依次来看一下。
第1种是面向容器,大家都知道容器是非常灵活的,我们可以通过容器来去交付你的任何应用。对于开发者跟平台方来讲,因为关注的是容器,所以不用关心容器内部跑的是什么编程语言。所以可以基于容器来做非常丰富的框架和非常灵活的定制。也可以享受到容器的很多编排特性,包括有状态、无状态应用和任务等调度能力。
第2种是面向应用, 早年Google 推出的 App Engine,可以认为是 Serverless 的一个早期鼻祖。对于Java 或者 php等应用, 我们只需要去部署一个war包、jar包或zip包,来灵活的管理。他的好处是抽象层次更高,但是弊端是会限定到特定的语言框架,如Java框架、特定的 php版本和特定的go的框架,所以在灵活性上可能会有一些损失。
第3种是大家熟知的面向函数。面向函数来讲的话,包括最早亚马逊提出的Lambda,和阿里云 的函数计算服务,我们只需要提交代码片段,就可以方便的做开发。但是正是因为你提交的是一段代码片段,所以我们在整个应用框架和通信框架上有了更多的一些限制。面向函数的场景,非常适合通过基于事件驱动的方式,快速的把你的代码片段启动起来。
我们可以选择合适的 Serverless的方案来解决不同的问题。如果你有一个非常简单的事件驱动应用,可以选择面向函数的Serverless,如果有一个非常复杂或者是说定制性很强的场景,我们可以选择基于容器的 Serverless。
Serverless Kubernetes: 关注应用,不用关注基础设施
回到我们正题,今天要分享的是 Serverless Kubernetes。用一句话定义,我们提供了一个兼容 K8s API 的 Serverless基础设施。它有几个特性。
第1个,它所有的接口都是可以支持面向容器的,所以我们可以享受到容器的敏捷性和其他优点,同时不会有面向应用或者函数计算的一些限制。
第2个,因为是Serverless Kubernetes,所以可以不需要管理非常多的 K8s 的 worker 节点。大家都知道,如果你维护一个 K8s 集群,比如说有几百台上千台的机器,你需要维护这些机器的升级和安全漏洞修复。而这些在 Serverless 场景是不需要考虑的。
第3个,也是 Serverless 的特性,基于 Serverless 容器的横向的弹性扩容和缩容。
最后可以做到Pay as you Go,可以按照应用的容器的CPU等规格来计费,而不需要像传统的先买一堆机器,要考虑机器到底有多少资源。这样可以做到很大的总成本降低。在这里介绍完,希望大家对我们的Serverless Kubernetes有一个初步的理解。
02
Serverless Kubernetes 架构设计
接下来进入第2个部分,我会介绍一下 Serverless Kubernetes 的架构设计,考虑到每个人对 Kubernetes 的理解会有些不同,我们先回顾下一个经典的 Kubernetes的架构。一个经典的架构可以分为两个部分。上面部分是 master,包含了一些核心组件。开发者可以通过撰写一个yaml的格式,去定义你的应用是按照什么样的workloads去运行。下面部分有一个 worker池,需要考虑把这一堆容器编排调度到不同的机器上去。
这里有两个名词要强调一下,第1个就是pod,它是针对一组容器进行了一个管理,这一组容器的网络和存储是共享的,所以可以做到一个非常好的亲和性。第二个是kubelet,kubectl 是你在机器上的agent,可以把这台机器上的所有资源上报到master。它会告诉这台机器有多少 cpu、memory,然后我们的 Kubernetes 的 master 就可以把很多机器统一的管理起来。Kubelet的另一个职责是管理pod的生命周期,它可以接收 master 的指令,会根据请求看哪台机器比较空闲,把pod下发下去。这里简单回顾了一下,什么是一个标准的 Kubernetes 的架构,
回到我们今天的正文,如果要设计一个 Serverless Kubernetes该怎么做呢?顾名思义是说我们不需要再管理这一堆机器池了。首先对于开发者来讲,他的理解有什么不同。作为一个K8s的开发者,原先需要关心pod的亲和性策略,一个deployment会部署到不同机器上去,所以需要关注不同机器的拓扑关系。而在 Serverless 场景中,因为根本没有 node 这个概念的,所以我们可以只关注pod本身。对于平台方来讲,需要考虑如何把一个经典的 K8s 架构能够演进成一个 Serverless K8s 的架构,如何把一个二维的结构(先挑选node再部署 pod)变成一个一维结构(只关心POD的资源消耗)。接下来我们做了一个核心的架构策略,就是解耦容器编排和容器资源生产。这个架构是我们的Serverless Kubernete的核心思想,整个架构设计分成了三个部分。
核心架构策略:解耦容器编排和容器资源生产
第一部分, 不需要关心有多少个 node,只关心需要多少个 pod或容器。所以我们希望有一个独立的组件或服务。它可以去管理 pod 的创建和生命周期,可以负责生产4C8G或0.25核的 pod,而不用先找一堆机器再分配资源。
第三部分,就是说Serverless Kubernetes本身,目标是兼容K8s API,它可以满足更多的生态和应用场景,所以我们会尽量复用 Kubernetes 的一些调度能力。
第二部分,相当于基于Virtual Kubelet 的组件,把 K8s 的调用逻辑跟底层的容器资源生产做一个协调,实现连接器的作用。
通过这样的一个架构,可以把容器的编排和容器的资源生产做了一个解耦,后面我会介绍这样设计的好处。接下来我会依次介绍下每个模块的现状和一些设计。
ECI: Elastic Container Instance
前面讲的第一部分,是说我们希望把容器的资源生产当做一个独立的模块或产品,现在我们这个产品叫做ECI,Elastic Container Instance。我们希望这个产品能够承担容器的无服务器基础设施。这里有一个我们在初期讨论比较久的概念,如果提供一个容器的基础设施,它的接口会怎么定义?
K8s 的核心概念是一个 pod 概念,一个 pod有多个容器,所以当初我们做了多轮的讨论:这个面向容器的无服务器基础设施,它应该是面向 pod 还是面向容器的?经过我们大量调查发现,且我们相信未来越来越多的应用大部分会基于 Kubernetes 进行部署。所以我们做了一个策略,希望容器是面向 pod 的。不过在这一个设计约束之下,我们并没有把我们容器实例服务的接口定义为 pod,而是定义了一个名词叫做Container Group , 它可以兼容 pod 语义。通过这样的方式,我们提供了一个面向pod或Container Group 的标准API,任何人都可以基于这个API去生成 pod资源。作为一个基础设施,它必须要满足我们对 Serverless 的一些遐想或者说要求,它必须有非常细粒度的资源,我们现在可以提供 0.25 核 CPU 的细粒度的规格。如果你去买一台服务器,可能最少是 1 核 1G 起,所以从这个层面来讲,对于低资源功耗的应用使用这样的一个基础设施是可以有巨大的成本节约。此外,在高规格上也支持了64核和其他一些特性。同时也可以做到秒级的启动和部署。
Key Design of ECI
从实现的角度,生产容器也需要一堆物理机资源。这个架构和我们在阿里云上生产虚拟机是类似的,所以我们可以做到资源的统一调度,即混部。可以在阿里云几十万几百万台的物理机上,同时部署传统虚拟机和面向pod的容器,通过这样混合部署之后把原来物理宿主机上的资源碎片充分利用起来。从这个程度来讲,整个容器的基础设施能够做到成本最大化的节约,可以充分的享受到阿里云大规模的计算能力。如果有些小厂商它的资源池不够大的话,是很难把成本做的足够低。除此以外,ECI可以和阿里云虚拟机的很多能力做复用,比如热迁移、统一管控和故障定位等能力,从而让我们的这种面向容器实例的产品做得更加强大。
最后做个阶段总结:第一,我们定义了一个Container Group的接口;第二,可以做到跟阿里云的虚拟机做一个混合部署;第三,从容器隔离的角度,我们也支持不同的技术演进,比如通过一台虚拟机部署容器组的方式来实现强隔离,或者基于类似KataContainer的安全容器技术来隔离。通过这样的一个良好的抽象,我们可以让我们的弹性容器实例满足不同的需求。
Virtual Kubelet: Connect Kubernetes with ECI
第二部分,通过Virtual Kubelet将容器资源生产和 K8S 的调度能力做一个解耦。前面提到基于 Kubelet 可以做到整个node资源的注册,获得POD的生命周期管理。但实际上在Serverless场景中,已经没有传统 K8s的这些机器池了,我们需要基于 Virtual kubelet 的协议来做了一个新的实现,把这些实现能够对接到ECI 上去。比如如何获得 node 的状态,如何创建POD或获得POD的列表,通过一个语义的翻译,实现POD的创建等生命周期管理,通过我们底层的容器无服务基础设施来承载。这里有个链接,我们已经把这段逻辑开源出来。此外Virtual Kubelet已经成为CNCF的Sandbox项目,大家有兴趣的话可以了解一下。
Serverless Kubernetes
再回到Serverless Kubernetes。Serverless Kubernetes 因为可以做到0节点,而不像传统的 K8s必须有两三台的 worker,所以从第1天,它的架构就可以让我们做到一个非常灵活的成本的节约。只需要在真正部署pod的时候,才会按需的去调用底层的接口,来创建一个容器实例。另外基于底层的ECI的资源池,我们可以做到一个基本无限的节点弹性。此外,我们希望能够他能够兼容 K8s 大部分的编排能力,可以无缝的连接 K8s 的生态, 使用标准的workloads,后续我们会更细节的介绍。
Serverless Kubernetes vs. Classic Kubernetes
这里简单对比下 Serverless Kubernetes 和经典 K8S 。传统 K8S 需要管理几十台上百台的机器,包括集群的容量规划、升级运维、安全修复等。而对于 Serverless Kubernetes 来讲,由于没有节点概念,你完全不需要去操心底层的资源容量规划和节点的运维,从而有非常好的Serverless 的特性。
Serverless K8s: 面向云规模的Nodeless架构
这里我们来看具体的一些实现。其中蓝色标出来的是一个 VK 组件。
大家对K8s比较了解的话,比如部署一个web应用,需要先部署一个10个replica的Deployment,包含10个POD,对于pod的生成,可以将它映射到底层的 ECI 容器实例上。
如果要让这个web应用被外界访问,需要创建一个 service来做负责均衡。我们可以基于阿里云的负载均衡 SLB,可以将 SLB 挂载到我们后端的ECI上去。
同样对于Kubernetes内的DNS能力,比如CoreDNS, 在云上可以基于阿里云的PrivateZone实现DNS的解析转换。
右上角橘黄色的图里描述了ECI内部可以做POD的生命周期管理。
Serverless Kubernetes 模型映射
对于一些 K8S 的PV\PVC, 同样可以映射到阿里云的块存储、对象存储和文件存储。通过将 K8s 的一些标准原语和底层的实现做一个映射,我们可以实现一个面向云规模的一个Nodeless架构,提供了几乎于无限容器容量的 K8S 产品能力。
Serverless Kubernetes 2.0 – New Release
这里介绍下我们最近做的Serverless Kubernetes 架构升级。在此之前,大部分友商的无服务器容器产品,都是基于Kubernetes的Namespace作为租户隔离暴露给用户,这样的话有很多约束。因为 K8s 在整个架构设计上,并不是所有的资源都是充分隔离的,比如说CRD、RBAC等资源是全局的,所以很多功能是用不起来的。
在今年阿里云的Serverless Kubernetes做了一个演进,可以把Serverless 的编排模块变成一个纯单租的架构,每个Serverless K8s的master都是独立的,好处是不同的 serverless K8s 互相之间是并不会干扰,从而实现基本上等价于标准 K8s 能力的一个Serverless服务。可以更好的支撑场景,比如Knative、Istio等技术。此外,在单租的架构下,可以很好的跟用户VPC做点对点的打通,可以实现较好的安全防护。
Virtual Node in Classic Kubernetes
前面提到可以通过创建一个独立的Serverless K8s集群来实现无服务器的容器管理。然后我们可能已经有一些标准的Kubernetes集群。比如新年促销或双11活动,需要考虑到一些突发资源准备。我们是否可以把传统的 K8S 跟我们今天讲的Serverless 技术服务能够打通起来,这里我们提供了一个叫做 Virtual Node的能力。在添加 Virtual Node之后,相当于新增一个无限容量的虚拟节点。所以当我们在容量不够的时候,其实我们可以自动将新扩出来的pod扩容到虚拟节点上去,从而免去了我们再去采购服务器和添加机器的必要。此外也可以在 K8s 的某个特定Namespace里添加标签,可以让这个Namespace的容器都自动部署到虚拟节点上。这里我们可以让一个普通的 K8s 也享受了近乎无限容量的虚拟节点能力,也更好的支撑了K8s上的生态。
VK-autoscaler:应对在线业务的弹性伸缩
此外我们也做了一个弹性伸缩的增强。在传统场景,K8s 的调度发现有一个资源不能满足的时候,会触发新的机器的创建。在Serverless的场景,当一个 Deployment 不能横向扩容的时候,可以自动的去触发虚拟容器的一个部署,实现一个完美的整合。
接下来重点看下哪些典型场景比较适合Serverless Kubernetes。
03
典型场景案例
案例一:Use Virtual Node at scale with kubernetes
首先看第1个场景,一般企业都会有业务的波峰波谷,比如晚上做一些定时任务需要有一些额外的资源去运行,这个时候可以把活动任务自动的去调度到虚拟节点,从而实现计算成本的降低。此外,通过虚拟节点来弹性伸缩POD是比弹性伸缩节点更快的。
案例二:Adopting ASK on CI/CD Pipeline
第2个场景,关注下 CI/CD 的场景,比如现在比较火的Tekton,可以基于独立的Serverless Kubernetes实现快速镜像构建。这种 CI/CD 场景非常典型,只有在做构建时候才会需要一堆资源,而正常情况就是零节点。通过这样的方式,可以很好的让整个开发和测试团队做到成本最优和高效的研发效率管理。
案例三:在线教育的录制和转码
第3个场景,比如视频制作或者转码,它往往需要一个非常大的计算量,而往往很难估计到底需要多少资源。这个时候通过虚拟节点的使用,可以避免预留资源池,从而实现快速弹性进行编码或解码的制作,可以很方便地节省成本。通过类似的架构,我们曾经帮助一些厂商把成本降低50%以上。
Serverless Container应用场景
最后我们总结一下Serverless Kubernetes的众多应用场景和三种使用方式。如果你需要一个完整的 Serverless Kubernetes 能力,可以创建一个单独的集群;如果已经有一个标准的K8s集群,可以通过虚拟节点的方式来使用;第三种是可以通过ECI的API来自主管理容器资源。
Pricing: 按需收费/多种计价模型
接下来分享下Serverless Kubernetes的定价模式,目前我们提供了几种方式:按量是按照你使用的 CPU 规格来计费;预留实例,相当于一个资源包, 比如提前做个规划,预计会使用 1 万核 资源;竞价实例,相对最便宜。比如刚刚提到的视频编解码任务,它的时效性可能并没有那么关键,所以可以基于竞价实例。如果你的价格比别人高就可以持续使用,如果别人出价比你高,你云资源可能被抢掉。但对于编解码来说,从两个小时到三个小时可能没那么重要。
从价格的角度来说,我们需要考虑不同的应用负载而选择不同的这种定价和计费模式。在 云计算和Serverless 时代,我们作为一个开发者,要思考自身技能会有什么样的变化?前面提到,Serverless化了不用管理服务器和基础设施,我们确实减少了很多职责,但是我们要更加思考应用的业务模式,了解业务背后的缩扩容模式和游戏那几模式,要把整体业务的规划结合云计算的成本模型来进行更系统化的思考。正如早期的DBA会转型到数据架构师。
最后介绍下阿里云的容器产品族。大家可以针对性的选择标准的 K8S或者Serverless 的 K8s 的服务。如果想了解更多Serverless Kubernetes的特性,请参考我们的云栖介绍文章“Serverless Kubernetes入门:对kubernetes做减法”(https://yq.aliyun.com/articles/730349)
今天的分享就到这里,谢谢大家。
Q & A
提问:我一共有三个问题,第1个问题想问的是底层的容器安全隔离是采用了哪一个技术?是还有一个,剩下的就是K8S里面的网络是平行的,然后你的产品是开放出去的,如果你的 Serverless里面有一个坏的逻辑,比如说有一个用户专门是恶意的一个容器在里面,它同时可以因为网络是通的,在安全上做了哪些东西?
好,第1个问题我忘了一个,就是在 Serverless 容器秒启动里面,你们做了哪些努力?然后最后一个,希望介绍一下 Serverless 现在的市场情况。
汤志敏:谢谢,问题比较多,我来解答一下。第1个问题是说底层的容器的隔离选择哪一个?目前来讲我们是有两套架构在并行,然后会不断的演进。第1个是说我们可以基于一个轻量级的虚拟机,可以部署多个容器。这套架构,它是可以天然是跟我们虚拟机做混合部署。第2个也是说大家都比较熟悉的基于KataContainer 的安全容器,并且我们内部也有一个专门的优化项目,然后也在很多场景做了一个使用。
提问:普通容器的隔离性不是很好,安全容器的独立性虽然比较好,但是启动会比较慢。你们在实现容器的秒启动上做了哪些努力?
汤志敏:在启动优化上有很多要考虑的方向,实际上启动容器也分为很多个步骤。比如容器的调度、容器镜像的拉取。在容器的镜像拉取优化上,我们支持基于镜像快照,可以通过快照的技术快速的把镜像拉起来,而不需要先把镜像从远程拉下来,再解压到本地。在容器的调度上,我们做了较多的网络初步化和虚拟化初始化的优化。基于这一切的优化努力,目前我们已经把单个pod的启动时间降低到10s以内。
提问:还有一个就是安全性上的,因为K8S里面的容器网络都是平行的,不同pod之间都是可以互相访问的。
汤志敏:即使不考虑 Serverless Kubernetes,在 Kubernetes 中也有很多标准的网络隔离技术,比如可以通过Network Policy去做不同 pod 之间的网络ACL隔离。此外,我们也基于阿里云的高性能网络Terway, 实现了网络流控和QOS限制。目前我们在 Kubernetes 的管控平台已经有很多能力了,在虚拟化底层也做较多保障。在Serverless Kubernetes中,我们可以很灵活的通过安全组的能力限制pod之间的互通。
提问:还有一个现在无服务的市场程度、接受程度怎么样?市场是否成熟?
汤志敏:我个人理解是这样子的:从跨越鸿沟的角度,整个云计算不同的技术有不同的发展历程。在 Serverless 场景,它是有一个比较明确的应用负载特征倾向,可以解决很多短任务或者是一些突发的流量,会占据一个比较垂直的市场,短期不会把所有标准的 K8s场景和所有的工作负载的场景全部覆盖掉。
提问:刚才像您讲的话,现在如果我们用 Serverless Kubernetes的话,我们是感知不到底层的一些 node 吗?他在我们原有这些混台词这种容器调度里面,基于这种策略的 pod 和 node 之间的一些策略,或者是一些亲和性的这些策略,我们如何来做?
汤志敏:这是一个非常经典的问题。前一阵子伯克利写的一篇论文,在讲 Serverless 是如何简化云计算。但实际上在某些场景是有一些局限性的。如你说的场景,除了可以按照node 做调度,实际上在node内部还可以做一些Locality。而在Serverless 的场景中,这些能力已经不再适用,所以在使用Serverless场景的时候,可能会牺牲这一点。
但从另一个角度,我们的编排框架在Serverless领域可能也要做一个演进。我们要能够换一种思维,通过分布式的缓存来解决原先node的亲和性。对于Serverless平台来讲,需要将更多的能力下沉到平台。
重磅活动预告
Gopher Meetup 上海站即将开启。来自蚂蚁金服&携程、趣头条、讯联数据、TutorABC的大咖讲师将带来 Go 开发领域的一线实践经验分享,尽在12月14日,微软加速器!
报名请戳:阅读原文
Go中国
扫码关注
国内最具规模和生命力的 Go 开发者社区
欢迎投稿,请联系:
situzhihui@163.com