58同城深度学习推理平台基于Istio的云原生网关实践_推理_架构_网关

SACC中国系统架构师大会

2022年10月27日~29日,由IT168旗下ITPUB企业社区平台主办的第十五届中国系统架构师大会(SACC2022)在云端进行网络直播。本届大会以“激发架构性能 点亮业务活力”为主题,按照技术主线分为传统架构线(高可用架构、云架构、分布式存储)、智能运维线(DevOps、安全设计、网络架构、数据中心等)、云原生技术线(云原生架构、微服务、容器、低代码)、前沿技术线(5G、DDD、知识图谱)以及行业架构应用主线(金融行业与制造业),云集国内CTO、研发总监、高级系统架构师、开发工程师和IT经理等技术人群,力争为各路豪杰奉献一场技术的饕餮盛宴。

58同城TEG-AI Lab后端资深工程师魏竹斌受邀出席,于2022年10月28日16:00-16:50在云架构设计与实践专场下分享了《58同城深度学习推理平台基于Istio的云原生网关实践》。

本文根据分享实录整理而成,欢迎大家阅读分享。

01

导读

AI正在驱动行业变革,为加速58同城AI应用的落地,AI Lab自2017年9月开始构建机器学习平台WPAI(Wuba Platform of AI),支持机器学习算法一站式开发,以提高AI工程师的研发效率。

图1 AI Lab产品能力

WPAI包括基础计算平台、算法应用平台两部分:

基础计算平台集中管理GPU、CPU、NPU硬件资源,支持机器学习模型离线训练和在线推理,在线推理服务支持自动扩缩容(弹性推理服务),离线训练作业和在线推理服务支持混合部署(离在线混部)。开发者可以向平台申请离线、在线资源,使用机器学习框架开发模型,打造自己的机器学习服务。

为了进一步提高AI工程效率,我们在基础计算平台之上继续打造了算法应用平台,包括NLP算法平台WubaNLP、图像算法平台凤凰(由58技术委员会AI分会基于WPAI基础计算平台协同共建)、排序学习平台(应用于搜索、推荐、广告系统)等。算法应用平台直接集成了相应领域下的常用模型,以Web的方式提供应用,开发者只需要在Web界面做相应配置即可完成训练和推理,大大提高开发效率。

在AI平台之外,我们还构建了AI周围子系统,如向量检索平台vSearch、AB实验平台日晷,以进一步提高AI工程效率。

WPAI机器学习平台是AI应用的底座,我们基于WPAI打造了灵犀智能语音语义平台、MAI智能营销引擎、智能写稿等,感兴趣可以添加58技术小秘书(jishu-58)咨询。

02

背景

展开全文

深度学习推理平台在架构上属于WPAI的子平台,旨在将算法人员使用深度学习框架训练出来的模型部署到生产环境,提供高性能、高可用的在线推理服务。总体架构如下图所示,底层依托于Kubernetes和Docker,实现了对GPU/CPU等资源的统一调度和管理,网关侧搭配Istio实现了推理服务发现和流量治理功能;算法层集成了TensorFlow、PyTorch和PaddlePaddle等优秀的深度学习框架,同时也支持用户自定义服务;应用层从模型管理、部署、推理加速和服务高可用保障等方向都提供了一系列功能。支撑了58同城在图像、NLP、语音、搜索、推荐、广告、风控领域内的各类AI应用,目前已上线模型数1000+,峰值节点数4000+,日均流量30亿。本文主要介绍深度学习推理平台推理架构的演进过程,以及新架构下在流量治理建设和可观测性建设方面的设计细节。

图2 深度学习推理平台架构

03

推理架构1.0

3.1推理架构1.0设计背景

每一种系统架构的设计都有其特定的历史背景,我习惯从需求驱动和技术支撑两方面去分析。

在WPAI上线之前,为支撑业务的快速发展,实现AI应用的快速落地,集团各业务部门只能选择各自为战,独立开发推理相关功能,但因为缺乏平台化管理、监控等能力,难免会出现研发、运维效率低下的问题;再加上算法与工程没有明确边界,导致算法同学深陷工程泥潭,无法将有限的精力聚焦在模型优化上,模型迭代效率也不尽如人意,所以集团对AI平台化能力有着迫切的需求。

从技术支撑角度看,由于K8S集群内外网络是不联通的,所以我们需要在集群边缘架设网关来打通整套推理流程,而当时集团自研的Java系RPC框架-SCF在经过多次版本迭代和集团多条业务线在生产环境的检验后,已经具备成熟的服务治理能力(如超时、限流、监控、告警等)、强大的横向扩展能力及高可用保障,并且对业务方来说基本没有学习和使用成本,所以为了满足业务方快速接入的需求,我们选用SCF作为网关实现搭建了我们1.0版推理架构。

