作者: 魁予

如今有越来越多的企业开始采纳云原生理念进行运用架构转型。而 K8s 和微服务是云原生的两大支柱,随着云原生浪潮而被广泛运用。

对大都运用而言,供给对外服务的任务并不会改动,比较于原来的单体运用,微服务架构下的运用的服务出口更多,办理更繁琐,微服务网关也应运而生;而 K8s 也供给了多种方法来露出运用的服务,各种 Ingress 完成百家争鸣。面临众多技术计划,咱们怎么做出合理的挑选,躲避潜在风险,本文将给出一些选型建议,供大家参阅。

云原生网关根本概述

K8s 中服务对外拜访的方法

关于布置在云服务器上的运用,一般运用负载均衡软件或服务(如 SLB)来供给高可用的服务。K8s供给了依据 Service 的服务发现机制,用户经过将一批相同特性的 Pod 绑定到一个 Service,能够供给安稳的 VIP(虚拟IP)或域名供集群内拜访,并由 kube-proxy 组件依据 ipvs 或 iptables 完成 Pod 拜访的负载均衡。当需求供给服务对外拜访时,需求运用 NodePort 或 LoadBalancer 类型的 Service。

从 Nginx Ingress 窥探云原生网关选型

默许情况下,NodePort 会为服务在每个 K8s 集群的节点上分配一个节点端口,运用节点的 IP 地址和指定的节点端口能够从集群外部拜访到服务后端的 Pod。用 NodePort 的方法露出服务时,因为客户端装备的是节点的 IP 地址和端口,即使 Service 供给了负载均衡的才干,其安稳性也会受对应节点的影响。在客户端拜访服务时,设置多个 K8s 集群节点的 IP 和服务 nodePort 端口,并装备合适的负载均衡和重试战略,才能够防止单点故障。

K8s 一起供给了 LoadBalancer 的 Service,客户端运用 LoadBalancer 的服务端点,能够有用躲避掉节点单点故障风险。LoadBalancer 类型 Service 依据 NodePort 完成,云厂商 CCM 组件将依据 Service 创立负载均衡监听端口,并将 K8s 集群中各节点和 nodePort 端口添加到负载均衡器后端,由云上负载均衡器完成服务负载均衡才干。

关于需求 TCP 或 UDP 协议的四层转发时,运用 LoadBalancer 是一个简单有用的方法。可是当 K8s 集群中有大量 HTTP 或 HTTPS 类型的 web 服务需求进行七层转发时,假如仅运用 LoadBalancer 方法来露出服务,当存在多个服务需求运用相同的端口时,需求为每个服务创立一个负载均衡器,分配不同的 IP 地址,会形成大量的资源本钱和保护本钱。

运用网关的要求

如前文所述,K8s Service 解决的是服务发现和负载均衡的问题,但并没有服务办理才干,无法被当成网关运用,而关于一个典型的运用网关,根本都包含以下才干:

从 Nginx Ingress 窥探云原生网关选型

  • 为了防止为各个微服务做重复冗余的认证鉴权装备,网关能够支撑供给安全认证、拜访限制、支撑 SSL 卸载等。
  • 出于网关安稳性考虑,咱们希望网关能够供给必定的限流才干。
  • 需求有可观测才干查看网关后端各服务呼应时刻趋势、恳求状态码计算等。
  • 为了保证能够快速定位排查问题,网关也需求记录各恳求的具体拜访日志。

K8s 提出了 Ingress 以支撑从集群外部到集群内服务的 HTTP 和 HTTPS 服务路由,并供给了对外拜访的统一端点,Nginx Ingress 是社区供给的依据 Nginx 完成的默许 Ingress 操控器。

NginxIngress 概述

网关云原生化是一个遍及的趋势,运用不同底层网关完成的 Ingress Provider,其供给的网关特性才干各不相同。Nginx 作为被遍及运用的反向署理工具,依据 Nginx 完成的 Nginx Ingress 也成为了 K8s 集群中最广泛运用的Ingress网关。

工作原理

从 Nginx Ingress 窥探云原生网关选型

一般 Nginx Ingress 以 Deployment 结合 LoadBalancer Service 的方法布置在 K8s 集群中,Nginx Ingress Controller 由 manager 和 Nginx 进程组成,manager 担任监听 Ingress 资源改变并依据 Nginx 装备模版将 Ingress 资源的 Spec 界说和注解转换为Nginx可辨认参数,生成新的 nginx.conf 装备文件,并由 manager 发起 Nginx 进程 reload,新的路由装备就经过 Ingress 在网关收效了。外部流量经过 LoadBalancer 转发到 Nginx,由 Nginx 依据路由装备转发到后端服务中。

