本文做者来自蚂蚁金服系统部之芥html
knative 是谷歌开源的 serverless 架构方案,旨在提供一套简单易用的 serverless 方案,把 serverless 标准化。目前参与的公司主要是 Google、Pivotal、IBM、Red Hat,2018年7月24日才刚刚对外发布,当前还处于快速发展的阶段。git
这是 Google Cloud Platform 宣布 knative 时给出的介绍:github
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 应用的构建、部署和运行的问题。docker
serverless 的概念已经出现蛮久了,为了理解 serverless 能够从应用开发者的角度来看,使用 serverless 框架以后,应用开发者的整个操做流程就变成了:ubuntu
~ # 编写 code 和 configuration 文件
~ # faascli build
~ # faascli deploy
~ # curl http://myapp.com/hello
hello, world from Awesome FaaS App!复制代码
能够看到用户只须要编写代码(或者函数),以及配置文件(如何 build、运行以及访问等声明式信息),而后运行 build 和 deploy 就能把应用自动部署到集群(能够是公有云,也能够是私有的集群)。后端
其余事情都是 serverless 平台(好比这里的 knative)自动处理的,这些事情包括:api
和标准化的 FaaS 不一样,knative 指望可以运行全部的 workload : traditional application、function、container。缓存
knative 是创建在 kubernetes 和 istio 平台之上的,使用 kubernetes 提供的容器管理能力(deployment、replicaset、和 pods等),以及 istio 提供的网络管理功能(ingress、LB、dynamic route等)。性能优化
为了实现 serverless 应用的管理,knative 把整个系统分红了三个部分:bash
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
配置文件以下:
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: example-build
spec:
serviceAccountName: build-auth-example
source:
git:
url: https://github.com/example/build-example.git
revision: master
steps:
- name: ubuntu-example
image: ubuntu
args: ["ubuntu-build-example", "SECRETS-example.md"]
steps:
- image: gcr.io/example-builders/build-example
args: ['echo', 'hello-example', 'build']
复制代码
其中,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 文件):
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: kaniko-build
spec:
serviceAccountName: build-bot
source:
git:
url: https://github.com/my-user/my-repo
revision: master
template:
name: kaniko
arguments:
- name: IMAGE
value: us.gcr.io/my-project/my-app复制代码
serving 的核心功能是让应用运行起来提供服务。虽然听起来很简单,但这里包括了不少的事情:
knative serving 功能是基于 kubernetes 和 istio 开发的,它使用 kubernetes 来管理容器(deployment、pod),istio 来管理网络路由(VirtualService、DestinationRule)。
由于 kubernetes 和 istio 自己的概念很是多,理解和管理起来比较困难,knative 在此之上提供了更高一层的抽象(这些对应是基于 kubernetes 的 CRD 实现的)。这些抽象出来的概念对应的关系以下图:
services.serving.knative.dev
。单独控制 route 和 configuration 就能实现 serving 的全部功能,但knative 更推荐使用 Service 来管理,由于它会自动帮你管理 route 和 configuration一个 hello world 的 serving 配置以下所示:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: docker.io/{username}/helloworld-go
env:
- name: TARGET
value: "Go Sample v1"
复制代码
看起来和 kubernetes 的 pod 定义很是相似,可是它会帮你管理 deployment、ingress、service discovery、auto scaling……从这个角度来看,能够认为 knative 提供了更高的抽象,自动帮你封装掉了 kubernetes 和 istio 的实现细节。
下面这张图介绍了 knative serving 各组件之间的关系:
serving 系统实现的功能是让应用/函数可以运行起来,而且自动伸缩,那何时才会调用应用呢?除了咱们熟悉的正常应用调用以外,serverless 最重要的是基于事件的触发机制,也就是说当某件事发生时,就触发某个特定的函数。
事件概念的出现,让函数和具体的调用方可以解耦。函数部署出来不用关心谁会调用它,而事件源触发也不用关心谁会处理它。
Note:目前 serverless 的产品和平台不少,每一个地方支持的事件来源以及对事件的定义都是不一样的(好比 AWS Lambda 支持不少本身产品的事件源)。Knative 天然也会定义本身的事件类型,除此以外,knative 还联合 CNCF 在作事件标准化的工做,目前的产出是 CloudEvents 这个项目。
为了让整个事件系统更有扩展性和通用性,knative 定义了不少事件相关的概念。咱们先来介绍一下:
它们之间的关系流程图以下:
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 是 2018 年 7月才刚刚对外开放,虽然内部已经开发一段时间,可是目前还处于很是早前的阶段(从支持的事件源和 bus就能看出来)。目前代码还不稳定,不少实现都是 hard-coded。
knative 也是脱产于 google 和 CNCF,所以整个社区运行方式和目标与以前的 kubernetes 以及 istio 很是类似。社区根据组件分红多个 Working Group,每一个 Group 独立负责本身的功能,全部的开源活动(文档、视频、代码)都是开放的。另外,CloudEvents 做为 knative 依赖的标准,目标也是成为 CRI、CNI、CSI 这种相似的标准。
knative 社区目前很是活跃,已 github.com/knative/serving
项目为例,一个月已经有 600+ star,目前有 60+ contributor,900+ commits,并且入门的文档和教程都已经很是全面。
knative 基于 kubernetes 和 istio 的 serverless 开源实现,目标是为了提供更高层次的抽象,让开发者无需关注基础设施(虚拟机或者容器,网络配置,容量规划),而专一于业务代码便可。
目前 serverless 以及 knative 的几个问题:
性能问题一直是 serverless 被人诟病的一点,也是目前它不能普遍用于应用服务上的决定性缘由。互联网的应用大多数有高并发、高性能的要求,serverless 整个网络链路很长,容器启停须要额外的时间,还没法知足互联网应用的要求。
针对这一点,不少 serverless 框架也在不断地作改进,好比不断精简容器的启动时间、容器启动以后会作缓存等,好比 nuclio 就宣称本身的平台比 AWS Lambda 要快 10 倍以上。
相信随着 serverless 的不断演进,性能问题会不断优化,至于能不能达到互联网应用的要求,还要时间给咱们答案。
基于 kubernetes 的 serverless 组件很是多,好比 kubeless。可是基于同时又基于 istio,目前 knative 仍是第一个这么作的。
有些人的疑问在于,knative 真的有必要基于 istio 来作吗?对于这个问题,我我的的见解是必要的。
虽然 istio 才刚刚release 1.0 版本,可是它做为集群基础设施通用网络层的地位已经开始显露,相信在将来的发展中接受度会愈来愈大,并逐渐巩固本身的地位。虽然现阶段来讲,不少人并不很是熟悉 istio 的状况,可是从长远角度来看,这一点将是 knative 的一个优点所在。
另外,基于 istio 构建本身的 serverless 服务,也符合目前软件行业不要重复造轮子的工做。istio 在集群的网络管理方面很是优秀(智能路由、负载均衡、蓝绿发布等),基于 istio 来作可让 knative 不用重复工做就能直接使用 istio 提供的网络通用功能。
这一点和上面相似,knative 下面已经有两个很是复杂的平台:kubernetes 和 istio。这两个平台的理解、构建、运维自己就很复杂,现在又加上 knative 整个平台,须要了解的概念都要几十个,更不要提落地过程当中会遇到的各类问题。
对于公有云来讲,kubernetes 和 istio 这些底层平台能够交给云供应商来维护(好比 google Function),可是对于内部构建来讲,这无疑提升了整个技术门槛,对系统管理人来的要求更高。
如何安装部署整个集群?如何对集群作升级?出现问题怎么调试和追踪?怎么更好地和内部的系统对接?这些系统的最佳实践是什么?怎么作性能优化?全部这些问题都须要集群管理人员思考并落实。
相对于编写微服务来讲,单个函数的复杂度已经很是低,可是当很是多的函数须要共同工做的时候,如何管理这些函数就成了一个必须解决的问题。
对于函数的运维,通常的 serverless 平台(包括 knative)都提供了 logging、metrics、tracing 三个方面的功能。默认状况下,knative 使用 EFK(Elasticsearch、Fluent、Kibana)来收集、查找和分析日志;使用 prometheus + grafana 来收集和索引、展现 metrics 数据;使用 jaeger 来进行调用关系的 tracing。
针对 serverless 衍生出来的运维工具和平台还不够多,如何调试线上问题尚未看到很是好的解决方案。
最后一点是关于 knative 成熟度的,前面已经提到,knative 目前刚出现不久。虽然整个框架和设计都已经搭好了,可是不少实现都比较初级。这里提几点来讲:
这方面的问题都不是大事情,随着 knative 版本的迭代,在很快的时间都可以解决。
欢迎关注【金融级分布式架构】微信公众号,了解更多