图3 SCF整体架构

3.2推理架构1.0设计实现

推理架构1.0中的SCF网关属于传统API网关实现,下面我将使用当下比较流行的数据面和控制面概念对其进行描述。

控制面侧主要包括三大模块:

1、向下连接K8S集群,通过K8S List/Watch机制实现了服务注册发现功能,基于Endpoints构建了面向模型的、细粒度的gRPC连接池。

2、向上连接AI管理平台,通过WConfig(58自研配置中心)实现模型运行时参数的实时同步功能,例如超时时间、限流阈值等。

3、基于WOS(58自研对象存储服务)打造了协议转换jar插件中心。这里需要着重解释下:因为SCF网关无法透传gRPC请求,这要求我们在网关内部将每一个SCF请求转换为gRPC请求后,再转发给后端模型服务,返回数据同理。为实现这一功能,平台提供了标准协议转换接口,算法人员需要在模型上线前基于平台提供的接口实现模型特有的请求和返回数据数据转换逻辑,打成jar包后再通过平台管理界面上传到插件中心。

数据面侧则围绕服务治理相关功能打造了请求处理的Pipeline:包括鉴权、秒级限流、协议转换jar包热加载(收到模型第一次推理请求时通过自定义类加载器加载jar包)、Request/Response协议转换、加权负载均衡、流量转发、日志与异常处理等功能。

图4 推理架构1.0实现

3.3 推理架构1.0不足

推理架构1.0的上线,很好地解决了集团在线推理平台化能力缺失的问题,解耦了算法同学和工程同学的工作职责,提高了算法迭代和工程研发的工作效率。但随着接入方不断增多,业务方模型迭代需求的增加,1.0架构逐渐暴露出一些不足:

业务接入角度:协议解析Jar包的编写和上传,使得接入流程稍显复杂,增加了算法人员模型调试成本,而且接入方式单一,不支持HTTP方式接入。

服务性能角度:一方面SCF与gRPC协议互转会增加推理耗时;另一方面,SCF网络通信层是基于Netty实现的,Netty会给每一个SocketChannel分配一定的缓冲区(ByteBuffer)用于数据的读取,缓冲区大小直接影响服务的性能(分配过大会增加GC的回收压力,分配过小又会触发扩容,进而执行内存拷贝操作)。在Netty实现中,提供了一种“可预测性”的缓冲区分配机制来解决这个问题(核心实现参见io.netty.channel.AdaptiveRecvByteBufAllocator class),然而这套机制对size较大请求不太友好,例如图片美化类推理场景,当输入图片的size超过1M的时候,缓冲区会扩容到16M,所以SCF客户端连接数直接决定服务端JVM老年代的内存占用情况,随着接入规模增加会因为GC问题导致推理性能抖动。

开发运维角度:网关实现与第三方库紧密耦合,集成新功能或第三方库升级都需要对网关进行整体升级,成本较高(此处不得不提Log4j)。

04

推理架构2.0

4.1 Istio云原生网关

为了解决1.0推理架构这种传统网关实现所暴露的问题,我们决定升级推理架构,拥抱云原生网关Istio。Istio的定义关联甚广,快速了解Istio最好的方式就是从它的诞生时间线入手:

2012-2013年移动互联网开始兴起,企业对服务迭代效率提出了更高的要求,应用程序架构开始从单体逐渐转向微服务,服务规模开始初步增长。

2013年Docker开源,提供了更轻量级的虚拟化方案,解决了应用封装、隔离和移植性问题。

2014年Google宣布开源Kubernetes,为容器编排和生命周期管理提供了标准解决方案,集群向大规模、分布式快速发展,服务数量激增,拓扑链路复杂。

2016年Buoyant公司CEO William Morgan首次提出ServiceMesh定义:服务网格是一个基础设施层,用于处理服务间通信;云原生应用有着复杂的服务拓扑,服务网格保证请求在这些拓扑中可靠地穿梭;在实际应用当中,服务网格通常是由一系列轻量级的网络代理组成的,它们与应用程序部署在一起,但对应用程序透明。并同年发布第一代ServiceMesh产品—Linkerd。

2016年Envoy代理开源,在Lyft作为边缘代理得到生产级验证,作为可编程代理时代里程碑产品,其定义的xDS(x Discovery Service)协议更是在云原生场景中大放异彩。

2017年Google、IBM 和 Lyft 联合宣布开源Istio ,确定了数据平面和控制平面的组成以及 Sidecar 模式,被称为第二代ServiceMesh产品,ServiceMesh理念深入人心。

