在云原生时代,基于主流的云操作系统 Kubernetes ,其常见的外部流量访问方式主要基于以下 NodePort、LoadBalancer 以及 Ingress 等。
针对 NodePort 方式,在所有节点(虚拟机)上开放一个特定端口,例如:3000,任何发送到该端口的流量都能够被转发到对应服务。其对应服务 Yaml 文件如下:
代码语言:javascript复制apiVersion: v1
kind: Service
metadata:
name: mydemo-service
spec:
type: NodePort
selector:
app: MyDemoApp
ports:
# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
- port: 80
targetPort: 80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
nodePort: 30007
基于 NodePort 方式,其简要拓扑示意结构如下图所示:
基于此种拓扑结构,存在以下缺陷,具体如下所示:
1、每一个端口只能为一种服务提供。
2、端口范围限制,只能是 30000 - 32767 区间。
3、如果节点或VM 的 IP 地址发生变化,我们需要通过其他方案能够处理这种情况。
因此,基于以上原因,通常不建议在生产环境上用这种方式暴露服务。如果我们运行的服务不要求一直可用,或者对成本比较敏感,可尝试可以使用这种方法。这样的应用的最佳例子是 Demo 应用,或者某些临时应用。
关于 LoadBalancer 方式,在使用支持外部负载均衡器的云提供商的服务时,设置 type 的值为 "LoadBalancer", 将为 Service 提供负载均衡器。负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段发布出去。其对应服务 Yaml 文件如下:
代码语言:javascript复制apiVersion: v1
kind: Service
metadata:
name: mydemo-service
spec:
selector:
app: MyDemoApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
clusterIP: 10.0.171.239
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 192.0.2.127
基于 LoadBalancer 方式,其简要拓扑示意结构如下图所示:
基于此种拓扑结构,其最大缺陷是基于云厂商所提供的服务,每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费。
作为 Kubernetes集群中服务的入口,Ingress 已经被当前的容器生态完全接纳。Ingress 事实上并不是一种服务类型。相反,它处于多个服务的前端,扮演着“智能路由”或者集群入口的角色。以 Traefik Ingress 为例,其对应服务 Yaml 文件如下:
代码语言:javascript复制kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: "foo"
namespace: production
spec:
rules:
- host: example.net
http:
paths:
- path: /bar
backend:
serviceName: service1
servicePort: 80
- path: /foo
backend:
serviceName: service1
servicePort: 80
基于 Ingress 方式,其参考拓扑图如下所示:
Ingress 是访问Kubernetes集群的入口,流量按 Ingress 资源指定的规则分发到集群内部的上游服务。针对上述相关组件的详细解析与实践,可参考之前文章,具体链接地址为:Kubernetes Ingress深入解析以及Kubernetes Service解析。除了Kubernetes 默认的NGINX Ingress Controller(基于原生 NGINX)之外, 业界也有不少其他第三方的 Ingress Controller 的实现。这也是本篇文章所要解析的内容。Apache APISIX 作为国内最快毕业的 Apache 顶级项目,实现了Apache APISIX Ingress Controller,为Kubernetes用户提供了功能更为便捷的 Ingress 实现。
概念解析
其实,本质上来讲,Apache APISIX 是一个基于微服务 API 网关,其不仅可以处理南北向的流量,也可以处理东西向的流量即服务之间的流量。Apache APISIX 集成了控制面板和数据面,与其他 API 网关相比,Apache APISIX 的上游、路由、插件全是动态的,修改这些东西时都不用重启。并且 Apache APISIX 的插件也是热加载,可以随时插拔、修改插件。我们来看一下其网络拓扑参考,具体如下所示:
上面我们解析到 Apache APISIX 是一种 API 网关,其主要基于云原生生态领域,基于Nginx 和 Etcd 实现。那么,基于此种技术,Apache APISIX 能够做哪些呢,或许这才是核心。截止到目前的版本,其提供以下功能,具体如下:
1、K8S Nginx Controller 相关功能
2、替代 Nginx 处理南北向流量
3、替代 Envoy 处理服务间东西向流量
4、基于 MQTT 插件作为 IoT 网关
5、基于 IdP 插件实现零信任网关
6、处理 L4、L7 层流量,可满足Http、Https、Tcp、Udp、gRPC以及其他
Apache APISIX Ingress Controller 基于 Apache APISIX, 集成 Kubernetes 的集群管理能力,支持使用 YAML 申明的方式动态配置入口流量的分发规则,绑定插件,并且支持服务发现、配置校验等能力。Apache APISIX Ingress Controller 将配置写入 Apache APISIX,由 Apache APISIX 承载业务流量。
除此之外,Apache APISIX Ingress Controller 除了覆盖 NGINX Ingress Controller 已有的能力外,还解决了一些 Nginx Ingress Controller 的痛点。具体如下:
1、配置的动态化加载
通常情况下,作为接入层的 Ingress Controller ,其承载着服务的入口流量引入,在生产环境中,我们的业务对系统的可靠性有着更高的要求,然而,基于 Apache APISIX Ingress Controller 其能够支持动态配置,即时生效,降低生产事故的意外及风险,有助于提高运维可维护性。
2、较强的灰度能力
在实际的业务场景中,有的时候,往往会依据某些特定的需求进行权重调整,结合业务需求按比例进行流量控制,Apache APISIX Ingress Controller 可以支持 Service和 Pod 级别的权重调整,配置清晰而且可读性更强。
除此,相对于NGINX Ingress Controller 中通过 Annotation 的方式提供 Canary 灰度方案,Apache APISIX Ingress Controller 能够解决其缺陷,从而能够更好的提供灰度策略。
3、较好的扩展能力
基于 Apache APISIX 强大的插件能力,Apache APISIX Ingress Controller 通过动态绑定插件来增强功能。Apache APISIX 通过插件封装逻辑,易于管理;完善的文档,易于使用和理解。Apache APISIX Ingress Controller 通过配置即可绑定和解绑插件,无需操作脚本。
设计理念
通过上述解析,我们可以大概的知晓,Apache APISIX 其设计理念是基于API 网关的数据平面和控制平面分离。控制平面不仅仅能够控制 Apache APISIX ,同时其还能够控制其他组件;数据平面不仅仅能够被自身的控制平面控制,还能被其他组件所控制。由于其基于ETCD 来存储和分发路由数据,默认具备高可用,无单点故障风险。除此之外,其能够友好地支持 Prometheus、SkyWalking 动态追踪、流量复制、故障注入等相关功能。
架构原理
关于Apache APISIX 架构,其主要分为数据面和控制面,其参考示意图如下所示:
1、数据平面:以 Nginx 的网络库为基础,(弃用 Nginx 的路由匹配、静态配置和 C 模块),使用 Lua 和 Nginx 动态控制请求流量,通过插件机制来实现各种流量处理和分发的功能:限流限速、日志记录、安全检测、故障注入等,同时支持用户编写自定义插件来对数据面进行扩充。
2、控制平面:使用 Etcd 来存储和同步网关的配置数据,管理员通过 Admin API 或者 Dashboard 可以在毫秒级别内通知到所有的数据面节点,同时 Etcd 集群也保证了系统的高可用。
因为 Apache APISIX 使用了 ETCD 作为配置中心,在对应其他组件时会非常方便,可以把 ETCD 直接就当做服务注册发现中心来使用(服务注册、发现),当然同时也支持 Consul、Eureka、Nacos 等服务注册中心。
接下来,我们来看一下其工作流程,具体如下示意图所示:
结合上述的架构参考图以及工作流程图,我们再来了解一下 Apache APISIX Ingress Controller 的应用实现场景,具体来说,Apache APISIX Ingress Controller 可以轻松地替换 NGINX Ingress Controller,基于更为便捷的配置方式,动态的调整网关配置。无需 Reload Nginx,配置即会实时生效。
应用场景
Apache APISIX Ingress 典型的应用场景如下所示:
基于上述场景,Apache APISIX Ingress 对外提供访问Kubernetes集群的入口,用户通过外部负载均衡器访问到 Apache APISIX Ingress。流量经过 Apache APISIX 路由规则,分发到目标上游服务。
同时,内部支持通过Kubernetes Service 或者Kubernetes Pod IP Port 的方式访问上游服务,Apache APISIX Ingress Controller 集成Kubernetes,实现服务自动注册和发现,实时同步Kubernetes状态变更。
得益于 Apache APISIX 丰富的插件支持,可以通过绑定插件,轻松扩展 Ingress 的能力。比如,限流、熔断、灰度发布、跨域、用量管控、健康检查等。更为甚至可以自定义插件,满足特殊业务场景。比如,配合 Apache APISIX Ingress Controller 的服务发现机制,实现自定义的负载均衡能力。
最后,我们来看个简单的 Demo 示例,通过 ApisixRoute 定义一个路由,指向端口是 5555 的上游服务。具体 Yaml 文件内容如下:
代码语言:javascript复制apiVersion: apisix.apache.org/v1
kind: ApisixRoute
metadata:
name: demo-route
spec:
rules:
- host: demo.apisix.apache.org
http:
paths:
- backend:
serviceName: foo
servicePort: 5555
path: /luga*
当访问 demo.apisix.apache.org/luga 时,Apache APISIX Ingress 将会把请求转发到上游 foo 服务。我们再来定义 Proxy-Rewrite 插件,实现转发给上游服务的同时修改 Host 和 Uri。具体如下:
代码语言:javascript复制piVersion: apisix.apache.org/v1
kind: ApisixRoute
metadata:
name: demo-route
spec:
rules:
- host: demo.apisix.apache.org
http:
paths:
- backend:
serviceName: foo
servicePort: 5555
path: /luga*
plugins:
- enable: true
name: proxy-rewrite
config:
regex_uri:
- '^/(.*)'
- '/extend/$1'
scheme: http
host: foo-beta.apisix.apache.org
目前,基于社区的最新进展,在保证现有功能的稳定迭代的同时,Apache APISIX Ingress 后续也将支持 VM Cluster 的部署方式,作为 VM Ingress,丰富服务注册/发现场景,比如,支持 Consul 等注册中心,与此同时,支持 VM Cluster 与 Kubernetes Cluster 统一配置。至此,关于 Apache APISIX Ingress 相关解析本文到此为止,大家有什么疑问、想法及建议,欢迎留言沟通。