Nginx Ingress Controller 还监听了 Service 的后端的改变,并将改变后的后端列表发送到 Nginx 中进行缓存,在运用 Pod 改变或扩缩容时,无需考虑 Pod IP 改变即可完成 Nginx 服务后端的动态改变。此外,Nginx Ingress 官方供给了 prometheus 监控对接计划,并供给了基础指标的监控大盘,便于调查网关后端服务呼应状态。

Ingress 资源界说了主机名和途径来设置服务在 Nginx 上的七层转发规矩,一起 Nginx Ingress 还支撑装备扩展,扩展机制包含:

  • 通用注解:关于一些通用的 Nginx 才干,比方重写、重定向、衔接数设置、超时时刻等,Nginx Ingress 界说了通用的注解以便于 Controller 辨认解析为 nginx.conf 装备文件内容。
  • 装备片段:面临需求定制化 Nginx 装备的场景,Nginx Ingress 也供给了注解 main-snippet、server-snippet、configuration-snippet 来刺进定制化的 nginx.conf 装备片段。
  • lua 插件:Nginx Ingress 还支撑插件化挂载自界说 lua 脚本便于从自建 Nginx 搬迁到K8s Nginx Ingress 中。

一个运用 Ingress 的注解来自界说 location 片段,完成依据恳求头重定向的例子如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($http_user = "gray") {
        rewrite ^/(.*)$ /traffic;
      }
  ...
spec:            
  rules:                                 
  - host: test.domain.com                
    http:                                
      paths:                             
      - backend:                         
          service:                       
            name: test-svc               
            port:                        
              number: 80                 
        path: /test
  ...

查看 Nginx Ingress Controller 中的装备,能够看到刺进的装备片段:

server {
  server_name test.domain.com
  ...
  location /test {
    ...
    if ($http_user = "gray") {
        rewrite ^/(.*)$ /traffic;
    }
  }
}

Nginx Ingress 网关缺乏

不难看出,Nginx 反向署理网关依然是布置在 K8s 集群中的,网关的功能直承受 Pod 资源分配和宿主机功能影响。且假如 Nginx Ingress Controller Pod 地点的节点依然存在其他事务 Pod,还会呈现资源抢占问题。因为 Nginx Ingress 承担了集群的大量进口流量,安稳性要求很高,一般情况下,咱们会将其 Pod 独立调度来保证安稳性,比方在节点上设置污点,并在 Ingress Controller 的 Pod 中设置污点容忍让其独占节点资源;为增强 Ingress 网关可靠性,需求结合事务实践压力设置 Ingress 的副本数和资源分配;出于网关高峰期弹性考虑,还需求结合 HPA 以支撑网关 Pod 水平扩容;此外,Nginx Ingress 实践是由负载均衡器供给的对外拜访才干,还需求结合事务考虑负载均衡带宽是否满意高峰期需求。

K8s 为 Pod 供给了 livenessProbe 和 readinessProbe 的存活查看和健康查看机制,官方Nginx Ingress Controller 的 Deployment 布置模版中也运用了该机制进行网关健康查看,相关装备如下:

livenessProbe:
  failureThreshold: 5        
  httpGet:                   
    path: /healthz           
    port: 10254              
    scheme: HTTP             
  initialDelaySeconds: 10    
  periodSeconds: 10          
  successThreshold: 1        
  timeoutSeconds: 1          
readinessProbe:              
  failureThreshold: 3        
  httpGet:                   
    path: /healthz           
    port: 10254              
    scheme: HTTP             
  initialDelaySeconds: 10    
  periodSeconds: 10          
  successThreshold: 1        
  timeoutSeconds: 1

其健康查看和存活查看运用的是由操控面 manager 监听的 10254 端口供给的 /healthz 健康查看进口,而 Nginx Ingress 数据面和操控面在同一个容器中,在事务高峰期网关负载较高时很有或许导致操控面的健康查看接口呼应超时。依据 livenessProbe 机制,很有或许呈现 Nginx Ingress 网关不断重启导致网关不安稳,流量有损。此外,操控面 manager 还担任收集prometheus监控指标,在事务高峰期操控面还或许抢占不到足够的 CPU,呈现 OOM,导致容器被 Kill 的情况。