2018年云原生计算基金会(后简称CNCF)重新定义云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。

图5 Istio诞生时间线

总结而言:Istio是一个与K8S紧密结合的、适用于云原生场景的、ServiceMesh形态下的、用于服务治理的开放平台,提供流量管理、安全性、可观测性三大核心功能。

Istio因为ServiceMesh而名声大噪,但它又不仅仅是一个ServiceMesh产品,因为相较于Linkerd而言,它默认提供了K8S Ingress的解决方案(基于可编程代理Envoy)来处理集群内南北向流量,而且相较于业界其他类型的Ingress Provider(例如Kong),Istio具备以下优势:

优质的基因。Envoy作为边缘代理在Lyft公司中得到生产验证,随后成为CNCF第三个毕业的项目;CNCF正式将Service Mesh写入云原生第二版定义 ,Istio也于近期成为 CNCF 孵化项目;控制面和数据面隔离架构,搭配xDS动态配置同步方案。

全面的能力。包括强劲的代理性能,基于c++实现了全异步事件机制驱动;丰富的流量治理能力,如请求路由、负载均衡、超时、限流、熔断等,开箱即用;强大的可观测性支持,具有详细的监控指标,完整的访问日志;灵活的可扩展性,可以基于Filter、Lua和WASM方式增强功能。

强劲的势头。2020年CNCF中国云原生调查显示:去年排名第四的Envoy近1年内使用量明显上升,从15%的份额增长到29%,超过F5和HAProxy跃居第二;Istio/Envoy在谷歌、微软、阿里、腾讯等等国内外头部公司大规模落地应用,已然成为服务网格/数据面代理的事实标准。

鉴于上述种种,我们最终选择基于云原生网关Istio来打造我们的2.0版推理架构。

4.2 推理架构2.0实现

推理架构2.0实现如图6所示,可分为模型服务层、网关层和业务应用层。

图6 推理架构2.0

模型服务层同1.0推理架构相比并无修改,因为基于以下几点原因考虑,我们没有启用Istio的Sidecar方案:

1、在线推理属于典型的端到端场景,没有东西向流量需求。

2、Istio的Sidecar方案是基于iptables实现请求转发功能的,会有一定的性能损耗,影响推理性能。

3、大量的Sidecar容器对于集群资源来说也是不小的负担,而且会增加运维管理的复杂度。

架构设计,复杂是万恶之源,虽然Istio的Sidecar方案是开箱即用的,但我们也要按需使用。

网关层则是Istio的原生架构,Istio将控制面Istiod和数据面Ingress Gateway拆分成两个进程独立部署以保证资源隔离,互不影响。控制面Istiod包括三大模块:Citadel通过内置的身份和凭证管理实现了强大的服务到服务和最终用户身份验证,可以在网格中启用授权和零信任安全性;Galley是 Istio 配置验证、提取、处理和分发组件;Pilot为数据面代理提供服务发现、流量管理功能和弹性。数据面Ingress Gateway则又包括Envoy和Pilot-agent两部分,Envoy具体执行流量代理功能,而Pilot-agent 则负责为Envoy生成静态配置文件及Envoy生命周期管理,Pilot-agent就像是Envoy的"Sidecar"。总体来说,网关层中控制面向下感知集群内节点运行状态变化,向上通过标准接口接收应用层对网关行为配置的变更,再对所有信息进行整合后,通过标xDS协议实时推送给数据面;数据面依据这些信息来决定如何管理用户流量,例如执行负载均衡,限流熔断等策略。两者各司其职,真正做到了高内聚、低耦合。

业务应用层又可分细分为数据面和控制面。数据面侧为了方便用户的接入及后续流量的管理,我们以部分为粒度做了多租户的隔离,通过域名+ 58DNS + CLB的组合实现了网关的负载均衡和高可用;在控制面侧,我们封装了K8S Manager Service做为业务操作K8S+Istio资源的统一入口,标准化了查询和变更行为。K8S Manager Service向上对接各种业务场景的调用,例如在web页面修改了模型推理超时配置等场景。

4.3 推理架构升级应用效果

通过此次架构升级,实现了推理平台从性能、稳定性、易用性方面的全面提升。推理耗时相对于1.0架构减少了50%以上;数据面和控制面从部署层面实现资源隔离,使得服务更加稳定;Istio提供的丰富、开箱即用的流量治理功能,也极大地方便后续开发、运维工作。

05

2.0架构下流量治理能力建设

