一、K8s给Serverless带来了什么
Kubernetes是基于容器的调度引擎。早期,基于容器的技术有LXC、Cgroup等。2013 年,Docker 项目的开源标志着容器技术的成熟,容器镜像标准诞生。
容器镜像标准诞生之前,业界对系统并没有真正地进行有关注点的拆分,我们认为系统是面向于基础设施的。而容器镜像标准的诞生意味着系统将会依据两个关注点被拆分:一是面向应用,二是面向基础设施。面向应用即容器镜像,面向基础设施即内核。有了容器镜像,才有基于容器的部署生态的不断完善。
2014年时,Kubernetes项目诞生,同年Lambda发布,标志着Serverless商业化进程再进一步。2016 年,CNCF 云原生基金会的成立标志着 Kubernetes生态逐渐成熟和壮大。2018 年,Knative和阿里巴巴Serverless应用引擎发布,标志着基于Kubernetes的serverless实现产品化。
在 CNCF 框架下,诞生了很多Kuebrnetes生态项目,发展欣欣向荣。
Kubernetes的特殊在于其理念,比如它遵照着serverless的理念,比如不可变基础设施、面向终态、声明式 API 等,造就了今天的Kubernetes生态。
早期的 Linux 操作系统面向一台服务器,应用运行时可以和底下的设备进行解耦。应用只需通过内核的 API 即可在不同的硬件上进行适配、运行。其设计哲学为“一切皆文件”,也造就了Linux生态的繁荣。而Kubernetes的声明式API也可以看作资源文件的CRUD接口,它实现了分布式的基础设施和应用之间的解耦。
Linux针对单台机器,Kubernetes针对分布式系统,集群里所有节点都被打平,可以直接调度,又因为其面向不可变基础设施的理念,进程挂掉以后可以重建、可以调度到其他节点上。
Kubernetes是一个虚拟的分布式操作系统, Linux 系统上遇到的问题,在Kubernetes上也将会遇到。
二、分布式应用交付遇到的问题
Kubernetes 发展至今,生态在不断完善,而容器和Kubernetes的生态奠定了一系列应用交付的形态,但是暴露了过多复杂性,选型、维护和管理的复杂性大幅增加。
当前,用户的关注点一直在左移。早期更多的关注点在于基础设施、网络硬件等,而如今已经渐渐无需关注基础设施层,只需专注于自己的业务。
自建Kubernetes主要存在以下三个方面的问题:
第一,资源消耗。对于中小用户而言,维护一套集群会带来很多成本,比如一个高可用的operator需要三副本,还需围绕三副本建立监控、日志等。且集群本身也会占用资源,业务波动时容易导致node节点利用不足、资源浪费。
第二,运维复杂。不仅要了解Kubernetes集群的架构,还要对addon(日志、监控)进行技术选型,保证生产环境出问题时能够快速排查定位。且问题的排查也会给运维工程师带来更多的工作量。
第三,使用心智。Kubernetes的API具有两面性,一方面是面向实现,是operator运行的基础;另一方面是面向使用,比如kubectl、kustomize、helm等。一个裸的kubernetes中约有近百种资源类型,但用户使用到的资源基本不超过10种。
三、SAE的解决之道
Serverless架构已经成为趋势,更容易被大家所认可,也真正提高了用户的使用体验。Serverless不仅指函数计算,也指计算基础设施的所有供应、扩展、监控和配置都委托给平台的操作模型。
如果要自建Kubernetes,则过程类似于选择一台组装电脑,需要经历多次选型比如显卡、CPU、内存等,试错成本高;而如果使用一站式的发布平台,则类似于选择一体机,无需关注各项细节,开箱即用。但一站式的发布平台需要基于大规模的沉淀和积累。此外,阿里也针对一些开源组件进行了改造和适配,沉淀为Serverless的体验。
SAE即上文提到的“一体机 ”——一站式应用发布平台。
SAE平台基于Kubernetes实现,但考虑了与基础设施的兼容,也考虑了面向应用会涉及到的addon适配和兼容等,最终实现了一个集成的版本,为用户提供更好的体验。
SAE提供了Serverless体验,用户无需关注基础设施,将基础设施托管给云平台,以此得到更大的弹性和扩缩容能力。另外,SAE提供了急速弹性和灵活的策略。得益于与云的高度结合,支持突发场景下的秒级弹性伸缩、按量计费等Serverless特点,稳健保障用户的 SLA,支持丰富的弹性策略。
四、SAE技术原理
首先,Kubernetes集成了安全容器。容器的内核是宿主机共享,安全容器相当于每个容器都有独立的内核,保证了不同应用之间不会因为有内核漏洞或越权等出现跨容器的侵入。
社区的安全容器解决方案包括Kata、Firecracker、gVisor。安全容器不仅实现了安全隔离,也实现了性能隔离和故障隔离,不会因为某应用引发内核问题而导致机器上所有应用都产生故障。
SAE提供了微服务无损下线的能力。
Kubernetes所有接口都为异步,pod终止之后才会从注册节点摘掉自己的服务,因此会出现断流。而SAE基于Kubernetes本身的能力 pre-stop 实现了主动下线,一旦收到pod终止的信号,首先会调用 pre-stop 帮助用户主动将流量从注册中心摘除,使得应用在下线过程中不会出现断流。
监控和诊断方面,集成了阿里云内部产品比如 ARMS等,应用发布后可自动集成监控能力,可在界面上一键查看服务调用情况、函数的调用路径等。
SAE提供了端云联调的能力。
用户可以在本地通过 IDE 以及阿里云上的插件,再结合跳板机,即可实现本地和云端的联调,提升用户本地开发的效率。
在SAE场景下,用户对集群无感知,只需创建命名空间,并设置命名空间的 VPCA、switch。应用部署到某个命名空间之后,应用下的pod也会随之部署在 VPCA上,无需自建Kubernetes集群,管理维度也可到达命名空间粒度。
Serverless提供的免运维能力能够直接面向应用,一键部署,无需关注底层的基础设施资源,按照实例收费,按照应用维度做各种运维操作,ECS 上所需的日志监控系统等都已集成在内。
Serverless的极速弹性带来了更好的用户体验以及成本的降低。面对剧烈变化的流量,能够在10-15s内实现迅速伸缩。
原生k8s部署重建升级策略如上图所示。而SAE实现了原地升级策略,只更新镜像时,容器无需重新调度,在原地即可将老的镜像进行销毁然后拉起新镜像,实现快速启动,部署的效率提升42%。
另外,SAE实现了镜像预热策略。拉起pod时很大一部分时间花费在镜像的拉取上,而拉取用户镜像和调度系统的某一部分有重叠,因此,无需在将网络容器建立后再拉取镜像,而是可以提前在某个节点上帮助用户将节点进行加载,加速预热过程,帮助用户更快地启动容器,弹性效率提升30%。
SAE针对不同语言做了启动加速。
以 Java 为例,我们将Dragonwell进行了优化后集成进SAE,增强了AppCDS启动加速。比如多个实例场景下,第一个实例的启动时间可能正常,其他几个实例启动或扩缩容时,可以通过 AppCDS 技术大幅缩短冷启动时间。
同时,利用Dragonwell Wisp的能力实现了Java运行时加速。将正常的 Java 线程转换为协程来实现运行式的加速,运行效率提升20%。
Q&A
Q:函数计算选型时,为什么会选择轻量级的容器?
A:函数计算最早时只有一种模型,即单实例单请求,意味着某一时刻一个实例只能处理一次请求,处理完后,下一次请求如果再打到该实例,则再进行处理。当前,函数计算底层的隔离是 Micro VM ,不再是传统的 Docker。很多客户看到了函数计算的弹性,但是对冷启动无法接受,因此希望通过单实例多请求来规避冷启动。因为多请求时会基于水位实现弹性伸缩,在水位未到达弹出警戒线时,几个并发都在已有的实例上工作,多个请求都在一个Micro VM里,对于单个请求没有做隔离。
Python 或Node.js虽然支持了单实例多并发,但它只是减少了冷启动,具体的请求处理过程中依然是单个处理模型。所以多请求是没有的。另一种比如Java 生态或 go 生态,可以做协程或多线程触发,可以在同一时间处理多个请求,但在runtime 模型上,如果在请求层面再套一层隔离,则会导致 overhead很长。
另外,单实例多线程情况下,一个线程 panic 可能会导致整个实例panic ,目前该问题尚且没有较好的解决方案。