随着云原生关注重心不断从基础设施层向应用架构层上移,各个应用产品包括业务中台都在从CloudHosting往CloudNative演进。最近一年,好多技术甚至产品同学经常言必谈“云原生”,具体的含义却各不相同----有些同学说云原生意思是要镜像化改造和容器化部署;有些同学说云原生意思是要上K8S平台;有些是想做微服务架构优化,想借助Service Mesh的能力来优化服务的管控;而另外有些同学的意思是说我们能不能做到持续交付,快速满足我(产品和业务)。大家有很多诉求点,但由于没有拉齐对云原生整体的认识,往往结果都不满意。有时候,我们甚至像那条寻找大海的小鱼,明明已经在按云原生的技术架构演进了,却视而不见。
所以,对云原生整体特别是云原生背后的思想阐述清楚,达成共识是我们的技术产品能够成功演进到Cloud Native的基础,也是分享这篇文章的初衷。
从亚马逊宕机事件讲起
2015.9.20 AWS有一次比较严重的宕机事故,核心系统持续宕机5小时,很多牛逼公司都受到大面积故障,损失惨重。然而netflix,同样建立在AWS基础设施之上的应用却几乎不受影响,这得益于他高度分布式的架构体系以及经常性的故障演练(混沌工程),使得应用系统能够应对基础设施的不断变化。当Us-east-1出现不可用故障时,一套多Region化部署自治系统(类比我们的单元化架构)能够迅速识别并failover。
这不仅揭示了现代应用系统“始终可用”的关键需求,而且让人们意识到建设比基础设施更可靠的应用系统是可以做到的。
商场如战场,业务上的“快速试错、小步快跑”要求应用系统能够“频繁的迭代和发布”来缩短反馈周期。另一方面,面临移动端和多设备、以及物联网的连接,现代应用系统需要应对巨大且大幅波动的请求和数据量。无论是发布期间面临新旧版本更替,还是在运行期间遇到突发的流量洪峰,甚至是遇到基础设置的故障,应用系统需要一直运行。“零停机”这个时髦的词也成为了现代应用系统的技术要求。
我们把这些需求看做是对现代应用系统的美好理想的话,那现实中面临的问题还是非常骨感的----习以为常的碎片化变化,有风险的部署,以及在开发设计的时候总是假设环境或者某些依赖是稳定不变的
如何做到,我们的环境是一致的?可部署的构件是一致的?没有碎片化变化所以流程是可以重复可以自动化的?基础设施和应用系统在设计之初就考虑了各种失败以及应对措施的?最终我们在技术层面做到安全部署,在业务层面做到持续交付。这就是云原生背后的核心诉求。
那么什么到底是云原生
怎么理解云原生?我认为云即云计算,没有云计算就无所谓云原生了,云代表了基础设施,一种不可变基础设施;而“原生”指的是应用程序,我理解为原生为云设计的应用系统。除了技术层面的含义,“云原生”还有非技术层面的诉求,通过组织架构和研发流程层面对devops的支撑,最终做到持续交付。
既然云原生分为云(计算)和原生(为云设计的应用)两部分,那我们分别来看一下。
- 云(计算)
云计算是伴随着虚拟化技术发展而诞生的,而随着云计算的发展更加促进了虚拟化技术的发展。1974年《Formal Requirements for Virtualizable Third Generation Architectures》论文的发表奠定了虚拟化技术的理论基础,随后vmware与1998年将虚拟化技术引入到X86架构,然后除了计算的虚拟化之外,网络和存储虚拟化也逐步发展。随着2005年以及2006年两个大名鼎鼎的虚拟化开源技术(XEN和KVM)的发布之后,云计算开始蓬勃发展。云计算的蓬勃发展反过来促进虚拟化技术朝着软硬一体的方向发展,具有代表性的是AWS的Nitro以及阿里云的神龙。而云计算从IaaS到PaaS再到FaaS的发展逐渐为云原生概念的诞生准备了良好的土壤。 而另一方面,随着容器和容器编排技术的发展,PaaS层面的标准逐步确立之后,云原生概念和技术也就和盘托出了。
- 原生(为云设计的应用)
什么样的应用是原生为云设计的应用?从一开始提出的12 Factors应用,到后来提出Beyond 12 Factors之外的三点(API先行、遥测、认证和鉴权),基于微服务架构的应用被认为原生为云设计的应用。有人可能会说在云原生概念提出之前已经微服务架构了。确实如此,“云原生”是技术先行,概念随后。无论是在云原生概念提出之前的微服务、容器等技术的探索,还是随后云原生概念山呼海啸而来,背后的理念都是为了解决现代应用程序的需求。
有了这层理解,我们来看一下云原生的定义。
Pivotal作为云原生的鼻祖,对云原生的定义有过几次调整,最后认为云原生的定义包括技术层面微服务和容器,以及通过非技术层面的devops做到业务上的持续交付。
云原生官方组织CNCF对云原生的定义也有过调整,在V1.0版本的定义中,认为云原生代表技术有五方面:
云原生技术--容器
相比虚拟机,容器的进程隔离机制具有更高效的资源利用率、更快速的启动、更轻松的迁移、更方便的维护和扩展,更重要的是能够提供一致的运行环境。这得益于容器的两种关键技术:namespace和cgroup.
一开始容器产品也是竞争激烈,最终 Docker胜出逐步席卷天下,这得益于docker建立了一整套容器管理的生态系统(包括镜像、镜像仓库、容器以及友好的API)、以及基于分层的镜像模型使得生态快速生长和积累。
云原生技术--Kubernetes
在介绍kubernetes的架构和原理之前,先来看一下k8s两种设计理念
- 面向变化的设计思路
提供各种API来接受客户端的请求,每一种请求都代表了用户的一种期望,也就是系统要到达的终态;利用状态存储组件来存储系统需要到达的终态;调度器组件不断的轮询系统当前的的实际状态和用户期望的状态是否一致(通过比较器),如果发现不一致则进行一次调和,使得系统的状态逐步达到终态为止。
- 声明式API
有了面向变化设计思路和声明式API的介绍铺垫,现在再来大概K8S架构&工作原理。首先是master节点主要是四个组件,API Server负责接收客户端请求(所有的请求和交互都要经过他),etcd是他的分布式状态存储,Controller Manager不断的循环来检测系统的实际状态和用户期望的终态是否一致,Scheduler负责调度。k8s的另一部分工作节点(集群)是运行用户容器组(Pod)的地方,节点上的kubelet组件会去运行pod和网络组件。
用一个例子来解释下工作原理,假设创建一个Deployment资源,APIServer会把这个资源存在到etcd里,同时DeploymentController会通过watch机制收到通知,DeploymentController于是通过调用ApiServer 把deployment中包含的ReplicaSet资源创建出来(也是保存到etcd里),此时ReplicaSetController会收到通知,发现有Pod需要创建,于是就把需要创建的Pod通过ApiServer保存到etcd里。当scheduler监听有pod需要创建时,会根据pod模板描述进行节点调度,把Pod调度的node信息一起写到(通过ApiServer)etcd里。最后,对应Node上的kubelet监听到之后就开始运行容器组。
所以K8S各个组件各司其职,通过资源抽象和实现对应资源controller的方式来玩的。
云原生技术--Service Mesh
服务网格主要解决应用架构基础设施下沉问题,让应用研发的同学专注在业务研发层面,而服务管控、流量、熔断等能力下沉到Mesh层面。
服务网格的实现思路是Sidecar模式,通过为每个业务容器配备一个sidecar容器来劫持流量达到目的。
介绍完云原生代表技术之后,我们来看云原生平台,从云机房到云就绪再到云原生,是 “关注重心不断从基础设施层向应用架构层上移” 的发展过程.
伴随着关注点的上移,云原生平台分层也在逐渐变化,使得我们的平台工程师和应用工程师的关注点能够很好的分离。
关注点的分离,使得我们应用工程师只需关注应用研发和可部署构件,通过配置外化、声明式描述期望的状态达到前文描述的“一致的环境和构件、可重复和自动化”等。而基础设施层面的资源调度和编排等无需应用研发关注。最终迈向serverless,用户无需知道我们系统需要多少资源,资源在哪里,当需要的时候自然会扩容满足,当流量下降或者系统负载降低之后自动缩容,做到pay as you go.
Serverless那么智能,还需要花大力气建设云原生应用干什么?
既然serverless那么好,可以按需为你提供资源,为什么还需要花大力气建设云原生应用?其实原因可以讲很多,围绕这个几个问题想一下:serverless真的可以帮我们无限制的弹性扩容吗?我们的预算是无上限的吗?单纯依靠基础设施的弹性扩缩容能力真的能够得到良好的结果吗?显然不是,我们的应用系统还需要有一定的容错能力,且不说基础设施有可能出现不稳定的情况(如AWS宕机事件),即便是遇到流量洪峰若是没有自身的保护也是会被击垮的。所以,云原生应用需要做好三点设计:面向高可用的设计、面向易扩展的设计、面向失败的设计。下面是一个微服务化的网上银行的例子,展示了云原生应用模型:服务、数据和交互。服务是高度分布式、且无状态的,状态数据跟着服务走,服务有管控和路由,服务之间的交互除了请求-响应之外,很多时候会考虑基于事件的异步方式。
最后,云原生让我们以基础设施为中心的模式转变到以应用为中心的模式,我们不再关注应用有哪几台服务器,不会再登录到服务器上去做碎片化的更改,而是通过事件流的方式集中收集日志来监控应用状态。当某台服务器出现问题的时候,云原生的方式不是ssh登录上去修复他,而是让其死掉重新创建一台服务,我们可以去修改代码和配置重新构件镜像来升级版本。而要做到这一些需要很多前文描述的云原生平台和云原生应用共同实现,很多架构设计和技术细节会在后续的文章里逐步分享。