从网关角度出发,客户端流量通常具有不可控、不均衡等特点,而集群内工作负载的流量处理能力虽然可量化但却并不稳定,作为集群流量的统一出入口,网关的流量治理能力不可或缺。在1.0推理架构下,我们借助SCF服务分组能力实现了不同业务线间租户隔离功能,借助SCF服务管理平台提供了服务监控和告警功能,通过多次版本迭代,在SCF网关内集成了灰度发布、A/B Test、推理超时、秒级限流、节点动态加权负载均衡等功能,保证了推理服务的稳定性,那在2.0推理架构下该如何实现?再者,离在线混部、推理服务自动扩缩容功能的应用使得服务节点上、下线操作变得频繁,如何保证上、下线期间请求不受影响?下面就将借由网关多租户隔离、自适应限流等功能的实现来展示下Istio流量治理的应用细节。

5.1 Istio流量治理基础-声明式API

声明式API,其实就是K8S提供的CRD扩展,Istiod中Pilot模块通过List/Watch机制监视所有CRD资源的变更,并将最新的配置整合后同步到数据面代理。在Istio内部定义了上百种CRD,我们简单介绍其中最常用的四个:

Gateway:抽象网关在L4-L6层负载均衡属性,例如暴露端口、协议等。

VirtualService:配置L7层流量路由规则,可以在流量端口、header 字段、URI 等内容上设置匹配条件,将流量到路由到适当的目标,同时还可以使用路由规则在流量上执行特定操作,例如添加删除header、重写URL、为请求设置重试策略等。

DestinationRule:定义目标服务或其子集,以及调用转发到目标服务或其子集时的流量策略,例如负载均衡策略、熔断器设置等。

EnvoyFilter:Istio插件机制,定制Envoy请求处理逻辑,例如服务Metrics统计、限流等。

在图7的例子中,Gateway、VirtualService、DestinationRule三种CRD通过name或label关联到一起,意思是将所有请求*search.wpai.58dns.org:8866并且header包含taskid=666信息的流量通过轮训的方式路由到k8S中名称为service-666的服务所包含的工作负载上。

图7 声明式API架构

5.2 网关多租户实现-Gateway拆分

Istio中,Gateway可以部署任意多个,可以共用一个,也可以每个租户、namespace单独隔离部署。为了减少网关故障爆炸半径,在保证推理质量的同时兼顾网关资源使用率,我们综合考虑了业务线特征和流量特征,将网关集群与namespace之间按照1:1和1:N关系进行了拆分。如图7是一个网关拆分的简易示例图,其中test和search namespace都单独部署了一套网关集群,而其余的namespace则共用另一套网关集群。

图8 网关拆分示意图

5.3 自适应限流实现

Istio在Gateway侧默认提供了全局限流和本地限流两种限流方案。全局限流需要访问外部限流服务,在我们高并发测试case中,性能表现差强人意,所以我们选择了本地限流方案。本地限流是基于Envoy内部提供的令牌桶算法实现的,通过EnvoyFilter对外提供配置接口,限流配置最小粒度为route(路由),对应K8S中Service的概念,在我们推理场景下即为任务。但是在弹性扩缩容运行机制作用下,任务副本数会随着流量和自身负载的变化而变化,而任务所能承载的总QPS是由副本数*单副本QPS计算而来,所以为了达到精准限流的效果,我们实现了自适应限流功能,核心逻辑包含以下两步:

1、基于平台可观测体系监测任务画像的变更,此处主要指任务副本数。

2、将副本变更事件经过防抖动处理后,转换得到任务总QPS,然后通过请求K8S Manager Service来修改EnvoyFilter中任务的限流配置。

图9 自适应限流方案

Istio在Gateway侧默认提供了全局限流和本地限流两种限流方案。全局限流需要访问外部限流服务,在我们高并发测试case中,性能表现差强人意,所以我们选择了本地限流方案。本地限流是基于Envoy内部提供的令牌桶算法实现的,通过EnvoyFilter对外提供配置接口,限流配置最小粒度为route(路由),对应K8S中Service的概念,在我们推理场景下即为任务。但是在弹性扩缩容运行机制作用下,任务副本数会随着流量和自身负载的变化而变化,而任务所能承载的总QPS是由副本数*单副本QPS计算而来,所以为了达到精准限流的效果,我们实现了自适应限流功能,核心逻辑包含以下两步:

1、基于平台可观测体系监测任务画像的变更,此处主要指任务副本数。

2、将副本变更事件经过防抖动处理后,转换得到任务总QPS,然后通过请求K8S Manager Service来修改EnvoyFilter中任务的限流配置。

图9 自适应限流方案

5.4 无损上线实现-模型预热