另外需求留意的是,经过 Nginx Ingress 更新 Nginx 网关路由规矩直接将域名和途径订正到 nginx.conf 装备文件,需求更新 Nginx 装备并重新加载才干收效。当运用存在长衔接,如 websocket 的情况下,reload 操作会导致事务衔接在一段时刻后呈现显着掉线。

从 Nginx Ingress 窥探云原生网关选型

在操作 Ingress 资源时,如新建 Ingress、删去 Ingress、更新 Ingress 后端、更新 Ingress 证书装备等操作,都会触发 Nginx 进程的 reload。虽然 Nginx 的 reload 过程存在优雅停止机制,在接收到 reload 信号后会创立新的 workerq 子进程并保持旧 worker 进程处理已有恳求,如下图所示:

从 Nginx Ingress 窥探云原生网关选型

可是当客户端存在 TCP 长衔接超过了 worker_shutdown_timeout 时刻没有断开时,会强制停止原有的 worker 进程,断开 worker 上的衔接,nginx reload 原理示意图如下:

从 Nginx Ingress 窥探云原生网关选型

除此之外,因为 Nginx Ingress Controller 是经过 List 和 Watch 机制监听 K8s 中的资源,多个节点的操控器行为一致,reload 操作的时刻虽然存时刻差异,但大致能够看作是一起进行,一起 reload 无疑会让风险最大化。为下降 reload 的影响,咱们能够考虑优化 Nginx Ingress,比方经过将 Nginx Ingress Controller 的装备文件改变与主动reload 行为分隔,保留动态修正装备逻辑,增加 reload 触发逻辑,reload 操作只有满意了特定条件才干进行。比方,为 Pod 新增 reload 信号注解,操控器辨认到节点存在该注解再触发 reload,下降 reload 操作的影响面。

可是 Nginx Ingress 经过装备文件来更新 Nginx 路由装备的操作,无法防止 reload。面临该问题,业界也提出了运用 Nginx 结合 Lua 插件动态读取网关上游装备的计划,路由规矩存储在数据库中,由 Lua 装备读取到 Nginx 的共享内存中,示意图如下。

从 Nginx Ingress 窥探云原生网关选型

自建网关容易疏忽的细节

综上可见,Nginx Ingress 网关在 K8s 集群中存在进程 reload 长衔接有损、数据面和操控面未别离、运维难度高级短板。当咱们需求自建 Nginx Controller 时,设想一下,在 K8s 中还需求考虑哪些细节:

  • 不安稳的后端 IP:Pod 的 IP 地址会随运用的重启、搬迁、新版本发布频频的改变。不安稳的后端 IP 让装备难以下手。
  • 频频更新的装备文件:每次后端运用的改变都需求人工保护 Nginx 装备,当构建多节点的高可用 Nginx 服务时,需求人工保证多节点装备的准确性一致性。
  • 装备耐久化:因为 Pod 的不安稳性,当以 Pod 方法布置 Nginx 服务时,每次 Pod 的毁掉和新建,在 Pod 中的改变都会丢掉,需求耐久化保存装备并挂载到多个 Nginx Pod 中。
  • 监控面板对接:需求运维人员自行安装 Nginx 监控模块,并对接到外部监控系统。
  • 拜访日志耐久化:需求为 Nginx 服务额定挂载耐久化数据盘以保存拜访日志。

庆幸的是,随着云原生化趋势,越来越多的网关兼容了 Ingress 完成成为了 Ingress Provider,不少网关现已完成了装备热加载,数据面和操控面别离的才干,并且依据网关特性才干的不同存在各自的优缺点。在 EDAS 中,除了接入了 Nginx Ingress 路由外,还接入了 ALB Ingress、MSE Ingress。下面以这两种 Ingress Provider 为例介绍多种Ingress Provider 的通用完成及其优缺点。

其他 Ingress 网关完成

Ingress 支撑设置 “kubernetes.io/ingress.class” 注解或者装备 ingressClassName 属性来为 Ingress 相关不同的 Ingress Controller。并由 Ingress Controller 来作为 Ingress 资源的监听组件,将 Ingress 的装备解析为后端网关的装备中,如 Nginx 网关的 nginx.conf 装备,ALB 网关的监听后端转发规矩,云原生网关的路由规矩。Ingress、Ingress Class、Ingress Controller 相关联系如下图所示:

