Golang 无疑是云原生领域开发的首选开发语言,继 Docker、Kubernetes 等大作之后Knative 又是一个基于 Go 语言的云原生范式。Knative 提供了一整套云原生应用的 Serverless 模型,使得我们可以方便的基于 Go 语言开发 Serverless 云原生应用。本文作者冬岛:阿里云技术专家
本文字数:5166字
精读时间:10分钟
也可在5分钟内完成速读
00
前言
大家好!我是阿里云容器服务团队的冬岛,2016 年阿里巴巴开始全面容器化,我负责双十一链路应用的容器化 CAAS 平台。承担双十一应用的扩容、缩容、升级以及灰度发布等所有和容器相关的平台支撑。2017 年开始基于 Kubernetes 在公有云上做相关的产品,直到今天在做 Knative。本次分享分为四部分:
第一,云计算最根本的驱动力是什么;
第二,云原生应用是什么;
第三,Knative 给应用的云原生化开发带来了什么价值;
第四,Demo展示
01
云计算第一性原理
第一性原理顾名思义就是最根本的机制是什么,在讨论云原生之前先来思考一下为什么企业要上云、为什么技术人员要学习面向云的编程思维以及咱们应该怎么看待云这件事儿。
咱们先从一顿火锅谈起,吃火锅要有肉、有菜、有鱼还有有金针菇。一顿火锅虽然愿望不大,但会涉及到非常多的东西。各种蔬菜、各种牛羊肉,甚至还有进口的。细想一下所有这些我们都经常食用,但有哪些是咱们自己亲手养殖或者种植的?其实没有,咱们每天都是坐在办公室里,下班的路上到菜店或者超市就把这些东西买全了,不知道其实也不关心这些东西的具体生产过程。
现在因为有专业的人在做这些事情,所以我们大多数人都无需劳心蔬菜是怎么种植的。而我们工程师所做的和计算机打交道的事情也能通过其他的渠道反过来帮助那些种菜的人。这就是社会分工的威力,是不同地域、不同角色之间通过市场相互协作的成果。
好,说完火锅咱们再回过头来看看一个应用都是由哪些部分构成的。应用要提供服务首先要有计算、存储和网络资源才能把进程跑起来。当然这些也仅仅是把进程跑起来,如果要承接具体的业务还需要依赖数据库等服务。如果要做分布式架构还需要做微服务拆分,这时候就需要缓存、注册中心、消息各种中间件的服务。现在说的这些都是程序已经有了,如何把程序跑起来承接业务的部分。还有一部分就是如何把代码变成可启动的程序,这就是 CICD 部分了。从代码到应用启动再到应用依赖的周边系统支撑都说完了,还有一部分就是日常运维相关的:
• 比如日志收集、分析
• 比如监控和告警
虽然我们本来只是想要写一个应用,支撑业务功能。但是应用周边的这些支撑系统比这个应用自身的消耗还要高。这其实不是咱们期望的结果。咱们期望的是更多的精力关注到业务逻辑本身,而不是周边的这些系统上来。
让业务团队更多的聚焦在业务本身,这才是咱们希望看到的。实际上有一定规模的公司,内部的组织架构基本也都是由一个基础平台团队和多个业务团队构成的,基础平台团队负责提供这些应用需要的公共能力支撑,业务团队更聚焦在业务上,使用基础平台团队的能力即可。
这其实也是社会分工在 IT 组织中的体现,专业的人做专业的事儿,分工提升效率。
02
云原生应用
说完云原生这个理念,咱们来看看云原生应用。看看在云原生的这个大背景下,如何看待传统的应用架构。
![](https://s4.51cto.com/images/blog/202104/19/2874cc6d859052cfce064794bd39e08e.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
无论是云上的应用,还是云下的应用,其实应用依赖的这些核心要素都没有变。只是这些核心要素的提供形式发生了变化。咱们先来看看这 7 个核心要素,这 7 个要素中日常运维这一块其实不是强依赖的,日常运维这一块对业务的稳定性影响极大,但是这并不是业务跑起来的核心链路,没有这些业务也能跑,而其他的几块都是核心链路。那么咱们就来看一下在云原生架构下,这些核心链路的要素都处于什么位置。然后剖析一下云原生应用的基本范式。
![](https://s4.51cto.com/images/blog/202104/19/97890955432da0028ca18bd3e82f5626.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
先来看看最右边的中间件这一块,这里面有数据库、Redis 以及消息中间件组件。而这一块其实是应用代码里面直接调用的,并且这里包含的所有这些能力都有标准的协议,比如无论是使用 SQL Server 还是使用 MySQL,咱们程序里都可以使用 SQL 规范进行操作。这部分被标准化了。
计算、存储和网络这三个核心要素已经被 Kubernetes 这一层统一了。前面志敏已经分享了 aliyun Serverless Kubernetes(简称 ASK),在 ASK 中已经实现了计算、存储和网络资源的无服务器化。那还有两块:CICD 和应用托管。
Serverless 其实不单单是无服务器,还包括应用本身的编排。这就是应用编排这一层的价值所在。
应用 Serverless 编排
Kubernetes 已经提供了 Pod 的资源调度,而应用层想要用好这个能力其实是有很多事情需要处理的。
• 弹性
• 缩容到零
• 突发流量
• 灰度发布
• 如何实现灰度发布
• 灰度发布和弹性的关系
• 流量管理
• 灰度发布的时候如何在 v1 和 v2 之间动态调整流量比例
• 流量管理和弹性是怎样一个关系
• 当有突发流量的时候如何和弹性配合,做到突发请求不丢失
所以我们发现虽然基础资源可以动态申请,但是应用如果要做到实时弹性、按需分配和按量付费的能力还是需要有一层编排系统来完成应用和 Kubernetes 的适配。这个适配不单单要负责弹性,还要有能力同时管理流量和灰度发布。
03
Knative 应运而生
官方给出的定义:"基于 Kubernetes 平台,用于构建、部署和管理现代 Serverless 工作负载"。Knative 就是基于 Kubernetes 的应用 Serverless 编排系统。实际上 Knative 包含的不单单是 Workload,它还有 Kubernetes 原生的流程编排引擎和完备的事件系统。
Knative 由三个核心模块构成:Tekton、Eventing 和 Serving
• Tekton 是 Kubernetes 原生的流程编排框架,主要用户构建 CICD 系统
• Eventing 主要负责事件处理功能,可以接入外部系统的事件、事件接入以后进行一系列的流程处理以及触发 Serving 消费事件
• Serving 是应用运行工作负载的核心管理模块,主要负责流量调度、弹性以及灰度发布等职责
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 模块基于 CloudEvent 标准实现了一系列的事件处理机制。Eventing 模块的核心能力分成四大块
• 外部事件接入
Eventing 有很强的扩展机制,可以接入任何外部事件源的事件,
• 比如 github 里面的 commit、pull request 等事件
• 比如 Kubernetes 里面的事件
• 比如 消息系统里面的消息
• 比如 OSS、表格存储以及 Redis 等系统的事件
• CloudEvent 标准
Eventing 接入外部事件以后会转换成 CloudEvent 格式,事件在内部的流转都是通过 CloudEvent 事件标准完成的
• 事件在内部的处理
Eventing 模块引入的 Broker 、Trigger 模型,不仅将事件复杂的处理实现给用户屏蔽起来,更提供丰富的事件订阅、过滤机制
• 事件处理事务管理
Eventing 基于可靠的消息系统,可以对事件进行事务管理。如果事件消费失败可以进行重试或者重新分发等操作
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 通过对流量的控制实现了流量管理、弹性和灰度三者的完美结合。
04
Demo 演示
05
问答环节
提问:你好,首先自我介绍一下,我是目前在网易云这边做CICD 平台的,所以我可能对这块比较感兴趣。其实刚才看的时候也有几个疑问:
Knative 是如何实现的按百分比的流量切分,并且把切分的流量转到不同的 Revision 上去的?以及这个流量切分和 Kubernetes 的 Ingress 有什么异同吗?
Knative 和 OAM 大概是怎样的一个关系?
冬岛:
Knative 0.10 及之前的版本 Gateway 使用的是 Istio Gateway 实现的,计划从 0.11 版本开始支持基于 Envoy 的原生实现。不过无论是 Istio Gateway 还是基于 Envoy 原生的实现其实都是使用的 Envoy 的能力。Envoy 做 HTTP 流量的百分比切分。Knative 中每一个 Revision 都有一个唯一的 Kubernetes Service, Envoy 负责转发把匹配条件的请求转发到 Revision 的 Kubernetes Service 上,从而实现了 Ingress 流量的百分比切分。和 Kubernetes 原生的 Ingress 相比,原生的 Ingress 只能根据 Domain、path 或者 Header 这种维度进行切分,而 Knative 基于 Envoy 可以进行更细力度的控制,可以精确到 1% 的流量比例。
OAM 是一套开放的应用模型,OAM 可以有 Kubernetes 的实现也可以有 Knative 的实现。OAM 的价值在于跨不同的底层编排系统统一应用模型。
提问:
Knative 是符合解决冷启动速度的问题的
刚才你的演讲中也提到了团队角色分工的问题,那么如果企业上云运维团队或者 SRE 团队应该在如何在上云的模式下定位自己的角色?
冬岛:
Serverless 其实是要分成两层的。第一层是 IaaS 资源的按需使用和按量分配。第二层是对应用的 Serverless 编排。云原生技术栈中对 IaaS 资源的管理主要是 Kubernetes 这一层的能力,比如前面志敏分享的 ASK 其实已经解决了 IaaS 按量分配的问题,Knative 这一层更多的是聚焦在应用的 Serverless 编排上面。应用的 Serverless 编排主要体现在:流量的接入和流量分配、不同 Revision 的管理以及弹性。这三者完美的结合在一起形成一个闭环才能给应用提供 Serverless 编排。应用 Serverless 编排在扩容或者缩容的时候自动申请或者释放 IaaS 资源
如果企业上云并不代表企业就不需要 SRE 团队。相反在企业上云的过程中 SRE 团队的价值也会被放大。企业在上云之前其实 SRE 团队本身是企业的成本部门,SRE 本身不带来业务价值,但是需要公司支出成本。但是在企业上云之后 SRE 其实是帮助企业节省成本的部门。SRE 需要判断哪个云厂商的什么产品合适本公司的业务、需要判断使用产品的什么规格、是包年包月还是按量付费的方式使用。以及上云的过程中使用什么方案实现多云、混合云的能力,等等这些都是 SRE 发挥巨大价值的地方。
提问:关于 OAM 这一块,在你这边有一些实现吗?
冬岛:OAM 是有清晰的分层关系的,Knative 可以实现一个 OAM 的 Controller 从而实现通过 Knative 部署 OAM 应用的能力。
提问:你介绍的Knative 这套 Serverless 编排引擎 和志敏介绍的 Serverless Kubernetes 有什么关联或者区别?
冬岛:如前面所述,Serverless 至少要分成应用的编排和资源编排两层,IaaS 的编排其实就是 ASK 着重要解决的问题。而 Knative 更多的是建立在 ASK 之上的应用编排。应用编排更多的是关注流量的管理、灰度的管理和弹性的管理。Knative 和 ASK 在一起其实是比较完美的组合。
提问:我刚才看你演示的时候讲流量管理里面是通过 HTTP Header 的方式去改变流量控制,如果我是一个 RPC 服务的话,你这里如何控制我的流量?
冬岛:因为Knative 底层的流量管理机制是基于Istio ,Istio 下一层就是 Envoy ,比如说你用 Double 这种非 HTTP 请求, Knative 是不支持的。
提问:Tekton 的这套 Pipeline 引擎能不能跨 Kubernetes 集群进行 CICD 流程的控制或者服务的部署?假设我们有测试、预发和线上三个环境,怎样控制 Pipeline 在这三套环境中的流转呢?
冬岛:Tekton 的 Pipeline 里面可以包含多个 Task,每一个T ask 有多个 step,step 里面就是一个具体的 container 去执行一系列的命令。Step 的执行者和具体的 Kubernetes 集群没有直接绑定的关系。Step 中可以通过 Secret 挂载其他集群的 kubeconfig 文件,然后在 Step 中通过 kubectl 命令就可以跨集群进行操作了。所以如果实在构建测试到生产环境的 CICD Pipeline 流程的话可以在测试环境的最后一步通过生产环境的 kubeconfig 把服务发布到生产环境。
提问:阿里云的产品好多,看起来眼花缭乱,并且有很多产品看起来还是相互重叠的。关于这个问题你怎么看待?
冬岛:我觉得这个体感其实非常直接,很多企业上云的用户都会有这样的感觉。关于这个问题咱们就以 Knative 的 Serverless 编排和 ASK 为例进行说明。乍一看都是 Serverless 系统,这不就是重复的功能吗?当我们深入了解 Serverless 技术之后会发现 Knative 和 ASK 不但不冲突而且还是相互补充相互合作的关系。ASK 解决了 IaaS 按需分配的问题,Knative 解决了应用 Serverless 编排的问题。所以很多云产品看起来是有很多重叠的功能,但是如果深入到那个领域就会发现在垂直划分上大家都是有不同的场景的。
提问:我看刚才的演示中可以根据 HTTP 实时的请求进行扩缩容,那么我有这样两个疑问
是否可以根据机器自身的状况进行扩缩容?比如 CPU?
非 HTTP 协议的服务是否可以基于 Knative 进行管理?
冬岛:Knative 除了默认的 KPA 弹性策略还支持 Kubernetes 的 HPA 弹性策略,所以可以把 CPU 作为弹性伸缩的条件。另外 Knative 0.10 及之前的版本是基于 Istio Gateway 实现的流量接入,而 Istio Gateway 只能识别 HTTP 的应用层协议,所以默认的 Gateway 是不支持非 HTTP 协议的。但是 Knative 的设计是非常灵活的,Knative Revision 的 Ingress 和 Autoscaler 都是可以通过 plugin 的方式扩展的,这和 Kubernetes 的设计是一脉相承的,可以通过 Annotation 的方式声明使用哪个 Controller。所以 Knative 本身是可以通过自定义 Ingress Controller 实现非 HTTP 协议的流量管理的。
有疑问加站长微信联系(非本文作者)