说一说 Serverless 到底是什么?

2020-11-20 09:52:12 浏览数 (1)

关于 Kubernetes Service 理解的系列文章,本篇是最后一篇:

  • Part 1: Kubernetes Services
  • Part 2: Kubernetes Ingress
  • Part 3: Kubernetes Istio
  • Part 4: (本文)

Serverless 是一种云原生开发模型,可使开发人员专注构建和运行应用,而无需管理服务器。简单来说 Serverless 就是让你不与或少与运行应用程序所需的服务器和基础设施进行交互,当今天我们提到 "serverless" 这个词的时候通常它可以指 CaaSFaaS 这两种服务。

CaaS - 容器即服务

当我们创建容器后,把它扔到 CaaS 上,它就会自动运行、服务和扩展,比如 Azure Container Instances、Google Cloud Run 或 AWS Fargate 这些服务。

FaaS - 函数即服务

当我们写好代码,扔给 FaaS,它就会自动运行、服务和扩展。比如 Azure Functions、Google Functions 或者 AWS Lambda 这些服务。

FaaS 可以用不同的方式来运行你的代码,一种方式可能是 FaaS 为每一次代码变化构建一个容器,就类似于使用 CaaS 这种服务。

FaaS 构建成容器发送给 CaaS

另一种方式是 FaaS 在启动过程中动态地将函数的源码拉到一个预定义的环境(容器)中,不同的语言会有不同的环境,当使用像 Go 这样的编译语言时,那么编译必须在启动时进行。

事件或伸缩

FaaS 大多数时候与函数实例的触发器事件系统一起使用,事件可以来源于 API 网关、Github、Kafka、RabbitMQ、CronJobs 等。

FaaS 封装了与事件源的通信

对于每个事件,将创建一个新的函数来处理它,如果有多个事件同时发生,将创建多个实例来处理这些事件。这样我们就有了自动伸缩的功能。

FaaS 与各种事件源进行通信,所以函数本身不需要去实现,它们只需要与 FaaS 使用的一种事件格式进行通信,比如 CloudEvents 或者通过 HTTP 传输。

Kubernetes 应用

下面让我们来看看开发一个运行在 Kubernetes 上的传统非 serverless 应用需要的步骤。

我们需要构建一个容器,创建各种 Kubernetes 资源清单文件,然后决定我们需要多少个工作节点来运行我们的应用程序。

我们需要多少个工作节点的可以通过配置一个 Cluster/Node autoscaler来动态地处理,但是我们仍然必须配置它,并且需要设置一个最小 最大的节点数量。

Kubernetes Serverless 应用

现在我们来探讨一下为 Kubernetes 开发应用时的 serverless 方法。

CaaS - 容器即服务

可以看到我们大大减少了需要创建的 Kubernetes 资源清单的数量,CaaS 将为我们创建所有必要的子资源,比如 autoscaler、Ingress 或 Istio 路由。

我们要做的就是提供一个(Docker)容器,并创建一个单一的 k8s 资源,即通过 CRD 引入的 CaaS-容器资源。CaaS 决定什么时候启动我们应用的实例,以及启动多少个,可能是基于事件或我们自定义的方式。

我们必须确保我们构建的容器能够接收和处理来自 CaaS 的事件,例如可以通过 HTTP 或 CloudEvents,这可能需要容器内部的某些库支持。

Knative 就是一个典型的 CaaS 服务,Knative 提供了灵活的构建模块,其他解决方案也可以使用和依赖它。

FaaS - 函数即服务

在 FaaS 服务中的 function.yml 文件中将包含一个来自 FaaS 系统的 K8s 资源,通过 CRD 引入,在该资源中,我们可以配置函数名称、源代码位置、语言运行时和触发事件等内容。

有了 FaaS,我们也就拥有了 CaaS 解决方案的一切能力了,现在我们进一步减少了工作量,因为我们有工具在 Kubernetes 集群中运行,可以直接执行/构建我们的应用源代码。

