赞
踩
云原生技术
本文系统地介绍了云原生技术的产生背景、主要技术,以及云原生技术助力降本增效的案例。云原生涉及的内容较广,本文的深度不会很深,停止在知道是什么的层面,希望本文能帮助初接触云原生的读者加深理解,如有不对之处也烦请不吝赐教。全文篇幅较大,有些太过细节的内容已经用方框标注,如果不感兴趣可以跳过,不影响理解。
目录
2.5.1.1 FaaS(Function as a Service,函数即服务)
2.5.1.2 BaaS(Backend as a Service,后端即服务)
3.3 智联招聘升级为云原生架构,释放Serverless技术红利
随软件规模的增大、业务模块规模变大、部署环境增多、分布式复杂性增强、版本迭代速度加快,今天的软件构建变得越来越复杂,大量非业务性的事务耗费了大量人力物力。简单总结一下,软件更复杂、迭代需求更快、稳定性要求更高。
云计算出现后,云厂商提供了统一的IaaS能力和云服务,大幅提升了企业IaaS层的复用程度,但还远远不够,云计算从工业化应用到如今,已走过十七个年头,大量应用使用云的方式仍停滞在传统IDC时代:
对于如何使用这些技术,没有绝对的对与错,只是在云的时代不能充分利用云的强大能力,不能从云技术中获得更高的可用性与可扩展能力,也不能利用云提升发布和运维的效率,是一件非常遗憾的事情。
为使资源、产品可被不断复用,为能够进一步降低企业运营成本,IaaS以上层的系统也需要被统一,云的时代需要新的技术架构,来帮助企业应用能够更好地利用云计算优势,充分释放云计算的技术红利。
|
作为诞生于云计算时代的新技术理念,云原生拥有传统IDC无法比拟的优势,成为驱动业务增长的重要引擎。综上,云原生架构主要带来了以下提升:
1.快速开发:
2.自动发布(高度自动化的软件交付)
3.稳定运维(云的可用性与可扩展能力)
以大家最头疼的高可用为例,云产品在多个层面为应用提供了解决方案:
对企业而言,云原生技术能提升应用开发的交付效率,缩短应用上线所需的时间,企业有更多时间和精力进行业务创新。一开始,云原生技术生态主要集中在容器、微服务、DevOps等技术领域,但现在已扩展至底层技术、编排及管理技术、安全技术、监测分析技术以及场景化应用等众多分支,初步形成了支撑应用云原生化构建的全生命周期技术链。
企业业务要想真正的云化,不仅要在基础设施和平台层面实现,而且应用本身也应该基于云的特点进行开发,从架构设计、开发方式、部署维护等各个阶段和方面重新设计,构建真正应“云”而生的“云原生应用”。
容器作为标准化软件单元,它将应用及其所有依赖项打包,使应用不再受环境限制,可以在不同计算环境间快速、可靠地运行。以前部署应用需要在物理机上装系统、装环境、装依赖项,最后才能部署应用本身,哪怕虚拟机出现后,准备环境和依赖项仍然是件麻烦的事情,不同版本的环境和依赖项还有可能影响稳定性,而容器则很好地解决了以上问题。
容器的一个常见用例是在同一主机中拥有同一服务(例如,数据库服务器)的多个副本。每个副本都有独立的资源(文件系统、端口、内存),因此服务不需要处理资源共享,隔离保证故障或有害服务不会影响同一主机或底层系统中的其他服务或容器。
图1 传统、虚拟机、容器部署模式比较
表1 虚拟机和容器技术对比
对比项 | 虚拟机 | 容器 |
镜像大小 | 包含GuestOS,几十G以上 | 仅包含应用运行的bin/lib,几十M |
资源要求 | CPU按核分配,内存按G分配 | CPU按0.x核分配,内存按0.0xG分配 |
启动时间 | 分钟级 | 毫秒/秒级 |
可移植性 | 跨物理机器迁移 | 跨OS平台迁移 |
弹性伸缩 | VM自动伸缩、CPU/内存手动伸缩 | 实例自动伸缩、CPU/内存自动在线伸缩 |
隔离策略 | OS、系统级 | Cgroups、进程级 |
虽然2008年Linux就提供了Linux Namespace视图隔离方案、Cgroups资源管理机制,让应用得以运行在独立沙箱环境中,避免相互间冲突与影响,但标准化与可移植性面临较大挑战;直到Docker容器引擎的开源,才很大程度上解决了容器标准化与可移植性问题。Docker提出了创新的应用打包规范—Docker镜像,解耦了应用与运行环境,使应用可以在不同计算环境间一致、可靠地运行。
2016年OCI组织推出了开放容器标准,包括容器运行时标准(runtime spec)和容器镜像标准(image spec),推动了容器技术的广泛应用。借助容器技术,实现了一个优雅的场景:让开发所需要的灵活性、开放性和运维所关注的标准化、自动化达成相对平衡。如下图,docker应用是一种C/S架构,包括3个部分:
1.Docker Client:Docker的应用/管理员,通过相应的docker命令通过HTTP或REST API等方式与docker daemon实现docker服务使用与管理。
2.Docker Host:运行各种docker组件,提供容器服务。其中Docker Daemon负责监听Docker Client的请求并管理docker对象(容器、镜像、网络、磁盘等);Docker Image提供容器运行所需的所有文件;Linux内核中的Namespace负责容器的资源隔离,而Cgroup负责容器资源使用限制,每个容器的文件系统与其他容器是隔离的;容器内的存储层是跟随容器变化的,生命周期同容器保持一致,容器删除,则存储层信息丢失,所以存储东西最好使用存储卷(volume)、绑定宿主目录等方式。
3.Docker Registry:容器镜像仓库,负责docker镜像存储管理。可以用镜像仓库如Docker Hub或者自建私有镜像仓库,通过docker push/pull往镜像仓库上传/下载镜像。
所以,Docker运行过程就是Client发送Docker run命令到Docker Deamon,Docker Deamon从本地或镜像仓库获取Docker镜像,然后通过镜像启动运行容器实例。
图2 Docker容器应用架构
容器引擎负责容器的生命周期管理与资源管理,2017年4月docker公司将docker项目改名为Moby。Moby容器引擎的内部架构下图:
1.Moby daemon:通过HTTP/HTTPS或Restful API对外提供容器、镜像、网络与存储的管理。
2.Containerd:容器运行时管理引擎,向上提供gRPC调用,实现镜像与容器的基本管理。通过containerd-shim插件模块实现对不同容器运行时模块的创建、动态接管,保障Moby daemon或containerd动态升级时对业务不产生影响。
3.容器运行时RunC:基于OCI标准实现,负责容器的配置文件、运行环境与生命周期管理。另外应对Docker容器安全性不足,新推出Kata、gVisor等安全容器技术。
图3 Moby容器引擎架构
Linux namespace负责容器的工作空间与资源隔离。
容器中namespace通过unshare系统调用来创建,Linux内核提供了7中namespace: 1.PID namespace:保障进程隔离,每个容器都以PID=1的init进程来启动; 2.MNT namespace: 保障每个容器都有独立的目录挂载路径; 3.UTS namespace:保障每个容器都有独立的主机名或域名; 4.NET namespace:保障每个容器都有独立的网络栈、socket和网卡设备; 5.IPC namespace:只有在相同IPC命名空间的容器才可以利用共享内存、信号量和消息队列通信; 6.User namespace:用于隔离容器中UID、GID以及根目录等,可配置映射宿主机和容器中的UID、GID; 7.Cgroup namespace:保障容器中看到的cgroup视图像宿主机一样以根形式来呈现,同时让容器内使用cgroup会变得更安全。 |
Cgroups对容器进程进行层次化分组,并按组实现资源限制和策略控制。
1.Cgroupfs驱动:需要限制CPU或内存使用时,直接把容器进程的PID写入相应的CPU或内存的cgroup; 2.Systemd cgroup驱动:提供cgroup管理,所有的cgroup写操作需要通过systemd的接口来完成,不能手动修改。 Linux内核提供了很多Cgroup控制器,容器中常用的是 1.cpu/cpuset/cpuacct group:设置CPU share、cpuacct控制CPU使用率; 2.memory group:控制内存使用量; 3.device group:控制在容器中看到的device设备,保障安全; 4.freezer group:容器停止时Freezer当前容器进程都写入cgroup,进程冻结; 5.blkio group:限制容器到磁盘的IOS、BPS; 6.pid group:限制容器里面可用到的最大进程数量。 |
Kubernetes已经成为容器编排的事实标准,被广泛用于自动部署,扩展和管理容器化应用。Kubernetes提供了分布式应用管理的核心能力:
Kubernetes的控制平面包含四个主要的组件:API Server、Controller、Scheduler以及ETCD,如下图所示:
图4 K8S系统架构
Master的主要组件功能如下:
Node的主要组件功能如下:
Pod是K8S的最小调度以及资源分配单元,包含容器运行环境与资源。Pod之间相互隔离。一个Pod运行一个或多个容器,当某些容器间关系非常紧密Tightly coupled(如文件交换、频繁的RPC调用、共享网络或存储等),可在一个Pod运行多个容器方便调度管理。
Pod中可以通过Infra Container共享网络。Infra Container,大小100-200KB,最先启动,并绑定了Pod的唯一IP地址与各种网络资源,Pod内其他容器通过加入Infra Container的Network namespace来实现网络共享。Pod中的多个容器也可以通过挂载相同的共享路径实现存储共享。 Pod中可定义Init Container在应用启动前先启动来执行一次性的辅助任务,比如执行脚本、拷贝文件到共享目录、日志收集、应用监控等,以此将辅助功能与主业务容器解耦,实现独立发布和能力重用。 |
一个Pod就是一个应用运行实例,可以运行多个Pod实现应用横向扩展。当调度失败或运行失败时,Pod本身没有自恢复能力,需要借助上层的controller来通过采用提前定义好的Pod模板创建Pod,提供Pod重启、重建或迁移能力。
简而言之,Pod是k8s调度的最小单元,一个Pod可以包含1个或多个容器,可以理解为Pod是容器集合,每个Pod通过describe可以看到都有自己的ip地址,Pod内的容器共享相同的ip;Node是一个执行具体工作的机器,它可用是虚拟机也可用是物理机,一个Node上面可以有多个Pod,每个Node都由Master统一管理,关系如下图所示。
图5 Pod和Node的关系示意
K8S调度主要涉及资源调度和关系调度,采用两种机制过滤(Filtering)和打分(Scoring)。通过过滤机制选择备用节点,过滤因素包括CPU/内存/存储、Pod与Node匹配、Pod与Pod匹配等;然后将Pod调度到分数最高的节点,打分依据包含亲和性/反亲和性、资源水位等等。完整的调度流程如下:
默认情况下,容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题:
Kubernetes Volume解决了以上两个问题。本质上,Kubernetes Volume 是一个目录,当Volume被mount到Pod,Pod中的所有容器都可以访问这个Volume。Kubernetes Volume的生命周期与Pod相同,因此,Volume的生命周期比Pod中运行的任何容器要持久,在容器重新启动时能可以保留数据,但当Pod被删除不存在时,Volume也会被卸载(但有些类型的Volume不会删除数据)。在Docker中也有一个Docker Volume的概念,但Docker的Volume只是磁盘中的一个目录,生命周期也不受管理。Kubernetes Volume的涵义比Docker Volume更广,Kubernetes支持许多类型的Volume,一个Pod可以同时使用任意类型/数量的Volume。Kubernetes Volume的类型包括:
下面介绍几个比较重要的类型,其余的详见(http://docs.kubernetes.org.cn/429.html):
1. emptyDir:当Pod分配到Node上时,将自动会创建emptyDir,并且只要Node上的Pod一直运行,Volume就会一直存。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。注:删除容器不影响emptyDir。。
2.hostPath:挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。
3.local Storage:Local 是Kubernetes集群中每个节点的本地存储(如磁盘,分区或目录),在Kubernetes1.7中kubelet可以支持对kube-reserved和system-reserved指定本地存储资源,Local Storage同HostPath的区别在于对Pod的调度上,使用Local Storage可以由Kubernetes自动的对Pod进行调度,而是用HostPath只能人工手动调度Pod,因为Kubernetes已经知道了每个节点上kube-reserved和system-reserved设置的本地存储限制。
4. Persistent Volume:将Pod与Volume生命周期解耦,同时通过PVC(Persistent Volume Claim)实现职责分离,用户可以在不知道特定云环境的细节的情况下,实现持久化存储。其中,PVC定义业务侧的存储需求,如存储容量、访问模式(独占还是共享、只读还是读写)等,由用户提出;PV是存储的具体实现,分配存储空间,由管理员事先制备,PV是集群之中的一块网络存储,跟Node一样,也是集群的资源,并且不属于特定的namespace,有独立于Pod的生命周期。
图6 PV存储分配方式
K8S中通过工作负载Workload来管理应用部署与发布。需要基于不同的工作负载类型(Deployment、StatefulSet、DaemonSet、Job、CronJob),配置存储卷、容器实例与镜像、实例的数量与弹性伸缩、服务访问方式等。不同负载类型与说明如下表,另外容器中还可以通过ConfigMap、Secret来保持容器中的可变配置与敏感信息。
表2 不同类型工作负载特征
工作负载类型 | 关键特征 |
Deployment | 管理部署无状态应用。Deployment管理不同版本的ReplicaSet,ReplicaSet管理相同版本的Pod。Deployment调整ReplicaSet的终态副本数,控制器会维持实际运行的 Pod数量与期望的数量一致,Pod出故障时可以自动重启或恢复。 |
StatefulSete | 管理部署有状态应用。创建的Pod 拥有根据规范创建的持久型标识符。Pod迁移或销毁重启后,标识符仍会保留,如每个 Pod 有序号,可以按序号创建更新或删除;Pod有唯一网络标志(hostname)或独享的存储PV,支持灰度发布等。 |
DaemonSet | 管理部署每个节点都要运行的任务,如监控、日志收集等,也可以通过标签的方式指定哪些节点运行。 |
Job | 单次任务。可创建一个或多个Pod,监控Pod是否成功运行或终止;根据Pod状态设置重复次数、并发度、重启策略。 |
CronJob | 定时的Job,可以指定运行时间、等待时间、是否并行运行、运行次数限制。 |
表3 不同类型存储特征
存储类型 | 关键特征 |
ConfigMape | 存储容器的可变配置(文件、环境变量或命令参数),使容器的配置与运行镜像解耦,保证容器可移植性。可以通过挂载、环境变量或运行命令方式在容器中使用。 |
Secrete | 采用 base-64 编码保存密码、令牌、密等敏感信息。可以通过挂载、环境变量或运行命令方式在容器中使用。 |
K8S服务Service提供了功能相同的一组Pod统一抽象入口,定义了服务访问方式与负载均衡,实现前端Client的服务访问与后端Pod上的服务部署解耦。另外可以通过Ingress实现基于HTTP/HTTPS的7层负载均衡,配置转发规则,实现不同URL访问不同的service,支持配置SSL证书。如下表,容器服务支持基于负载均衡、Cluster IP或Node Port方式实现不同场景下的服务访问。
表4 不同服务访问方式
访问方式 | 说明 |
公网访问 | 使用负载均衡模式,分配公网 IP,实现公网访问容器服务;集群外通过域名或IP+服务端口访问;集群内通过服务名+端口访问。适合Web类服务。 |
集群内访问 | 使用Cluster IP模式,分配容器内网IP,集群内通过服务名+服务端口访问。适合数据库类服务。 |
VPC内网访问 | 使用负载均衡模式,分配VPC子网IP,实现VPC内访问容器服务;集群外通过域名或IP+服务端口访问;集群内通过服务名+端口访问。适合Web类服务。 |
Node Port访问 | 提供主机端口映射到容器的访问方式,支持TCP、UDP。可以通过IP+主机端口或服务名+服务端口访问服务。 |
1.就绪探针与存活探针
要保障容器应用的健康稳定运行,需要提供应用的运行状态、资源使用的可观测性与恢复能力。系统通过就绪探针Readiness Probe探测Pod是否处于就绪状态,如果不就绪就切断上层流量,Pod不对外提供服务;通过存活探针Liveness Probe探测Pod是否存活,如果不存活,根据重启策略判断是否需要重新拉起pod。两种探针支持3种探测方式:
2.监控告警与日志
K8S监控分为几种类型,如资源监控(CPU、内存、网络)、性能监控(APM应用性能指标)、安全监控(安全策略、越权管理、安全漏洞)、事件监控(正常Normal事件或异常warning事件)。目前K8S采用主流的开源监控标准Prometheus,应用侧只需要实现 Prometheus Client就可以实现数据采集,支持3种数据采集策略:
K8S日志也分为几种类型:主机内核日志、运行时Runtime日志、K8S组件日志、业务应用日志。日志通过宿主机文件、容器日志文件或日志标准或错误输出进行采集。目前主流的日志采集呈现方案是ELK,通过 Fluentd采集日志,将数据汇集到 Elasticsearch(或InfluxDB)分析处理,然后再通过 Kibana(或Grafana)做日志展现。
过去开发一个后端应用最为直接的方式就是通过单一后端应用提供并集成所有的服务,即单体模式。随着业务发展与需求不断增加,单体应用功能愈发复杂,团队人员也越来越多,应用迭代效率由于集中式研发、测试、发布、沟通模式而显著下滑。为了解决由单体应用模型衍生的过度集中式项目迭代流程,微服务模式应运而生。
微服务模式将后端单体应用拆分为松耦合的多个子应用,每个子应用负责一组子功能。这些子应用称为“微服务”,多个“微服务”共同形成了一个物理独立但逻辑完整的分布式微服务体系。由于微服务架构有下面这几个优势,已经成为云计算时代应用的标准架构:
但也要注意到微服务模型也面临着分布式系统的典型挑战:如何高效调用远程方法、如何实现可靠的系统容量预估、如何建立负载均衡体系、如何面向松耦合系统进行集成测试、如何面向大规模复杂关联应用的部署与运维……
在云原生时代,云原生微服务体系将充分利用云资源的高可用和安全体系,让应用获得更有保障的弹性、可用性与安全性。
相较于单体应用,微服务架构的架构转变,在提升开发、部署等环节灵活性的同时,也提升了在运维、监控环节的复杂性。在结合实践总结后,阿里云的《云原生架构白皮书》中总结了设计一个优秀的微服务系统应遵循以下设计约束:
一个设计良好的微服务应用,所完成的功能在业务域划分上应是相互独立且功能完整的,微服务的“微”并不是为了微而微,而是按照问题域对单体应用做合理拆分。如果当一个微服务修改或者发布时,不应该影响到同一系统里另一个微服务的业务交互。
在合理划分好微服务间的边界后,主要从微服务的可发现性和可交互性处理服务间的横向关系:
可发现性是指当服务A发布和扩缩容的时候,依赖服务A的服务B如何在不重新发布的前提下,如何能够自动感知到服务A的变化,这里需要引入第三方服务注册中心来满足服务的可发现性,特别是对于大规模微服务集群,服务注册中心的推送和扩展能力尤为关键。
可交互性是指服务A采用什么样的方式调用服务B。由于服务自治的约束,服务之间的调用需要采用与语言无关的远程调用协议,比如 REST 协议很好的满足了“与语言无关”和“标准化”两个重要因素,在高性能场景下,基于IDL的二进制协议可能是更好的选择。
伴随着服务链路的不断变长,整个微服务系统也就变得越来越脆弱,因此面向失败设计的原则在微服务体系中就显得尤为重要。对于微服务应用个体,限流、熔断、隔仓、负载均衡等增强服务韧性的机制成为了标配。
在微服务领域,提倡数据存储隔离(DSS, Data Storage Segregation)原则,即数据是微服务的私有资产,对于该数据的访问都必须通过当前微服务提供的 API 来访问。如若不然,则造成数据层产生耦合,违背了高内聚低耦合的原则。同时,出于性能考虑,通常采取读写分离(CQRS)手段。
同样的,由于容器调度对底层设施稳定性的不可预知影响,微服务的设计应当尽量遵循无状态设计原则,这意味着上层应用与底层基础设施的解耦,微服务可以自由在不同容器间被调度。对于有数据存取(即有状态)的微服务而言,通常使用计算与存储分离方式,将数据下沉到分布式存储,通过这个方式做到一定程度的无状态化。
从微服务系统设计一开始,就需要考虑以下因素:
第一代微服务架构中,应用除了需要实现业务逻辑之外,还需要自行解决上下游寻址、通讯,以及容错等问题。随着微服务规模扩大,服务寻址逻辑的处理变得越来越复杂,哪怕是同一编程语言的另一个应用,上述微服务的基础能力都需要重新实现一遍。
在第二代微服务架构中,引入了旁路服务注册中心作为协调者来完成【服务的自动注册和发现】。【服务之间的通讯以及容错机制】等服务治理能力开始被模块化,形成服务框架,各个微服务通过封装的SDK引入服务框架。
随着服务框架功能的日益增多,大量孤立的SDK被绑定在业务服务上,导致两方面问题,从而违背了微服务的敏捷迭代原则:
图7 第一、二代微服务架构
2016年出现了第三代微服务架构—服务网格,原来被模块化到服务框架里的微服务基础能力,被进一步地从一个SDK演进成为一个独立进程—Sidecar。这个变化使得第二代架构中多语言支持问题得以彻底解决,微服务治理能力演进和业务逻辑迭代彻底解耦,这个架构就是在云原生时代的微服务架构—Cloud Native Microservices。
在分布式系统中,应用通常包含业务逻辑、非功能性需求(NFR)和中间件依赖(三方依赖)。在应用程序中,只有业务逻辑才承载具体的业务价值,NFR 和三方依赖是必要的非增值活动,不直接产生业务价值,但是非增值活动耗费开发人员大量的时间和精力,导致业务交付速度慢。在第三代微服务架构中,NFR能力从业务逻辑中抽离出来,下沉到单独的组件中,实现 NFR 与业务逻辑的沉底解耦。边车进程(Sidecar)实现了大部分的NFR的能力(如可观测性、熔断、限流、灰度、路由、负载均衡等)。
图8 第三代微服务架构
服务网格解决了大部分的NFR的能力,但是三方依赖(如Mysql、Redis、MQ等)与业务逻辑耦合,仍然需要开发人员通过lib库或SDK的方式在业务代码中进行集成,不能让开发纯粹的专注于业务逻辑开发和业务价值交付。三方依赖(分布式能力)是否也可以以 sidecar的方式独立于业务逻辑,并且提供统一的能力抽象,屏蔽底层的组件差异,成为技术架构演进的新方向。
多运行时微服务架构由Red Hat的首席架构师Bilgin Ibryam提出,Bilgin Ibryam梳理总结了分布式应用的各类需求后,将其划分成了生命周期、网络、状态以及绑定四种类型,NFR和三方依赖被包含在这四种类型的需求中。
表5 分布式应用的四类需求
需求类型 | 说明 | 主要内容 | 分布式应用 |
生命周期 | 即应用从开发态到运行态之间进行打包、部署、扩缩容等需求 | 打包(Packaging)、健康检查(Healthcheck)、部署(Deployment)、缩扩容(Scaling)、配置(Configuration)、 | Kubernetes |
网络 | 分布式系统中各应用之间的服务发现、容错、灵活的发布模式、跟踪和遥测等需求 | 服务发现(Service discovery) A/B 测试、金丝雀、回滚(A/B testing、canary rollouts) 重试、超时、熔断(Retry,timeout,circuit breaker) 安全、可观察性(Point-to-point,pub/sub) | 服务发现/注册、负载均衡、流量管理 |
状态 | 我们期望服务是无状态的,但业务本身一定需要有状态,因此包含对缓存、编排调度、幂等、事务等需求 | 工作流管理(Workfow mgmt)、幂等性(Idempotency)、时间调度(Temporal scheduling)、缓存(Caching)、应用状态(Application state) | 数据库、对象存储、块存储 |
绑定 | 与外部服务之间进行集成可能面临的交互适配、协议转换等需求 | 链接(Connectors)、协议转换(Protocol conversion)、消息投递(Message transformation)、消息路由(Message routing)、事务性(Transnationality) | 事件分发、分布式事务、消息路由 |
在多运行时微服务架构中,非功能性需求(NFR)和三方库能力彻底与业务逻辑解耦,并以独立的sidecar(进程)提供这些能力。开发人员无需关注必要的非增值活动,最大限度的管制业务逻辑实现和业务价值交付。
图9 第四代微服务架构
在多运行时微服务架构中,有两个组件,其中每个组件都是独立的运行时,这两个组件都位于同一个主机中,并且在它们之间有可靠的网络。组件之一称为微逻辑(Micrologic),它包含了几乎所有从分布式系统关注点中剥离出来的最小业务逻辑。另一个组件叫Mecha,提供了所有分布式系统功能(生命周期除外,它是平台的功能),Mecha特征如下:
对于特定的API 交互操作,可以为Mecha附加规范,如OpenAPI、AsyncAPI、ANSI-SQL等;对于由多个步骤构成的状态化工作流,可以使用如亚马逊状态编程语言(Amazon State Language)的规范。对无状态集成,可以用类似Camel-K YAML DSL 的方法使用企业集成模式(Enterprise Integration Patterns,简称 EIPs)。 |
图10 多运行时微服务架构
微服务架构本质上与容器及K8S技术无关,在Java体系的Spring Cloud就提供了诸如网关Zuul组件、Ribbon负载均衡组件、Eureka服务注册组件、LCM扩容组件、Hystrix业务恢复组件。利用Spring Cloud的能力可以实现一套完善的微服务架构。Spring Cloud有大量的java开发人员所拥护,这是它的优势。但是Spring Cloud的劣势很突出,那就是限制编程语言和编程技术。
Kubernetes提供了服务注册、配置管理、负载均衡、故障隔离、业务恢复、自动扩容等能力。基于Kubernetes的Paas平台又提供了诸如基础数据服务、网关服务、微服务治理服务等基础服务能力。此外,Kubernetes不限制编程语言,社区活跃、功能稳定。所以微服务与Kubernetes集成会是一个大趋势。
在第三代微服务架构中,Service Mesh技术将那些微服务间的连接、安全、流量控制和可观测等通用功能下沉为平台基础设施,大量非功能性从业务进程剥离到另外进程中,Service Mesh以无侵入的方式实现了应用轻量化。下图展示了 Service Mesh 的典型架构:
图11 Istio架构
2017年发起的服务网格Istio开源项目,清晰定义了数据平面(由开源软件Envoy 承载)和管理平面(Istio自身的核心能力)。Istio为微服务架构提供了流量管理机制,同时亦为其它增值功能(包括安全性、监控、路由、连接管理与策略等)创造了基础。
在Istio架构中,Service A调用Service B的所有请求,都被其下的Proxy(在Envoy中是Sidecar)截获,代理完成Service A到Service B的服务发现、熔断、限流等策略,而所有这些策略的总控在Control Plane上配置。
从架构上,Istio可以运行在虚拟机或容器中,Istio的主要组件包括Pilot(服务发现、流量管理)、Mixer(访问控制、可观测性)、Citadel(终端用户认证、流量加密);整个服务网格关注连接和流量控制、可观测性、安全和可运维性。
虽然相比较没有服务网格的场景多了4个IPC通讯的成本,但整体调用的延迟随着软硬件能力的提升而并不会带来显著的影响,特别是对于百毫秒级别的业务调用而言可以控制在2%以内。从另一方面,服务化的应用并没有做任何改造,就获得了强大的流量控制能力、服务治理能力、可观测能力、4个9以上高可用、容灾和安全等能力,加上业务的横向扩展能力,整体的收益仍然是远大于额外IPC通讯支出的。
服务网格的技术发展上数据平面与控制平面间的协议标准化是必然趋势。大体上,Service Mesh的技术发展围绕着“事实标准”去展开——共建各云厂商共同采纳的开源软件。从数据平面角度,Envoy得到了包括Google、IBM、Cisco、Microsoft、阿里云等大厂的参与共建以及主流云厂商的采纳而成为了事实标准,而Service Mesh本身也将成为容器服务技术的标配技术组件。
微服务在帮助架构解耦的同时,也带来了很多新的挑战,比如运维成本的增加和部署自动化等挑战。即使使用云平台动态管理基础设施,仍然要面临如下现实问题:
Serverless,顾名思义就是无服务器架构,也就是说从使用者的角度,看不到服务器的存在,只要使用或者直接部署代码即可。
它与传统架构的不同之处在于,开发者实现的服务端逻辑运行在无状态(Stateless)的暂存计算容器中,它由事件触发, 完全被第三方管理;业务层面的状态则被开发者使用的数据库和存储资源所记录。
构建Serverless应用程序意味着开发者可以专注在产品代码上,而无需做复杂的容量规划和手动变配,无需管理和操作云端或本地的服务器或运行时,无需要关心 CPU、内存等资源的监控和告警。Serverless真正做到了部署应用无需涉及基础设施的建设,自动构建、部署和启动服务。
过去是“构建一个框架运行在一台服务器上,对多个事件进行响应”,Serverless则变为“构建或使用一个微服务或微功能来响应一个事件”,做到当访问时,调入相关资源开始运行,运行完成后,卸载所有开销,真正做到按需按次计费。
国内外的各大云厂商 Amazon、微软、Google、IBM、阿里云、腾讯云、华为云相继推出Serverless产品,Serverless也从概念、愿景逐步走向落地,在各企业、公司应用开来。Serverless涵盖了很多技术,分为两类:FaaS和BaaS。
FaaS(Function as a Service函数即服务)。开发者实现的服务器端应用逻辑(微服务甚至粒度更小的服务)以事件驱动的方式运行在无状态的临时的容器中,并且这些容器、计算资源都是由第三方管理。使用FaaS后,用户不需要自行供应服务器,也不需要全时运行应用程序。
FaaS产品不要求必须使用特定框架或库进行开发。在语言和环境方面,FaaS函数就是常规的应用程序。例如AWS Lambda的函数支持Javascript、Python代码的直接部署,JVM语言(Ruby(JRuby)/Scala/Clojure/Java等)编译成class文件部署。在迁往FaaS的过程中,唯一需要修改的代码是“主方法/启动”代码,其中可能需要删除顶级消息处理程序的相关代码(“消息监听器接口”的实现),可能只需要更改方法签名。
FaaS中的函数可以通过供应商定义的事件类型触发。对于亚马逊AWS,此类触发事件可以包括S3(文件)更新、时间(计划任务),以及加入消息总线的消息(例如Kinesis)。通常函数可以通过参数指定需要绑定到的事件源。大部分供应商还允许函数对传入的Http请求进行响应来触发,通常这类请求来自某种该类型的API网关(例如AWS API网关、Webtask)。
BaaS(Backend as a Service后端即服务)。严重或完全依赖第三方应用程序/服务(比如云平台)管理服务器端逻辑和状态的应用程序。在其中,开发人员外包Web或移动应用程序的所有服务端方面,仅需自行编写和维护前端。BaaS供应商为服务器上发生的活动提供预编写的软件,例如用户身份验证、数据库管理、远程更新和推送通知(针对移动应用程序),以及云存储和托管。
Serverles服务器适合于任何事件驱动的各种不同的用例,这包括移动应用、物联网、基于网络的应用程序和聊天机器人等:
Serverless 应用成功与否的评判标准并不是公司规模的大小,而是其业务背后的具体技术问题,比如业务波峰波谷明显,如何实现削峰填谷。一个公司的业务负载具有波峰波谷时,机器资源要按照峰值需求预估;而在波谷时期机器利用率则明显下降,因为不能进行资源复用而导致浪费。
业界普遍共识是,当自有机器的利用率小于30%,使用 Serverless 后会有显著的效率提升。而且,用户无论是自建还是使用普通实例,一般会根据高业务负载购买相关的规格,按固定资源付费。这样在波谷期浪费的资源较多,整体成本较高;如果出现预期外的大业务流量,资源不足又会使业务受损。Serverless 实例能进行快速且独立的扩容和缩容,在快速响应业务变化的同时,合理优化使用成本,助力企业降本增效。
图12 Serverless助力企业降本
对于云服务厂商,在具备了足够多的用户之后,各种波峰波谷叠加后平稳化,聚合之后资源复用性更高。比如,外卖企业负载高峰是在用餐时期,安防行业的负载高峰则是夜间,这是受各个企业业务定位所限的;而对于一个成熟的云服务厂商,如果其平台足够大,用户足够多,是不应该有明显的波峰波谷现象的。
视频处理的后端系统,常见功能需求如下:视频转码、抽取数据、人脸识别等,这些均为通用计算任务,可由函数计算执行。
开发者需要自己写出实现逻辑,再将任务按照控制流连接起来,每个任务的具体执行由云厂商来负责。如此,开发变得更便捷,并且构建的系统天然高可用、实时弹性伸缩,用户不需要关心机器层面问题。
对于企业来说,支持Serverless计算的平台可以节省大量时间和成本,同时可以释放员工,让开发者得以开展更有价值的工作,而不是管理基础设施;另一方面可以提高敏捷度,更快速地推出新应用和新服务,进而提高客户满意度。但是Serverless不是完美的,它也存在一些问题,需要慎重应用在生产环境。
Serverless在请求到来时才运行,这意味着,当应用不运行的时候就会进入 “休眠状态”,下次当请求来临时,应用将会需要一个启动时间,即冷启动时间。如果应用需要一直长期不间断的运行、处理大量的请求,那么你可能就不适合采用Serverless架构。
当采用某云服务厂商的Serverless架构时,就和该服务供应商绑定了,后续再将服务迁到别的云服务商上就没有那么容易了。
使用Serverless Framework时,会遇到很明显的问题:缺乏调试和开发工具。虽然serverless-offline、dynamodb-local 等一系列插件使得问题有一些改善。然而,阅读日志系统来说,仍然是一个艰巨的挑战。
每次调试代码的时候,需要一遍又一遍地上传代码;而每次上传的时候,又不能快速地定位问题,还是得借助分级别记录日志、大数据日志分析等技术。
Serverless很便宜,但是这并不意味着它很简单,比如AWS Lambda的CloudFormation配置就非常复杂,并且难以阅读及编写(JSON格式)。
在云原生的时代,传统中间件技术也演化升级为云原生中间件,云原生中间件主要包括网格化的微服务架构、事件驱动技术、Serverless等技术的广泛应用,其中网格化(Service Mesh)微服务架构和Serverless前面都讲过了,下面介绍一下事件驱动技术以及云原生技术带来的不同点。
事件驱动技术诞生背景:在单体应用中,我们可以利用关系型数据库的特性去完成事务一致性,但是一旦应用往微服务发展,根据业务拆分成不用的模块,而且每个模块的数据库已经分离开了,这时候,要面对的就是分布式事务了,需要在代码里头完成ACID(原子性、一致性、隔离性、持久性)。1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标:一致性(Consistency)、可用性(Availability)、分区容错(Partition tolerance),Eric Brewer 说,这三个指标不可能同时做到,这个结论就叫做 CAP 定理。微服务中,P(分区容忍)是必须要有的,这时剩下的C和A就无法同时做到了;此时一般放弃强一致性(C),通过事件驱动实现最终一致性,来保证系统的AP能力。
以电商系统为例,用户下单必须根据库存来确定订单是否成交,下面对比使用事件驱动前后,服务之间的调用的区别。
图13 服务间调用方式对比
未基于事件驱动的服务调用的缺点:
利用事件驱动实现最终一致性:
基于事件驱动的服务调用的优点:
基于事件驱动的服务调用的缺点:
综上,事件驱动技术是微服务架构中实现最终一致性的重要手段,且一般基于消息队列实现。
微服务架构一般包含下列组件:服务注册发现中心、配置中心、负载均衡、容错处理、API网关、消息队列、运行时监控、链路跟踪等。云原生中间件最大的技术特点是中间件技术从业务进程中分离,变成与开发语言无关的普惠技术,只与应用自身架构和采用的技术标准有关,比如一个PHP开发的REST应用也会自动具备流量灰度发布能力、可观测能力,即使这个应用没有采用任何服务化编程框架。
【服务注册发现中心】和【配置中心】的功能主要致力于解决微服务在分布式场景下的服务发现和分布式配置管理两个核心问题。随着云原生技术的发展,服务发现领域出现了两个趋势,一个是服务发现标准化(Istio),一个是服务下沉(CoreDNS);配置管理领域也有两个趋势,一个是标准化(ConfigMap),一个是安全(Secret)。
【负载均衡】、【容错处理】、【API网关】交由边车服务完成。
【消息队列】是云计算PaaS领域的基础设施之一,主要用于解决分布式应用的异步通信、解耦、削峰填谷等场景。云原生背景下,消息队列提供一种BaaS化的消息使用模式,用户无需预先购买服务器和自行搭建消息队列,也无需预先评估消息使用容量,只需要在云平台开通即用,按消息使用量收费。例如阿里云MaaS(Messaging as a Service)提供的是一站式消息平台,提供业界主流的开源消息队列托管服务,包括Kafka、RabbitMQ、RocketMQ等;也支持多种主流标准协议规范,包括AMQP、MQTT、JMS、STOMP等,以满足微服务、IoT、EDA、Streaming等各种细分领域的需求。
【事件驱动架构】在过去事件驱动架构往往是通过消息队列来实现,事件用消息来传递。进入云计算时代,云厂商提供更加贴近业务的封装,比如Azure提供了事件网格,把所有云资源的一些运维操作作为内置事件,用户可以自行编写事件处理程序实现运维自动化;AWS则把所有云资源的操作事件都用SNS的Topic来承载,通过消息做事件分发,用户类似实现WebHook来处理事件。由于事件是异步触发的,天然适合Serverless,所以现在很多云厂商都采用自身的Serverless服务来运行事件负载,包括阿里云Function Compute、Azure Function、AWS Lambda都和事件处理集成。
DevOps是Development和Operations的组合,重视软件开发人员和运维人员的沟通合作,通过自动化流程来使得软件构建、测试、发布更加迅速和可靠。
DevOps与上述的微服务、容器等技术应用没有直接的关系,可以讲,没有微服务和容器等技术,一样可以朝着自动化的构建、测试和发布流程上行进。但是,长久以来,Devops只是在文化上和流程指导上给出了方向,至于落地的方法论和工具链上,并没有很成功,只是在CI/CD流程的个别环节上独立发展出一些比较成功的产品,例如jenkins及一些自动化测试工具。究其原因,还是在软件应用基础架构上,没有完善的技术支撑和技术体系,软件的运行环境千差万别、软件的部署和维护流程千差万别、软件的形态和架构千差万别,Devops落地需要大量定制化,工具链落地难度很大。
在云原生时代,基于容器的微服务架构定义了云原生应用的标准架构;基于容器和Kubernetes的平台提供了云原生应用的标准发布和运行环境,为DevOps的流行提供了土壤。
持续集成(CONTINUOUS INTEGRATION,CI)指的是开发人员频繁的(一天多次的)将所有开发者的工作合并到主干上。这些新提交在最终合并到主线之前,都需要通过编译和自动化测试流进行验证,以保障所有的提交在合并主干之后的质量问题,对可能出现的一些问题进行预警。持续集成的核心在于通过自动化持续集成工具确保新增的代码能够与原先代码正确的集成。
持续集成带来的好处:易于定位错误、易于控制开发流程、易于Code Review、易于减少不必要的工作。
图14 持续集成
与持续集成相比,持续交付(CONTINUOUS DELIVERY,CD)的侧重点在于交付,其核心对象不在于代码,而在于可交付的产物。与持续集成相比较,持续交付添加了测试Test->模拟Staging->生产Production的流程,也就是为新增的代码添加了一个保证:确保新增的代码在生产环境中是可用的。
持续交付带来的好处:繁琐的部署工作没有了,团队不再需要花费几天的时间去准备一个发布;可以更快的进行交付,这样就加快了与客户之间的反馈环;轻松应对小变更,加速迭代。
图15 持续交付
持续部署(CONTINUOUS DEPLOYMENT)指的是通过自动化部署的手段将软件功能频繁的进行交付。从开发人员提交代码到编译、测试、部署的全流程不需要人工的干预,完全通过自动化的方式执行。这一策略加快了代码提交到功能上线的速度,保证新的功能能够第一时间部署到生产环境并被使用。
持续部署带来的好处:发布频率更快,因为不需要停下来等待发布,每一处提交都会自动触发发布流;在小批量发布的时候,风险降低了,发现问题可以很轻松的修复;客户每天都可以看到持续改进和提升,而不是每个月或者每季度,或者每年。
自动实时的部署上线,是最优的解决办法,但持续部署的要求是团队非常成熟,并且上线前是需要经过QA测试的,所以实际情况下很难实现,一般的团队也很难接受,挑战和风险都很大。
DevOps不仅包括了CI、CD,还有对于文化氛围的构建。DevOps也即是促使开发人员与运维人员之间相互协作的文化。在DevOps文化指导下,团队中将包含了具有不同技能的人员(开发、测试等),并通过自动化测试与发布的手段,更快、更高质量的生产软件。
由于精力有限,这里只列举了阿里云在云原生体系下的相关产品。
产品分类 | 产品名称 | 产品说明 |
容器 | 容器服务Kubernetes版 ACK | 提供高性能可伸缩的容器应用管理能力,支持企业级Kubernetes容器化应用的全生命周期管理。 |
容器服务Serverless版 ACK Serverless | 通过该产品,您无需管理和维护集群即可快速创建Kubernetes容器应用,并且根据应用实际使用的 CPU 和内存资源量进行按需付费,从而使您更专注于应用本身,而非运行应用的基础设施。 | |
容器计算服务 ACS | 以K8s为使用界面供给容器算力资源的云计算服务,提供符合容器规范的算力资源。 | |
容器镜像服务 ACR | 面向容器镜像、Helm Chart 等符合OCI标准的云原生制品安全托管及高效分发平台。ACR支持全球同步加速、大规模/大镜像分发加速、多代码源构建加速等全链路提效,与容器服务ACK无缝集成,帮助企业降低交付复杂度,打造云原生应用一站式解决方案。 | |
弹性容器实例 ECI | Serverless和容器化的弹性计算服务。您无需管理底层ECS服务器,只需要提供打包好的镜像,即可运行容器,与阿里云容器服务无缝对接并仅为容器实际运行消耗的资源付费。 | |
容器服务Edge版 ACK Edge | 一款提供标准Kubernetes集群云端托管,支持边缘计算资源、业务快速接入、统一管理、统一运维的云原生应用平台,能够帮助您轻松实现云边一体化协同。 | |
分布式云容器平台 ACK One | 面向混合云、多集群、分布式计算、容灾等场景推出的企业级云原生平台,支持连接并管理任何地域、任何基础设施上的Kubernetes集群,提供一致的管理和社区兼容的API,支持对计算、网络、存储、安全、监控、日志、作业、应用、流量等进行统一运维管控。 | |
容器服务发行版 ACK Distro | 是阿里巴巴针对异构IaaS环境发布的 Kubernetes发行版,使用者可通过阿里云容器镜像服务ACR 免费获取完整内容并获得社区支持。其核心组件经过阿里云容器服务Kubernetes版ACK和阿里巴巴集团业务场景的大规模生产环境验证和安全检查,具备安全性与可靠性。 | |
微服务 | 企业级分布式应用服务 EDAS | 是一个应用PaaS平台,一站式集成微服务、可观测、任务调度等技术;以专业易用的应用全生命周期管理、流量及容量治理等功能,配合业务视角的验收、资源管控与成本优化能力,助力企业应用架构云原生化升级。 |
微服务引擎 MSE | 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka)、云原生网关(原生支持 Higress/Nginx/Envoy,遵循 Ingress 标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。 | |
应用高可用服务 AHAS | 专注于通过多活容灾(简称MSHA)的功能提高应用高可用能力,提供从流量入口、应用层和数据的故障切换以及故障演练等能力,进行云上业务的同城及跨地域的多活建设,提升稳定性。 | |
Service Mesh | 服务网格 ASM | 是一个统一管理微服务应用流量、兼容Istio的托管式平台。通过流量控制、网格观测以及服务间通信安全等功能,服务网格ASM可以全方位地简化您的服务治理,并为运行在异构计算基础设施上的服务提供统一的管理能力,适用于Kubernetes集群、Serverless Kubernetes集群、ECS虚拟机以及自建集群。 |
Serverless | 函数计算 FC | 是一个事件驱动的全托管 Serverless 计算服务,您无需管理服务器等基础设施,只需编写代码并上传,函数计算会为您准备好计算资源,并以弹性、可靠的方式运行您的代码。 |
Serverless应用引擎 SAE | 是一款零代码改造、极简易用、自适应弹性的应用全托管平台。SAE 让您免运维IaaS和K8s,秒级完成从源代码/代码包/ Docker镜像部署任何语言的在线应用(如 Web /微服务 /Job任务)到 SAE,并自动伸缩实例按使用量计费,开箱即用日志、监控、负载均衡等配套能力。 | |
DevOps | 云效DevOps | 企业级一站式研发协同平台。支持公共云、专有云和混合云多种部署形态,通过云原生新技术和研发新模式,助力创新创业和数字化转型企业快速实现研发敏捷和组织敏捷,打造“双敏”组织,实现多倍效能提升。 |
资源编排服务 ROS | 是一种简单易用的云计算资源自动化部署服务。用户可以通过使用Json/Yaml格式的模版描述多个云计算资源(如ECS、RDS、SLB)的配置、依赖关系等,并自动完成所有云资源在多个不同地域以及多个账户中的部署和配置,实现基础设施即代码。 |
数禾科技以大数据和技术为驱动,为金融机构提供高效的智能零售金融解决方案,服务银行、信托、消费金融公司、保险、小贷公司等持牌金融机构,业务涵盖消费信贷、小微企业信贷、场景分期等多个领域,提供营销获客、风险防控、运营管理等服务。
随着业务的快速发展,风控模型对AI的需求也随之井喷。如何打造更敏捷的AI计算服务,支撑业务高速增长,同时节省资源成本,是摆在数禾科技面前的一大难题。
经过调研,数禾科技与阿里云云原生团队深度合作,联合打造全新的数禾AI推理服务平台,整个平台基于阿里云 Serverless 容器服务ASK构建,无需购买任何K8s节点即可直接部署推理服务容器应用,也无需对K8s集群进行节点维护和容量规划。同时,根据推理服务的实时请求量动态创建和销毁POD,资源成本大幅下降,服务的可用性也得到了很好的提升。此外,通过ASK Knative服务,有效解决了数禾模型的灰度发布和多版本并存问题,大幅提升了模型迭代上线的效率。
目前,该系统已上线部署数百个AI 模型服务,每天能够提供数亿次查询决策服务,ASK的实时弹性扩展能力帮助数禾节约资源成本约60%,同时平稳地应对了诸多运营活动等突发峰值场景,整个云原生部署和发布系统将数禾的平均部署周期由之前的1天缩短至0.5天,有效加速了商业化应用的迭代进程,为金融业务的拓展增长提供了强有力的支撑。
在2018年初,智联已经开始了容器化改造,最终实现了业务的快速迁移和扩展等能力。在2021年智联继续深度思考,以自身业务特点出发结合云原生技术优势,确定了Serverless容器混合云是系统进一步演进的最佳技术方案。
智联招聘在业内率先完成全面容器化改造,并与阿里云联合设计“分布式云容器平台 ACK One + IDC统一调度方案”。在应对春招期间高峰流量阶段,通过ACK One统一集群管理,IDC容器集群结合云上资源以及统一可观测性能力、秒级弹性能力,同时兼容线下调度器策略达到成本最优解,有效解决春招期间面临的系统稳定性、资源量预估困难、运维难度大等问题。
使用混合云的方式作为计算平台,不必因为业务突发增长的需求而一次性投入大量资金成本用于采购服务器及扩充机柜。在公共云上可以做到随用随付,对于一些创新业务想做技术调研非常方便,按量付费,大幅减少了试错的成本。在效率方面,借助混合云架构深度集成,方便研发人员完成一站式研发、运维工作,整个持续集成可以做到分钟级。
智联招聘的云原生转型助力了公司的快速变革,云原生架构、DevOps理念的实践,使得智联招聘的开发、测试、运维等工作能够更加协同和高效。此外,云原生架构的高可用性、灵活弹性、自动化特性,也使得智联招聘具备更好的容灾恢复能力和业务可靠性,保证业务在高峰期时能够快速响应和扩展。
1.阿里云云原生架构白皮书
2.容器原理架构详解-https://blog.csdn.net/shyeang/article/details/113059045
3.分布式应用多运行时架构-https://cloud.tencent.com/developer/article/1957270
4.微服务架构:利用事件驱动实现最终一致性-https://www.51cto.com/article/604138.html
5.微服务、容器、云原生、Kubernetes、SOA、PaaS平台、Devops 之间的关系-https://zhuanlan.zhihu.com/p/74483850
6. MSE Serverless 正式商用-https://zhuanlan.zhihu.com/p/671148625
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。