从 Nginx Ingress 窥探云原生网关选型

ALB Ingress

从 Nginx Ingress 窥探云原生网关选型

由上图可见,ALB Ingress 工作时事务面与数据面别离,支撑热加载,底层的网关完成为保管在阿里云上的 ALB 实例。依据 ALB 的高弹性、高并发数特性,能够得到完全免运维、主动弹性伸缩的高功能网关,阿里云的 ALB Ingress 解决了 Nginx Ingress 保护的难点。ALB Ingress 兼容了部分 Nginx Ingress 的通用注解,但关于装备片段和插件机制,因为底层完成的不同,并不能做到完全兼容。

MSE Ingress(云原生网关)

从 Nginx Ingress 窥探云原生网关选型

MSE Ingress 是依据 MSE 云原生网关完成的,事务面与数据面别离、支撑热加载,云原生网关不只能够作为 Ingress Provider 为 K8s 集群中的 Service 供给对外南北向流量办理,还能够作为微服务网关对接 EDAS 注册中心、MSE 注册中心、自建 Nacos、Eureka 注册中心供给东西向流量办理才干。一起支撑完备的微服务网关功能,如限流、流量防护、熔断等,能够节省布置和保护运用型微服务网关的本钱,如 springCloud gateway、zuul。此外,在扩展性上,MSE Ingress 支撑了 Wasm 插件,关于 Lua 插件的支撑也在进行中。

场景总结

网关云原生化是一个遍及的趋势,运用不同底层网关完成的 Ingress Provider,其供给的网关特性才干各不相同。除本文介绍 EDAS 支撑的装备的三种 Ingress Provider 外,还有其他多种热门 Provider,如 APISIX Ingress、Haproxy Ingress、Istio Ingress,他们在 K8s 集群中的工作模型均可参阅上述的 Ingress-IngressClass-Ingress Controller 模式。

面临多样化的运用路由网关,咱们需求了解网关特性才干并结合实践事务场景来做挑选,关于本文说到的三种 Ingress Provider,能够总结其分别适用的场景:

  • Nginx Ingress:官方供给的开源 Nginx Ingress 解决计划,与渠道无关最易接入,适用于对网关有定制化需求场景,适用于从自建 Nginx 网关搬迁到 K8s Ingress 网关的场景。但需求额定对网关进行运维,存在安稳性风险。

  • ALB Ingress:依据 ALB,全保管于阿里云上,免运维。适用于事务高峰期超大 QPS、超高并发衔接的场景。假如运用运行在阿里云上,且没有复杂的扩展需求,ALB 是省时省力的挑选。

  • MSE Ingress:依据云原生网关,作为流量网关和微服务 API 网关,适用于对 K8s Ingress 网关和微服务网关一起需求的场景,支撑多语言编写 Wasm 插件扩展网关才干。此外,该网关完成已开源,具体可见:github.com/alibaba/hig…

此外,Ingress API 仅支撑依据域名和途径装备转发规矩,网关供货商需求经过自界说注解来完成更丰富的路由转发和流量办理才干,致使网关路由资源装备越来越复杂。K8s 社区推出了开源项目 Gateway API,用以供给规范化、可扩展、更丰富的网关路由模型,已有多种 Ingress 网关供货商在其操控器中完成了 Gateway API 规范,保证了其路由装备向 Gateway API 规范滑润搬迁。

EDAS 运用路由办理

K8s Ingress为运用网关供给了许多灵敏的挑选,但每种网关才干各有差异,而且大多经过注解方法来供给扩展才干,对许多用户来说复杂度是比较高的。为此,EDAS 供给了运用路由办理功能,用户只需求编写路由规矩并挑选网关类型,就能将运用的服务露出到外部,方便快捷。一起 EDAS 也供给了运用路由的监控大盘,日志检索等必备的运维功能,能够帮助用户快速发现和定位问题,保证事务安稳性。拜见下图:

  • Nginx Ingress

从 Nginx Ingress 窥探云原生网关选型

  • MSE Ingress

从 Nginx Ingress 窥探云原生网关选型

  • ALB Ingress

从 Nginx Ingress 窥探云原生网关选型

  • 概览大盘

从 Nginx Ingress 窥探云原生网关选型

  • 拜访日志查询

从 Nginx Ingress 窥探云原生网关选型

  • 调用链路追踪

从 Nginx Ingress 窥探云原生网关选型