为我们构建的容器已经包含了必要的库,比如 HTTP 或 CloudEvents,来接收来自 FaaS 的事件,所以我们不必担心这个问题。

源码可能存储在 Git 仓库中,也可能是通过 web 界面上传的,或者是在其他地方提供的。FaaS 将访问代码,监听变化,构建容器,然后将其传递给 CaaS,用于服务终端事件。

TriggerMesh 的web 界面,用于上传代码并作为一个函数进行部署

冷热启动

冷启动将意味着没有 Pod 已经在运行处理事件,所以需要一些时间来创建它。通常情况下,这些 Pod 在最后一次使用后会保持一段时间,可以重复使用。在 "已经运行" 期间的调用被称为热启动,热启动的速度较快,但也会消耗资源。

Fission

Fission 是一个典型的运行在 Kubernetes 环境下面的 Faas 服务,实际上并没有为每个函数的代码变化构建一个不可变的容器,而是使用了可变的环境容器("Generic pods")的概念,动态地将代码拉进来,然后将这些容器转换成 "Specific Function pods",这也是 AWS Lambda 使用用 AWS Firecracker 的工作方式。

可观测性

从容器化的微服务转向函数,可能会导致不得不管理比以前更多、更小的服务。这是因为创建小型函数是很容易的,这些函数只是监听和处理一个单一事件。

为了管理更多的服务或功能,所以非常有必要保持可观察性(指标、日志、跟踪),这就是为什么大多数 Kubernetes 的 FaaS 和 CaaS 已经与Prometheus、Jaeger 和 Istio 或 Linkerd 等服务网格进行了集成。

Kubernetes Serverless 节点

上面我们谈到了 K8s Serverless 应用,我们看到了使用 CaaS 或 FaaS 时的工作流程,这些服务减少了我们很多重复性的工作。

但是开发人员或运维人员仍然在与服务器交互:作为集群中的工作节点的虚拟机,他们仍然需要指定有多少节点以及它们的资源(CPU/内存)。

下面我们来看下使用 Virtual Kubelet 让实际的底层 Kubernetes 节点成为 Serverless 节点。

FaaS 在 Kubernetes 之上,以 Virtual Kubelet 为节点

Virtual Kubelet 给 Kubernetes 模拟了一个 worker 节点,然后可以调度 Pods 到上面来工作,就像其他普通节点一样。虽然 Pods 的容器不是运行在虚拟机上,而是在云提供商的无服务器容器产品中,如 AWS Fargate、Google Cloud Run 或 Azure Container Instances。

K8s Serverless 应用和 K8s Serverless 节点可能是一个强大的组合,但是,如果我们把所有的东西都 serverless 化了,那为什么还要使用 K8s呢?

为什么还要用 Kubernetes

Kubernetes 提供了强大而灵活的构建功能,而不是为了方便交互和终端用户而生的的。这使得 K8s 变得很复杂,直接使用时需要大量的重复性工作。

Kubernetes 成为一个独立于云提供商的标准,在上面使用 serverless 框架,在使用 serverless 时保持这种独立性是有意义的,如果有必要的话,我们可以随时对我们的应用进行更加详细的定义,因为它的下面仍然只是运行 K8s 而已。

通过在 K8s 上使用 serverless,我们可以减少很多重复性工作,这样我们就可以花更多的时间来构建实际的应用了。

总结

最后我们来回顾下传统的 K8s 应用和 serverless 应用的区别。

传统 K8s 应用

Serverless 应用

我认为现代 serverless 事件驱动的架构已经证明了自己的能力,并且在未来几年会越来越普遍。Kubernetes上的 Serverless 只是持续自动化掉手工作业的结果。

“原文链接:https://itnext.io/kubernetes-serverless-simply-visually-explained-ccf7be05a689 ”

0 人点赞