在线推理场景下,新节点会在首次收到推理请求时,才将模型文件加载到内存/显存中,该过程耗时较长,当流量较高时就会导致大量请求阻塞、响应超时甚至资源耗尽最终宕机。为了达到节点无损上线要求,我们提供了模型预热功能,可在任务节点服务发布之前通过预热流量提前触发模型加载流程。

图10 模型预热实现方案

首先,考虑到不同的模型对于预热时长的要求不一样,我们引入了K8S提供的Startup探针和Readiness探针,其中Readiness探针决定容器服务发布(探针检测成功)和下线时机(探针检测失败),Startup探针负责检测容器服务是否启动成功,并且只有Startup探针检测成功后,Readiness探针才会启动。两个探针的可配置属性相同,这里主要利用了initialDelaySeconds这一属性,在Startup探针中表示容器启动多长时间后探针开始检测,在Readiness探针中则表示Startup探针检测成功多长时间后探针开始检测,所以通过将Readiness探针中的initialDelaySeconds属性设置为预热时长,即可实现服务启动到服务发布间隔时长的精准控制,业务方可按需配置预热时长,做到充分预热。

再者,不同模型对于输入、输出格式要求也各不相同,为此我们对线上模型及推理请求进行整理后抽象出一套模型配置文件,基于策略模式思想,依靠配置文件打造了模型专属的预热客户端,算法同学只要按规定上传配置文件后,即可在服务启动之后,在服务内部发送预热请求,提前触发模型的加载逻辑。

图11 模型预热配置

06

2.0架构下可观测性建设

可观测性一词来源于控制理论,是指系统可以由其外部输出推断其内部状态的程度。随着IT行业在系统监控、告警、问题排查等领域的不断发展,也逐渐将其抽象形成了一整套可观测性工程体系,主要包括三部分内容:数据模型、产品工具、观测能力。其中数据模型是可观测性建设基础,主要包括以下三种:

指标(Metrics):是一段时间内记录的各个维度的量化信息,用来观察系统的某些状态和趋势。

日志(Logs):是带有时间戳的、结构化或非结构化的、对程序运行过程中目标事件的记录。

链路追踪(Traces):是请求从开始到结束完整生命周期内调用链路的记录(主要用在微服务场景)。

图12 可观测性架构

可观测性是Istio的核心功能之一,内部提供了丰富的生态支持,但是因为对网关来说最重要的服务指标(例如延迟、流量、异常量等),Istio需要借助Sidecar才可以生成,所以我们并没有使用Istio提供的指标生成和采集方案,而是基于Istio的访问日志打造了自己的可观测性建设方案,如图13所示:

图13 2.0架构下可观测建设方案

网关结构化(json)访问日志及推理服务非结构化日志皆从磁盘采集并发送到对应Kafka,后借助ELK组件实现传输、存储及可视化,图14为网关访问日志可视化示例。

监控指标包括服务(流量)监控指标和资源监控指标。服务监控指标使用Kafka中网关结构化日志为数据源,通过流式计算引擎Flink计算得到维度丰富(基础指标+二次加工指标)、层级多样(部门级、任务级、副本级等)、跨度灵活(分钟级、秒级)的服务监控指标,并同时sink到ES及Kafka中;资源监控指标由cAdvisor采集计算,Prometheus负责传输和存储,同时为了构建实时任务画像,我们通过Prometheus-Kafka-Adapter将所有资源监控指标实时同步到了Kafka中。

监控指标通过Grafana大盘实现查询、可视化工作,并为监控报警、服务治理和弹性扩缩等功能提供数据支撑。

图14 网关访问日志可视化效果展示

图15 推理服务监控指标效果展示

07

总结

本文主要介绍深度学习推理平台推理架构的演进过程,以及新架构下在流量治理建设和可观测性建设方面的设计细节。未来我们持续跟进K8S、Istio等基础设施提供的新特性,丰富平台功能,提升推理性能;持续完善平台可观测体系建设,让运维更智能化。

参考文献:

[1] Pattern: Service Mesh()

[2] Istio官方文档()

[3] Beyond Istio OSS —— Istio 服务网格的现状与未来()

[4] Service Mesh Comparison: Istio vs Linkerd()

[5] 2020年CNCF中国云原生调查()

[6] Hango-云原生网关实践,为何选择Envoy()

[7] 云原生网关的可观测性体系实()

作者简介:

魏竹斌,58同城TEG AI Lab AI平台部后端资深工程师 。2020年7月加入58同城,目前主要负责深度学习推理平台和vSearch向量检索平台相关建设工作。

特别声明

本文仅代表作者观点,不代表本站立场,本站仅提供信息存储服务。

分享:

扫一扫在手机阅读、分享本文