网关两地三中心的实践与总结


轻舟网关两地三中心整体技术方案

背景概述

轻舟云原生网关作为轻舟平台核心组件,负责承接集群内外的所有入口流量,并对其进行转发和治理。而两地三中心作为一种容灾能力相对比较完整的架构,有助于提升产品的稳定性,具备业务容灾能力。因此本次方案将实现网关产品的两地三中心能力,并具备区域路由优先和多集群服务发现等产品能力。

需求说明

功能需求

  • 区域路由优先

    网关基于区域匹配信息进行流量优先级划分。

  • 多集群服务发现

    控制面能够发现多集群中的服务实例。

非功能需求

  • 多集群配置下发

    API Plane支持下发配置到多个集群中。

  • 数据一致性保障

    通过定时补偿任务达到数据最终一致性的目标

  • 基于K8s Informer缓存资源数据

    API Plane通过K8s Informer机制缓存资源数据,避免通过k8s api server全量拉取资源。

目标和非目标

目标
通过阅读该文档,明白网关两地三中心项目的设计思路及方案,并能通过该方案进行相关落地。

非目标
阅读人员需要熟悉网关整体架构,主要面向开发和运维人员。

系统指标

功能指标

实现两地三中心多集群部署,保障每个集群的网关代理组件的无状态性。

提供区域路由优先的产品能力,保证流量优先转发到当前集群。

提供多集群服务发现能力,实现多集群服务的统一纳管。

提供多集群配置下发能力,保证多集群网关配置的一致性。

支持灵活部署,资源有限的场景下,可以支持数据面高可用,控制面单集群部署。

性能指标

保证两地三中心部署模式下,流量转发延时和单集群延时保持一致。

多集群下每个网关都可以承接所有流量,QPS理论上可以n倍于单集群网关。

功能架构设计

区域路由优先

两地三中心模式下,可以通过地区(region)、可用区(zone)、集群(cluster)三元组定义网关和业务服务实例的地域信息。

  • 地区:代表较大的地理区域,例如杭州。一个地区通常包含许多可用区域。通过node标签mlha.skiff.netease.com/region确定服务的地区。
  • 区域:代表一个可用区,例如滨江。一个区域内通常会部署多个集群。通过node标签mlha.skiff.netease.com/zone确定服务的可用区。
  • 集群:代表服务所在的K8S集群,通过node标签mlha.skiff.netease.com/cluster确定服务的可用区。

例如:【杭州、滨江、集群A】,【杭州、余杭、集群B】

区域路由优先.png

若开启地域区域路由优先功能,网关代理(Envoy)会基于如下规则对流量进行转发:

1.优先将请求转发到当前集群中的服务。

2.若网关所在集群的服务不可用,则将流量转发到当前可用区中其他集群的服务。

3.若网关所在可用区的服务都不可用,则将流量转发到当前区域中其他集群的服务。

4.若网关所在区域的服务都不可用,则将流量转发到其他区域中的服务。

技术架构设计

网关两地三中心方案是在现有网关组件的基础上,通过多集群配置下发与监听、多集群服务发现等技术实现网关集群无状态水平扩展,每个集群都包含完整的网关组件。

整体技术架构

网关总体架构.png

网关的整体架构如图所示,主要可以划分为如下4部分:

  • 控制面组件

    控制面组件负责配置管理和服务发现,具体包括如下组件:

    Front:前端组件,负责轻舟网关的可视化展示。

    GPortal:轻舟网关控制台,和前端组件交互,负责配置管理和可视化。

    API Plane:资源管理组件,和K8s api server交互,负责配置资源(CRD)的创建。

    Istio Pilot:网关团队基于Istio开源控制面Pilot进行增强,主要负责与数据面Envoy的交互,包括服务以及配置等信息通过xDS协议与数据面进行交互。

    Mesh Registry:服务发现组件,通过MCP协议从注册中心获取服务实例,支持的注册中心包括Nacos、Kubernetes、Eureka、Zookeeper。

  • 数据面组件

    网关代理组件(Envoy Proxy),负责流量治理和转发,当网关使用集群限流功能时,需要额外部署Rate Limit组件。

多集群架构

网关多集群.png

网关多集群水平扩展后如图所示,每个集群都包含完整数据面和控制面组件,其中数据面组件包含完整的服务和配置信息,可以完整承接网关流量,上层通过Nginx进行流量负载均衡。

持久化数据依赖说明

网关依赖的持久化组件如下:

Mysql(强依赖):持久化流量治理相关配置,用于视图管理和资源下发。

Etcd(强依赖):K8s Api Server依赖组件,每个K8s集群都单独维护一个Etcd,用于存储相关Istio配置资源,Istio监听Etcd资源并下发配置给挖宝方法代理Envoy。

Redis(可选):用于缓存和限流插件。

Prometheus(可选):用于指标数据上报和统计。

部署架构设计

两地三中心部署架构.png

网关两地三中心部署方案如上所示,其中区域1为当前提供服务的区域,通过SLB将流量负载均衡到可用区A和B中;区域2为异地区域,区域1中的mysql配置数据会定时同步到可用区C的灾备中间件中。当进行故障切换时,需要执行如下两步骤:

1.同步最新的mysql配置数据到灾备数据库中。

