Knative Serverless 之道:如何 0 运维、低成本实现应用托管?
导读:Serverless 无疑是当前最热的云原生话题,那么作为业务的开发人员或者运维人员咱们应该怎么看待这个事情?云原生和 Serverless 到底有什么关系?通过本次分享咱们将逐一揭开这些神秘的面纱。
通过本文您将了解到:
- Knative 是如何让普通的应用具备 Serverless 能力的?
- 为什么说 Knative 是云原生的应用 Serverless 编排引擎?
- Knative 为什么是由 Tekton 、Eventing 和 Serving 三个模块组成,以及这三个模块的协作方式。
本文共有四部分内容:首先咱们一起来看一下云的核心驱动力是什么,接着从这个核心驱动力出发看一下云原生应用是什么样子。然后咱们再一起来看看 Knative 到底给应用的云原生化带来了什么价值,最后咱们通过一个 Demo 亲身感受一下 Knative 带来的这些能力。
云的核心驱动力
在讨论云原生之前我们先来思考一下:为什么企业要上云、为什么技术人员要学习面向云的编程思维以及咱们应该怎么看待云这件事儿。
咱们先来剖析一下发生这些事情的核心驱动力,然后通过这个核心驱动力出发看看整个云原生技术栈是什么样子。
社会分工
我们先从一顿火锅谈起,一顿火锅虽然很简单,但会涉及到非常多的东西,比如各种蔬菜、牛羊肉等。细想一下,所有的这些东西我们都经常食用,但是其中有哪些东西是我们自己亲手种植或养殖的呢?事实上都没有,我们每天都是坐在办公室,下班的路上到市场或超市买到这些东西,不知道也并不关心这些东西的具体生产过程。
我小时候在内蒙的农村长大,大家都知道,内蒙很大。村里每户人家都有一个大园子,夏天的时候家家户户都会在园子里种植各种蔬菜,如西红柿、黄瓜、茄子、辣椒等;但到了冬天,由于天气很冷,根本见不到新鲜的蔬菜,大家吃的都是咸菜、酸菜,或者是秋天晾晒的一些干菜。我们可以发现:一个地域非常容易受到季节的影响,虽然夏天可以种植各种蔬菜,但是到了冬天就什么都没有了。但是现在就不同了,全国各地随处都能非常容易地买到新鲜蔬菜,这其实是社会分工的结果、是不同地域、不同角色之间通过市场相互协作的成果。
现在因为有专业的人在做这些事情,所以我们大多数人都无需劳心蔬菜是怎么种植的。而我们工程师所做的和计算机打交道的事情也能通过其他的渠道反过来帮助那些种菜的人。
分工提高效率,这是现代经济学之父亚当斯密 200 多年前在他的经典著作《国富论》中的开篇观点。其实现代社会的运行机制也印证了该理论;我认为它也是企业拥抱云计算的根本原因。因为大家需要把一些非业务核心的部分“承包”给专业的人士去完成,那些和自己的业务强相关的部分才是企业的核心竞争力。
应用上云
接着咱们再来看看一个应用都是由哪些部分构成的。
应用要提供服务首先要有计算、存储和网络资源才能把进程跑起来。当然这些也仅仅是把进程跑起来,如果要承接具体的业务还需要依赖数据库等服务;如果要做分布式架构还需要做微服务拆分,这时候就需要缓存、注册中心、消息各种中间件的服务。
以上的情况都是程序已经存在,如何把程序跑起来承接业务的部分。还有一部分是如何把代码变成可启动的程序,这就是 CICD 部分了。从代码到应用启动再到应用依赖的周边系统支撑都说完了,还有一部分就是日常运维相关的:
- 比如日志收集、分析
- 比如监控和告警
虽然我们本来只是想要写一个应用,来为业务提供服务。但是应用周边的这些支撑系统比这个应用自身的消耗还要高上很多。这其实不是我们期望的结果,让业务团队更多的聚焦在业务逻辑本身,而不是周边的这些系统上,这才是我们希望看到的。
实际上有一定规模的公司,内部的组织架构基本也都是由一个基础平台团队和多个业务团队构成的,基础平台团队负责提供这些应用需要的公共能力支撑,业务团队更聚焦在业务上,直接使用基础平台团队的能力即可。这其实就是社会分工在 IT 组织中的体现,专业的人做专业的事儿,分工提升效率。
现在我们再回顾一下刚才吃火锅的例子。
如果时间倒退 20 年,回到北方的冬天,我们想要吃一顿有肉、有蔬菜、还有金针菇的火锅,根本就不可能,但是现在,我们可以随时随地买到这些东西,而所有这些都是专业的人士生产的,我们无法自给自足这么丰富的资源。
那么对于一家企业而言,也是一样的。虽然每个企业都有自己的基础平台团队,但是由于规模或者资金投入等原因,不可能提供像云这么丰富的平台支撑。如果有,那一定也是一个云厂商。所以对于业务来说,把所有和应用相关的周边系统都使用云的初始设施搭建,把这些周边系统承包给云厂商才是高效率的做法。我理解为这就是云原生出现的背景。
分工提高效率这是大家使用云的根本动力。云原生理念是在各大企业上云的过程中逐渐形成和完善的。这套理念是协调所有参与方对服务上云逐渐形成的统一标准,这个统一的标准可以很好地帮助企业上云、帮助云厂商释放云的能力。从云的客户角度来讲,这个统一标准就是避免云厂商锁定。比如 Kubernetes 就是一个非常好的统一共识,因为所有云平台都支持 Kubernetes。
那么这个标准的价值是什么呢?为什么云厂商和上云的企业都积极参与这个标准的“制定”呢?这其实是一个互利互惠的结果。在具体谈论这个标准的作用之前,我们先来聊聊两种资源分配模式的差别。
排队(先到先得)
这部分咱们以就医为例进行说明。
去医院看病需要提前挂号,医生的号源这是一种先到先得的资源分配方式。特别是在北上广这些大城市,好医生的号源更是一号难求。如果想保证一定要拿到某个医生的就诊号,就要保证比别人都更早地到医院排队,提前排队可以优先拿到就诊号。我们现在来分析一下,提前排队的人所付出的努力都有什么价值。
- 对于排队的当事人:当事人付出的努力对于自己是有意义的,自己拿到了就诊号,得到了回报;
- 对于其他的排队者而言,是没有任何好处的。早来的人拿到了就诊号,这就给别的竞争号源的人发出了一个信号——来的越早就越有可能得到号源。这有可能引发更多人更早的前来排队,这是一个恶性循环;
- 对于医生来说,没有任何意义,谁来看病都是一样,谁得到这个号对医生来说差别不大。很多时候甚至患者要求加号,但医生其实是不愿意的,因为每增加一个号源就意味着医生要付出一点儿休息的时间。对于医生而言,多付出的休息时间是不能换来更多报酬的,因为这是一个先到先得的排队秩序规则,每一个号源的价格都是一样的。
有没有发现在排队的过程中所做出的付出只对排队的当事人是有意义的,对于医生以及其他排队者都没有任何意义,甚至会带来恶性竞争,造成社会资源的巨大浪费。在排队的过程中,大量的资源都白白地流失,没有给社会带来任何价值。
市场经济
这部分我们以购买云服务器 ECS 为例进行说明。
假设目前阿里云的 ECS 是性价比最高的,大家上云都优先选择使用阿里云的 ECS,那么如果出现供不应求的情况就可能会导致 ECS 价格上涨,而价格上涨就会导致更多的云厂商供应 ECS ,最终导致价格又回落下来。我们分析一下在这个过程中购买 ECS 的人和提供 ECS 的云厂商之间的关系:
- 我们发现大量客户选购 ECS 这件事情本身对于上云的客户是有益无害的,因为大量的需求会导致云厂商做更多的供应,价格不可能持续高攀。所以 ECS 需求的竞争者之间其实不是零和博弈,而是一个相互合作的关系。大家一起把饼做大,就让整个供应链更稳定、便宜。就好比我买苹果手机,你也买苹果手机,但是咱俩不是竞争关系,而且买的人越多,苹果手机的质量就会越来越好;
- 大量的 ECS 需求会促使 ECS 技术的成熟。对于 ECS 的提供者云厂商而言,越多的人购买自己的服务就越好,所有的客户和云厂商之间都是相互促进的关系。
市场经济这种基于价格的自由交易能够非常高效地促进大家的合作,任何一方的努力对于其他的参与者而言都是有价值的。和医院排队中先到的人付出的努力只对自己产生价值相比较,市场经济的自由交易方式中,每一方的付出都让整个系统得到了优化,这是社会资源合理利用、合理分配的一种非常好的方式。
是不是感觉扯远了,这和云计算有什么关系?我们继续来剖析一下市场经济,就可以看到和云计算的密切关系了。
我们先来看一下这个场景:如果云厂商 A 提供的服务性价比很高,但是有一天云厂商 B 提供了性价比更高的服务,客户会不会立即把服务迁移到云厂商 B 上去?答案是客户想要迁移,但是比较难迁移。因为每一个云厂商提供的服务标准都不太一样,服务迁移的过程需要适配大量差异化的底层基础设施,这给迁移带来了巨大的成本,甚至抵消了云厂商 B 提供的高性价比,所以平常比较少见到这种迁移。
前面咱们分析了市场经济的资源分配方式是非常有利于社会各方面资源进行最优配置的,可是如果云客户不能在云厂商之间低成本的流动,其实就很难选择性价比高的云厂商。所以从有效配置社会资源这个角度来分析,现在迫切需要一个能够让客户在不同云厂商之间低成本“流动”的体系,而这就是云原生的意义所在。
如果把客户要在云上托管的应用比喻成水的话,那么云服务的价格就是海拔的高度。哪里海拔低,水就很自然的流到哪里去。无限降低迁移的成本,对于客户和云厂商来说都是非常有价值的一件事情。云原生旨在以标准化云服务的提供方式衔接云厂商和客户。这种方式对于客户而言降低了上云和跨云迁移的成本,让客户始终保有和云厂商议价的能力;对云厂商而言,因为客户跨云迁移的成本低,所以只要能提供性价比更高的云服务,就能很容易的聚集大量用户。
云原生是在不断促进整个系统的良性循环:既能让客户始终保有选择的能力,又能让优秀的云厂商快速服务更多的客户。如果客户的业务服务能像水一样低成本在不同云厂商之间流通,那么云厂商提供的服务就能像货币一样在客户之间流通。这是一个多赢的局面。
云原生应用
说完云原生这个理念,我们来看一下云原生应用,以及在云原生的这个大背景下,如何看待传统的应用架构?
云上基础设施
无论是云上的应用,还是云下的应用,其实依赖的核心要素都没有变,只是这些核心要素的提供形式发生了变化。
如上图所示,共有 7 个核心要素。这 7 个要素中日常运维这一块其实不是强依赖的,虽然它对业务的稳定性影响极大,但是这并不是业务跑起来的核心链路,没有这些业务也能跑,而其它的几块都是核心链路。那么我们就来看一下在云原生架构下,这些核心链路的要素都处于什么位置?然后剖析一下云原生应用的基本范式。
云原生技术栈
我们先来看看最右边的中间件这一块,里面有数据库、Redis 以及消息中间件组件。而这一块其实是应用代码里面直接调用的,并且这里包含的所有能力都有标准的协议,比如无论是使用 SQL Server 还是使用 MySQL,我们程序里都可以使用 SQL 规范进行操作。这部分其实早就被标准化了。
如图所示,计算、存储和网络这三个核心要素已经被 Kubernetes 层统一了。很多云服务已经实现了计算、存储和网络资源的无服务器化,比如阿里云的 ECI 和 ASK(Aliyun Serverless Kubernetes)。那么还有两块 CICD 和应用托管没有标准化,这就是应用编排这一层需要标准化的事情。Serverless 其实不单单是无服务器,还包括应用本身的编排,这也是应用编排这一层的价值所在。
云原生应用 Serverless 编排
Serverless Kubernetes 已经提供了 Pod 的无服务器支持,而应用层想要用好这个能力其实还有很多事情需要处理。
-
弹性:
- 缩容到零
- 突发流量
-
灰度发布
- 如何实现灰度发布
- 灰度发布和弹性的关系
-
流量管理
- 灰度发布的时候如何在 v1 和 v2 之间动态调整流量比例
- 流量管理和弹性是怎样一个关系
- 当有突发流量的时候如何和弹性配合,做到突发请求不丢失
我们发现虽然基础资源可以动态申请,但是应用如果要做到实时弹性、按需分配和按量付费的能力还是需要有一层编排系统来完成应用和 Kubernetes 的适配。这个适配不单单要负责弹性,还要有能力同时管理流量和灰度发布。
Knative 应运而生
上文中的内容就是 Knative 要解决的问题,这也是 Knative 出现的背景。接下来咱们来看看 Knative 。
Knative 是什么
我们先看看官方给出的定义:“基于 Kubernetes 平台,用于构建、部署和管理现代 Serverless 工作负载”。Knative 就是基于 Kubernetes 的应用 Serverless 编排系统。实际上 Knative 包含的不单单是 Workload,它还有 Kubernetes 原生的流程编排引擎和完备的事件系统。
前面提到 Kubernetes 实现了计算、存储和网络的标准化,而 Knative 目标基于 Kubernetes 提供了应用 Serverless 工作负载编排的标准化。
Knative 核心模块
Knative 由三个核心模块构成:Tekton、Eventing 和 Serving。
- Tekton 是 Kubernetes 原生的流程编排框架,主要用于构建 CICD 系统;
- Eventing 主要负责事件处理功能,可以接入外部系统的事件,事件接入以后进行一系列的流程处理以及触发 Serving 消费事件;
- Serving 是应用运行工作负载的核心管理模块,主要负责流量调度、弹性以及灰度发布等职责。
Tekton
Tekton 是一套 Kubernetes 原生的流程编排框架,主要用于构建 CICD 系统。比如从源码编译成镜像,以及对镜像里的服务进行测试、把镜像发布成应用等一系列的操作都可以基于 Tekton 完成。
Tekton 里面基本的执行单元是 Task。>
- Task 里面可以包含多个顺序执行的 Step。一个 Task 最终就是一个 Pod,里面的每一个 Step 最终执行的时候就是一个 Container 。每提交一个 TaskRun CRD 到 Kubernetes 就会触发一次 Task 的执行;
- Pipeline 可以编排多个 Task,Pipeline 中的 Task 是可以设置依赖关系。Pipeline 会根据依赖关系生成一个有向无环图,然后生成的根据有向无环图并发或者串行执行一系列的 Task。每提交一个 PipelineRun CRD 就会触发 Pipeline 的一次执行;
- PipelineResource 代表 Pipeline 使用或者生成的资源,比如:github 代码仓库、依赖或者使用的镜像等等;
- Tekton 是 Kubernetes 原生的实现,所以资源鉴权的秘钥等信息都可以通过 Kubernetes 的 Secret 进行管理。
Eventing
Eventing 模块基于 CloudEvent 标准实现了一系列的事件处理机制。Eventing 模块的核心能力分成四大块。
- 外部事件接入
Eventing 有很强的扩展机制,可以接入任何外部事件源的事件,比如 github 里面的 commit、pull request 等事件;Kubernetes 里面的事件;消息系统里面的消息;以及 OSS、表格存储、Redis 等系统的事件。
- CloudEvent 标准
Eventing 接入外部事件以后会转换成 CloudEvent 格式,事件在内部的流转都是通过 CloudEvent 事件标准完成的。
- 事件在内部的处理
Eventing 模块引入的 Broker 、Trigger 模型,不仅将事件复杂的处理实现给用户屏蔽起来,更提供了丰富的事件订阅、过滤机制。
- 事件处理事务管理
Eventing 基于可靠的消息系统,可以对事件进行事务管理。如果事件消费失败可以进行重试或者重新分发等操作。
Serving
Serving 核心的 CRD 就是 Service,Knative Controller 通过 Service 的配置自动操作 Kubernetes 的 Ingress、K8s Service 和 Deployment 从而实现简化应用管理的目标。
Knative Service 对应一个叫做 Configuration 的资源,每次 Service 变化如果需要创建新的 Workload 就更新 Configuration,然后每次 Configuration 更新都会创建一个唯一的 Revision,Revision 可以认为是 Configuration 的版本管理机制。理论上 Revision 创建完以后是不会修改的,不同的 Revision 一般用于灰度发布。
Route 是 Knative 管理流量的核心逻辑,Knative 是建立在 Istio 之后的,Knative Route Controller 通过 Route 的配置自动生成 Istio 的 VirtualService 资源,从而实现了流量的管理。
Knative Serving 对应用 Workload 的 Serverless 编排是从流量开始的。
流量首先达到 Knative 的 Gateway,Gateway 根据 Route 的配置自动把流量根据百分比拆分到不同的 Revision 上,然后每一个 Revision 都有一个自己独立的弹性策略。当过来的流量请求变多的时候当前 Revision 就开始自动扩容。每一个 Revision 的扩容策略都是独立的,相互不影响。
基于流量百分比对不同的 Revision 进行灰度,每一个 Revision 都有一个自己独立的弹性策略。Knative Serving 通过对流量的控制实现了流量管理、弹性和灰度三者的完美结合。
Knative 的云原生特性
Kubernetes 是业界公认的云原生操作系统,作为云原生的 Serverless 编排引擎 Knative 当然是兼容 Kubernetes API 的。
Knative 本身就是开源的,你可以在任何 Kubernetes 集群上面部署一套 Knative 。同样,你在任何 Knative 集群里面的服务都可以无缝迁移到另外一个 Knative 集群。如果你的服务是搭建在 Knative 之上,那么你的服务就可以像水一样在各个云厂商流通,任何一个云厂商的 Kubernetes 搭建好 Knative 就能轻松地把你的服务部署起来。咱们透过下面这个支持列表可以看到 Knative 已经被大量的厂商或平台支持:
- Google 的 CloudRun 是基于 Knative 的
- IBM 公有云已经支持 Knative
- 阿里云已经支持 Knative
- Pivotal 的 Riff 是建立在 Knative 之上的 FaaS 系统
- OpenShift 的 Knative 支持
- Rancher RIO 是基于 Knative 的
- kubeflow 社区基于 Knative 的 KFServing,正在用 Knative 做 AI 相关的框架
云原生的力量就在于此,开放的标准得到了广泛的支持。作为使用云的客户,基于这种开放的标准其实就是始终保有和服务商议价的权利,哪里的服务好就到哪里去,否则就有可能会被一家锁定。对于云厂商而言,通过开放的标准可以接入更多的客户,而这个标准之下的具体实现,每家都会根据自身特点进行支持,这也是云厂商的核心竞争力。
Knative 的典型应用场景
介绍了这么多,接下来咱们就捋一捋 Knative 都适合在哪些场景中使用。
应用 Serverless 编排场景
Knative Serving 从流量入手对应用进行 Serverless 编排。
首先 Knative 基于 Istio Gateway 来接管服务的流量,可以做到按百分比对流量进行切分。切分的流量可以直接用于灰度发布,比如把按百分比切分的流量直接转给一个 Revision,精准地控制每一个 Revision 承接的流量百分比,从而达到精准控制灰度版本对线上服务应用的范围。
Knative 的弹性策略是作用在每一个 Revision 之上的,不同的 Revision 根据“自己的节奏”独自伸缩,实现了从流量到灰度灰度再到弹性这三者的完美结合,所有应用弹性托管诉求都可以通过 Knative 来实现。下面这些场景非常适合使用 Knative 来解决:
- 比如托管微服务应用
- 比如托管 Web 服务
- 比如托管 gRPC 服务
事件驱动
Knative 的 Eventing 提供了完整的事件模型,可以很容易地接入各个外部系统的事件。事件接入以后通过 CloudEvent 标准在内部流转,Broker/Trigger 机制给事件处理提供了非常好的方式。
这套完备的事件系统可以比较容易的实现事件驱动的服务,比如:
- IOT 场景
- 比如和各种云产品的事件对接,从而实现云产品状态更新自动触发一个服务等
基于 Tekton 的 Pipeline
基于 Tekton 构建 CICD 系统等,比如:
- 当 gihub 有代码提交以后自动触发镜像构建、服务发布流程
- 当 docker 镜像仓库有镜像提交的时候,自动对镜像进行测试以及发布成服务等
MicroPaaS
基于 Knative Servering 部署服务,你就无需手动操作 Kubernetes 资源,这样可以大大降低使用 Kubernetes 的门槛。所以如果不是维护 Kubernetes 系统、或者要基于 Kubernetes 做复杂的开发,就可以使用 Knative 来管理自己的服务,非常便捷。
客户案例
阿里云 Knative 现在都有哪些典型的客户案例?
Web 服务托管
Web 托管服务其实就是前面介绍的 MicroPaaS 类型的场景,客户使用 Knative 是为了简化使用 Kubernetes 的复杂度。即便不使用 Knative 的弹性也可以带来应用托管效率的提升。
应用 Serverless 编排
- 微服务托管场景
- web 应用托管和弹性
- 小程序、公众号后台
- 电商服务后台
AI 服务托管
- 基于任务队列的弹性伸缩
- 使用 ECI 做弹性,有效降低长期保有资源的成本
SaaS 服务托管
- SaaS 用户提交代码之后自动给用户构建镜像
- SaaS 用户自己推送了一个镜像之后自动帮助用户发布服务
- CMS 系统 SaaS 提供商可以通过 Helm Chart 非常方便地给用户部署一套全新的服务
SpringCloud 微服务托管
把 Knative Service 的地址注册到注册中心,通过 Knative 的能力实现微服务的流量切分、灰度发布和弹性。这样 Knative 就给普通的微服务应用赋予了 Serverless 能力。
构建 CICD 系统
- 基于 git 代码仓库的自动构建、服务发布的 CICD 系统
- 当 docker 镜像仓库有新镜像的时候自动执行测试或者服务发布
OSS 事件
- 当 OSS 中新增一个文件自动触发机器学习任务的执行,对图片进行分析、识别等
- 当 OSS 中新增一个视频文件,自动触发一个任务处理视频,比如视频内容识别等
TableStore 事件
- Feed 流系统设计
- 社交信息发送通知等
Demo 演示
Demo 执行的命令如下:
本文作者:牛秋霖(冬岛)
本文为云栖社区原创内容,未经允许不得转载。