什么是 Knative?
Knative 是谷歌开源的 Serverless 架构方案,旨在提供一套简单易用的 Serverless 方案,把 Serverless 标准化。目前参与的公司主要是 Google、Pivotal、IBM、Red Hat,2018 年 7 月 24 日对外发布,当前还处于快速发展的阶段。
这是 Google Cloud Platform 宣布 knative 时给出的介绍:
Developed in close partnership with Pivotal, IBM, Red Hat, and SAP, Knative pushes Kubernetes-based computing forward by providing the building blocks you need to build and deploy modern, container-based serverless applications.
可以看出,Knative 是为了解决容器为核心的 Serverless 应用的构建、部署和运行的问题。
Serverless 的概念已经出现蛮久了,为了理解 Serverless, 可以从应用开发者的角度来看,使用 Serverless 框架之后,应用开发者的整个操作流程就变成了:
1 | ~ # 编写 code 和 configuration 文件 |
可以看到用户只需要编写代码(或者函数),以及配置文件(如何 Build、运行以及访问等声明式信息),然后运行 Build 和 Deploy 就能把应用自动部署到集群(可以是公有云,也可以是私有的集群)。
其他事情都是 Serverless 平台(比如: 这里的 Knative)自动处理的,这些事情包括:
-
自动完成代码到容器的构建
-
把应用(或者函数)和特定的事件进行绑定:当事件发生时,自动触发应用(或者函数)
-
网络的路由和流量控制
-
应用的自动伸缩
-
和标准化的 FaaS 不同(只运行特定标准的 Function 代码),Knative 期望能够运行所有的 Workload : Traditional Application、Function、Container。
Knative 建立在 Kubernetes 和 Istio 平台之上,使用 Kubernetes 提供的容器管理能力(Deployment、Replicaset、和 Pods 等),以及 Istio 提供的网络管理功能(Ingress、LB、Dynamic Route 等)。
Knative 核心概念和原理
为了实现 Serverless 应用的管理,Knative 把整个系统分成了三个部分:
-
Build:构建系统,把用户定义的函数和应用 Build 成容器镜像
-
Serving:服务系统,用来配置应用的路由、升级策略、自动扩缩容等功能
-
Eventing:事件系统,用来自动完成事件的绑定和触发
Build 构建系统
Build 的功能是把用户的代码自动化构建成容器镜像,初次听起来很奇怪,有了 Docker 之后有一个 Dockerfile 不就能构建容器了吗?为什么还需要一个新的 Build 系统?
Knative 的特别之处在于两点:一是它的构建完全是在 Kubernetes 中进行的,和整个 Kubernetes 生态结合更紧密;另外,它旨在提供一个通用的标准化的构建组件,可以作为其他更大系统中的一部分。
正如官方文档中的说的那样,是为了定义标准化、可移植、可重用、性能高效的构建方法:
The goal of a Knative build is to provide a standard, portable, reusable, and performance optimized method for defining and running on-cluster container image builds.
Knative 提供了 Build CRD 对象,让用户可以通过 YAML 文件定义构建过程。一个典型的 Build 配置文件如下:
1 | apiVersion: build.knative.dev/v1alpha1 |
其中,serviceAccountName
是构建过程中需要用到的密码和认证信息(比如连接到 Git Repo
的 SSH Keys
、Push 镜像到 Registry 的用户名和密码等);
source 是代码信息,比如这里的 Git
地址和分支;steps 是真正运行过程中的各个步骤。
这个示例中的步骤只是作为 Demo,真正的构建过程一般是 Pull 代码、 Build 镜像和 Push 镜像到 Registry 等逻辑。
因为大部分的构建过程都是一致的,因此 Knative 还提供了 Build Template
的概念,Build Template
封装了预先定义好的构建过程(就是封装了上面的 steps 过程),并提供了非常简单的配置参数来使用。
使用 Build Template
构建容器镜像就更简单了,只需要提供代码的地址和镜像名字即可。比如:下面是使用 Google Kaniko
模板构建 Github 源码的 YAML 文件(需要在代码根目录存在 Dockerfile 文件)。
1 | apiVersion: build.knative.dev/v1alpha1 |
Serving:服务系统
Serving 的核心功能是让应用运行起来提供服务。
虽然听起来很简单,但这里包括了很多的事情:
-
自动化启动和销毁容器
-
根据名字生成网络访问相关的 service、ingress 等对象
-
监控应用的请求,并自动扩缩容
-
支持蓝绿发布、回滚功能,方便应用发布流程
Knative Serving 功能是基于 Kubernetes
和 Istio
开发的,它使用 Kubernetes
来管理容器(Deployment、Pod),Istio
来管理网络路由(VirtualService、DestinationRule)。
因为 Kubernetes 和 Istio 本身的概念非常多,理解和管理起来比较困难,Knative 在此之上提供了更高一层的抽象(这些对应是基于 Kubernetes 的 CRD 实现的)。这些抽象出来的概念对应的关系如下图:
-
Configuration:应用的最新配置,也就是应用目前期望的状态,对应了 Kubernetes 的容器管理(Deployment)。每次应用升级都会更新 Configuration,而 Knative 也会保留历史版本的记录(图中的 Revision),结合流量管理,Knative 可以让多个不同的版本共同提供服务,方便蓝绿发布和滚动升级
-
Route:应用的路由规则,也就是进来的流量如何访问应用,对应了 Istio 的流量管理(VirtualService)
-
Service:注意这里不是 Kubernetes 中提供服务发现的那个 Service,而是 Knative 自定义的 CRD,它的全称目前是 Services.Serving.Knative.Dev 。单独控制 Route 和 Configuration 就能实现 Serving 的所有功能,但 Knative 更推荐使用 Service 来管理,因为它会自动帮你管理 Route 和 Configuration
一个 hello world 的 Serving 配置如下所示:
1 | apiVersion: serving.knative.dev/v1alpha1 |
看起来和 Kubernetes 的 Pod 定义非常类似,但是它会帮你管理 Deployment、Ingress、Service Discovery、Auto Scaling…… 从这个角度来看,可以认为 Knative 提供了更高的抽象,自动帮你封装掉了 Kubernetes 和 Istio 的实现细节。
下面这张图介绍了 Knative Serving 各组件之间的关系:
-
可以看到,每个 Revision 对应了一组 Deployment 管理的 Pod
-
Pod 会自动汇报 Metrics 数据到 Autoscaler,Autoscaler 会根据请求量和资源使用情况修改 Deployment 的 Replicas 数量,从而实现自动扩缩容。Serverless 一个重要的特定是它会 Scale to 0 的,也就是当应用没有流量访问时,它会自动销毁所有的 Pod
-
Activator 比较有趣,它是为了处理 Scale to 0 而出现的。当某个 Revision 后面的 Pod 缩容到 0 时,Route 的流量会指向 Activator,Activator 接收到请求之后会自动拉起 Pod,然后把流量转发过去
-
Route 对象对应了 Istio 的 DestinationRoute 和 VirtualService,决定了访问应用的流量如何路由
Eventing:事件系统
Serving 系统实现的功能是让应用/函数能够运行起来,并且自动伸缩,那什么时候才会调用应用呢?除了我们熟悉的正常应用调用之外,Serverless 最重要的是基于事件的触发机制,也就是说当某件事发生时,就触发某个特定的函数。
事件概念的出现,让函数和具体的调用方能够解耦。函数部署出来不用关心谁会调用它,而事件源触发也不用关心谁会处理它。
Note:目前 Serverless 的产品和平台很多,每个地方支持的事件来源以及对事件的定义都是不同的(比如 AWS Lambda 支持很多自己产品的事件源)。Knative 自然也会定义自己的事件类型,除此之外,Knative 还联合 CNCF 在做事件标准化的工作,目前的产出是 CloudEvents 这个项目。
为了让整个事件系统更有扩展性和通用性,Knative 定义了很多事件相关的概念。我们先来介绍一下:
-
EventSource:事件源,能够产生事件的外部系统
-
Feed:把某种类型的 EventType 和 EventSource 和对应的 Channel 绑定到一起
-
Channel:对消息实现的一层抽象,后端可以使用
Kafka
、RabbitMQ
、Google PubSub
作为具体的实现。Channel Name
类似于消息集群中的Topic
,可以用来解耦事件源和函数。事件发生后Sink
到某个Channel
中,然后Channel
中的数据会被后端的函数消费 -
Subscription:把
Channel
和后端的函数绑定的一起,一个Channel
可以绑定到多个Knative Service
它们之间的关系流程图如下:
Bus 是 Knative 内部的事件存储层,用户可以选择自己感兴趣的实现,目前支持的方式有:Stub(在内存中实现的简单消息系统)、Kafka
、Google PubSub
。如果想要事件能够正常运行,必须在 Knative 集群中安装其中一个 Bus 实现方式。
有了 Bus 之后,我们就可以监听外部的事件了。目前支持的事件源有三个:Github
(比如 Merge 事件,Push 事件等),Kubernetes(Events),Google PubSub(消息系统),后面还会不断接入更多的事件源。
如果要想监听对应的事件源,需要在 Knative 中部署一个 Source Adaptor 的 Pod,它负责从外部的系统中读取事件。
读取后的事件,会根据用户配置的 Feed 对象(里面包括了事件源和 Channel 的对应关系),找到对应的 Channel,然后把消息发送到这个 Channel 中(Channel 的消息最终是存储在后端的 Bus 系统里的)。
然后,Knative 会根据 Subscription 的配置,不断从 Channel 中读取事件,然后把事件作为参数调用对应的函数,从而完成了整个事件的流程。
Knative 项目进展
Knative 是 2018 年 7 月对外开放,虽然内部已经开发一段时间,但是目前还处于非常早前的阶段,各个版本间的变化也比较大。
Knative 也是脱产于 Google 和 CNCF,因此整个社区运行方式和目标与之前的 Kubernetes 以及 Istio 非常相似。社区根据组件分成多个 Working Group,每个 Group 独立负责自己的功能,所有的开源活动(文档、视频、代码)都是开放的。另外,CloudEvents 作为 Knative 依赖的标准,目标也是成为 CRI、CNI、CSI 这种类似的标准。
Knative 社区目前非常活跃,从下面发行版本的速度也可以看得出来,而且入门的文档和教程都已经非常全面。Knative 各版本具体发行时间节点如下:
-
2018-07-19 v0.1.0 版本发布
-
2018-10-31 v0.2.0 版本发布
-
2018-01-09 v0.3.0 版本发布
-
2019-02-20 v0.4.0 版本发布
-
2019-04-03 v0.5.0 版本发布
-
2019-05-14 v0.6.0 版本发布
-
2019-06-25 v0.7.0 版本发布
-
2019-08-07 v0.8.0 版本发布
-
2019-09-17 v0.9.0 版本发布
Knative 应用场景和思考
Knative 基于 Kubernetes 和 Istio 的 Serverless 开源实现,目标是提供更高层次的抽象,让开发者无需关注基础设施(虚拟机或者容器,网络配置,容量规划),而专注于业务代码即可。更多关于 Knative 的使用场景可以参考 AWS Lambda 或者其他相关的文档,这里不再赘述,主要讲讲 Knative 目前的局限性或者问题:
1. 性能问题
性能问题一直是 Serverless 被人诟病的一点,也是目前它不能广泛用于应用服务上的决定性原因。互联网的应用大多数有高并发、高性能的要求,Serverless 整个网络链路很长,容器启停需要额外的时间,还无法满足互联网应用的要求。
针对这一点,很多 Serverless 框架也在不断地做改进,比如不断精简容器的启动时间、容器启动之后会做缓存等,比如 Nuclio 就宣称自己的平台比 AWS Lambda 要快 10 倍以上。
相信随着 Serverless 的不断演进,性能问题会不断优化,至于能不能达到互联网应用的要求,还要时间给我们答案。
2. 是否需要 Istio 这一层?
基于 Kubernetes 的 Serverless 组件非常多,比如 Kubeless。但是基于 Kubernetes 同时又基于 Istio,目前 Knative 还是第一个这么做的。
有些人的疑问在于,Knative 真的有必要基于 Istio 来做吗?对于这个问题,我个人的看法是必要的。
Istio 作为集群基础设施通用网络层的地位已经开始显露,相信在未来的发展中接受度会越来越大,并逐渐巩固自己的地位。虽然现阶段来说,很多人并不非常熟悉 Istio 的情况,但是从长远角度来看,这一点将是 Knative 的一个优势所在。
另外,基于 Istio 构建自己的 Serverless 服务,也符合目前软件行业不要重复造轮子的思路。Istio 在集群的网络管理方面非常优秀(智能路由、负载均衡、蓝绿发布等),基于 Istio 来做可以让 Knative 不用重复工作就能直接使用 Istio 提供的网络通用功能。
3. 系统复杂度
这一点和上面类似,Knative 下面已经有两个非常复杂的平台:Kubernetes
和 Istio
。这两个平台的理解、构建、运维本身就很复杂,如今又加上 Knative
整个平台,需要了解的概念都要几十个,更不要提落地过程中会遇到的各种问题。
对于公有云来说,Kubernetes
和 Istio
这些底层平台可以交给云供应商来维护(比如 Google Function),但是对于内部构建来说,这无疑提高了整个技术门槛,对系统管理人员的要求更高。
如何安装部署整个集群?如何对集群做升级?出现问题怎么调试和追踪?怎么更好地和内部的系统对接?这些系统的最佳实践是什么?怎么做性能优化?所有这些问题都需要集群管理人员思考并落实。
4. 函数的可运维性?
相对于编写微服务来说,单个函数的复杂度已经非常低,但是当非常多的函数需要共同工作的时候,如何管理这些函数就成了一个必须解决的问题。
-
如何快速找到某个函数?
-
如何知道一个函数的功能是什么?接受的参数是什么?
-
怎么保证函数的升级不会破坏原有的功能?升级之后如何回滚?怎么记录函数的历史版本方面追溯?
-
当有多个函数需要同时工作的时候,怎么定义它们之间的关系?
-
函数出现问题的时候如何调试?
-
对于函数的运维,一般的 Serverless 平台(包括 Knative)都提供了
Logging
、Metrics
、Tracing
三个方面的功能。默认情况下,Knative 使用 EFK(Elasticsearch
、Fluent
、Kibana
)来收集、查找和分析日志;使用Prometheus
+Grafana
来收集和索引、展示Metrics
数据;使用Jaeger
来进行调用关系的Tracing
。
针对 Serverless
衍生出来的运维工具和平台还不够多,如何调试线上问题还没有看到非常好的解决方案。
5. Knative 成熟度
-
最后一点是关于 Knative 成熟度的,前面已经提到,Knative 目前刚出现不久。虽然整个框架和设计都已经搭好了,但是很多实现都比较初级。这里提几点来说:
-
为了实现 Autoscaling,Knative 在每个 Pod 中添加一个叫做
Queue Proxy
的代理,它会自动把请求的Metrics
发送给Autoscaler
组件作为参考。这样一来,整个网络链路上又多了一层,对整个性能势必会有影响,未来的打算是直接使用Envoy Sidecar
来替换掉Queue Proxy
-
支持的事件源和消息系统还很有限,外部事件只支持
Github
、Kubernetes
和Google PubSub
。 这个问题可以慢慢扩展,Knative 本身会实现很常用的事件类型,自定义的事件源用户可以自己实现 -
目前还没有函数的
Pipeline
管理(类似AWS Lambda Step Functions
),多个函数如何协作并没有自己处理。虽然没有在官方文档中看到这方面的Roadmap
,但是以后一定会有这方面的功能(不管是 Knative 本身来做,还是社区作为工具补充来实现)
这方面的问题都不是大事情,随着 Knative 版本的迭代,在很快的时间都能够解决。
参考资料
-
Google Cloud Platform 宣布 Knative 发布的博客文章: Google Cloud Platform Blog: Bringing the best of serverless to you
-
the Newstack 上非常好的科普文章: Knative Enables Portable Serverless Platforms on Kubernetes, for Any Cloud - The New Stack
-
Serving 的设计理念:https://docs.google.com/presentation/d/1CbwVC7W2JaSxRyltU8CS1bIsrIXu1RrZqvnlMlDaaJE/edit#slide=id.g32c674a9d1_0_5
-
knative 官方文档:GitHub - knative/docs: Documentation for users of Knative components
-
Google Cloud Next 2018 大会上宣布 knative 的视频 presentation: Kubernetes, Serverless, and You (Cloud Next ’18) - YouTube
-
Google Cloud Knative 产品页面,目前只有最简单的介绍和文档链接
-
什么是 istio
来源:Cizixs Blog
题图:来自谷歌图片搜索
版权:本文版权归原作者所有
投稿:欢迎投稿,邮箱: editor@hi-linux.com