2.基于同步后的灾备数据,全量发布网关资源(服务、路由、插件)。

容灾方案设计

同城单机房故障应对及影响

平台侧

SLB感知机房故障,自动将流量切换到同城可用机房,不会对流量产生影响。

业务侧

部署在本机房中的业务服务将无法接受流量,因此推荐用户将服务分散部署在多个集群中,避免机房故障导致服务实例不可用。

同城双机房故障应对及影响

平台侧

故障期间会导致网关不可用,需要人为切换到灾备机房,切换后需要同步最新数据到灾备数据库中,并进行全量资源发布后可正常提供服务。

业务侧

当前可用区中的服务将不可用,灾备机房中的服务可以正常接受流量。

关键方案设计

多集群读写

API Plane多集群配置下发.png

在网关下发配置流程中,GPortal负责落库,API Plane负责下发配置到K8S API Server。在两地三中心场景下,API Plane还需要提供多集群配置下发的能力。在具体实现层面,api plane需要指定主机群和从集群配置,其中主机群为当前集群,从集群为其他集群。

clusters: 
    master:
      k8s-api-server: ""
      cert-data: ""
      key-data: ""
      ca-data: ""
    test209:
      k8s-api-server: ""
      cert-data: ""
      key-data: ""
      ca-data: ""
  • 读操作

    对于读操作API Plane只从主集群中读取配置,若主集群crash,会导致pass平台视图展示失败,需要通过Nginx进行切换;

  • 写操作

​ 写操作包含GPortal落库和API Plane多集群配置下发两个操作。本方案优先API Plane下发配置,并且只要主集群配置下发成功,就返回成功,GPortal执行DB操作。对于从集群则通过子线程异步进行更新,若更新失败导致数据不一致,则需要通过定时补偿任务进行修正,保证数据的最终一致性。

定时补偿任务

本方案通过API Plane执行定时补偿任务对数据进行修正。其中每个API Plane组件都会校验本集群中CR和DB数据是否一致,若出现不一致,则以DB数据为准更新本集群CR。针对资源类型的不同,API Plane采用版本号校验和内容校验两种方式。

版本号校验:

通过对比DB中版本号和CR中版本号是否一致来判断配置是否成功下发,优先采用该方式,涉及的资源包括Destination Rule、Virtual Service和GatewayPlugin。

具体步骤:

1.相关表添加版本号标识符version字段,数据创建时初始化为0,之后每次修改都自增。

2.API Plane下发配置时需要带上版本号,映射到资源metadata中的hango.data.version字段。

3.定时触发校验校验任务比较两种的版本号是否一致,若版本号一致,则表明配置正常下发了;否则需要基于DB中的数据进行修正,修正场景如下:

场景 数据库 CR 操作
配置未更新 version=2 skiff.nsf.data.version=1 更新CR
配置未创建 version=2,enable=true NULL 创建CR
禁用相关功能 enable=false NULL 不操作
数据库更新失败 version=2 skiff.nsf.data.version=3 更新CR
配置未删除 NULL skiff.nsf.data.version=1 删除CR

上述为版本号校验的基本步骤,存在下面三种情况需要特殊处理:

  • 双表映射相同资源

    解释:两个表映射到相同资源

    场景:

    1.apigw_service_proxy和apigw_envoy_health_check_rule映射Destination Rule资源。

    2.apigw_route_rule_proxy和apigw_gportal_dubbo_info映射Virtual Service资源。

    解决方案:只在主映射表(apigw_service_proxy, apigw_route_rule_proxy)添加版本号,从映射表更新配置时,需要更新主映射表的版本号。

健康检查version.png

  • 同表多记录映射相同资源

    解释:同一个表中的多条记录映射到相同场景

    场景:路由级插件apigw_envoy_plugin_binding表中相同路由下的多个插件映射到同一个GatewayPlugin资源

    解决方案:多条记录维护相同的版本号,具体步骤如下:

项目级插件流程.png

内容校验:

直接比较CR资源和DB中的详细内容,该方式主要应用于内容相对简单的场景,具体指Service Entry资源。该资源只包含静态服务地址信息。

API Plane资源监听

定时补偿任务需要全量拉取K8s 资源进行校验,数据量过大时查询较慢(1w+数据需要查询3分钟),导致api server压力过大,同时导致并发问题影响补偿任务的正确性。为了解决上述问题,本方案通过K8s Informer机制实现资源缓存。

K8s informer.png

K8s Infomer机制的核心是List/Watch,Api plane 在全量拉取资源时会使用Informer中的Lister()方法,从本地缓存中(store)获取,而非直接请求Kubernetes API。而本地缓存则通过watch机制进行实时更新。具体原理可参考Kubernetes Informer详解

Istio多集群服务发现

Istio多集群监听.png
该部分主要基于Istio提供的多主架构部署方案实现,需要保证多集群处于单一的互通网络,任意负载间网络可达。该方案中每个集群中的Istio都会监听所有集群K8s API服务器的服务端点,从而实现获取所有集群中的服务实例。

Mesh Registry也具备多集群监听的能力,实现方式参照Istio,因此不进行额外说明。

监控、告警及运维

遗留或待解决问题

讨论及更新记录


文章作者: xyl
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xyl !
评论
  目录