本文将以 Kubernetes Ingress、Istio 和 Envoy Gateway 为例,向你介绍 Kubernetes 中的入口网关和 Gateway API,同时介绍 Gateway API 使得 Kubernetes 和服务网格入口网关融合的新趋势。
2014 年 6 月 Kubernetes 开源,起初只能使用 NodePort 和 LoadBalancer 类型的 Service 对象来暴露集群内服务,后来才诞生了 Ingress,两年后(Kubernetes 1.2)Ingress API 进入 Beta 版本,随后为了保持其轻量和可移植的特性,Ingress API 相较于 Kubernetes 其他 API 发展得比较缓慢,直到 Kubernetes 1.19 它才升级到 GA。
Ingress 的主要目标是用简单的、声明性的语法来暴露 HTTP 应用。你可以在 Kubernetes 中部署多种 Ingress Controller,并在创建 Ingress 的时候通过 IngressClass 指定该网关使用的控制器,或者在 Kubernetes 中设置默认的默认的 IngressClass。Kubernetes 默认只支持 AWS、GCE 和 Nginx Ingress Controller,同时还支持大量的第三方 Ingress Controller。
下图展示了 Kubernetes Ingress 的工作流程。
详细流程如下:
Istio 同时支持 Ingress 和 Gateway API,下面是一个使用 Istio 入口网关的配置示例,在后文中会使用 Gateway API 创建该配置。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: istio
spec:
controller: istio.io/ingress-controller
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress
spec:
ingressClassName: istio
rules:
- host: httpbin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin
port: 8000
注意:Ingress 的 spec 中必须在 ingressClassName
字段中指定使用的 IngressClass
,否则将无法创建对应的入口网关。
虽然 IngressClass
实现了入口网关与后台实现的解耦,但是它仍然有着巨大的局限性:
nginx.ingress.kubernetes.io/rewrite-target
annotation,已经无法适应可编程路由的需求;Gateway API 是一个 API 资源的集合 —— GatewayClass
、Gateway
、HTTPRoute
、TCPRoute
、ReferenceGrant
等。Gateway API 暴露了一个更通用的代理 API,可以用于更多的协议,而不仅仅是 HTTP,并为更多的基础设施组件建模,为集群运营提供更好的部署和管理选项。
另外 Gateway API 通过将资源对象分离,实现配置上的解耦,可以由不同的角色的人员来管理,其中的 API 对象如下图所示。
下面是在 Istio 中使用 Gateway API 的示例。
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
name: gateway
namespace: istio-ingress
spec:
gatewayClassName: istio
listeners:
- name: default
hostname: "*.example.com"
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
name: http
namespace: default
spec:
parentRefs:
- name: gateway
namespace: istio-ingress
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: httpbin
port: 8000
与 Ingress 类似,Gateway 使用 gatewayClassName
声明其使用的控制器,该控制器需要平台管理员创建,并允许客户端对 *.example.com
域名的请求。应用开发者可以在其服务所在的命名空间中,在此示例中是 default
创建路由规则,并通过 parentRefs
绑定到 Gateway 上,当然这必须是在 Gateway 明确允许其绑定的情况下(通过 allowRoutes
字段中的规则设置)。
当你应用上面的配置后,Istio 会自动为你创建一个负载均衡网关,下图展示了 Gateway API 的工作流程。
详细流程如下:
GatewayClass
和 Gateway 控制器;GatewayClass
);GatewayClass
和 Gateway
对象的变动;从以上步骤中我们可以看出 Gateway API 相比 Ingress 有了明确的角色划分,而且路由规则可以与网关配置解耦,这大大增加了管理的灵活性。
下图展示了流量接入网关后经过处理的流程。
从图中我们可以看出路由是与网关绑定的,路由一般与其后端服务部署在同一个命名空间中,如果在不同的命名空间中时,需要在 ReferenceGrant
中明确赋予该路由跨命名空间的引用权限,例如下面的 foo
命名空间中的 HTTPRoute foo
可以引用 bar
命名空间中的 bar
服务。
kind: HTTPRoute
metadata:
name: foo
namespace: foo
spec:
rules:
- matches:
- path: /bar
forwardTo:
backend:
- name: bar
namespace: bar
---
kind: ReferenceGrant
metadata:
name: bar
namespace: bar
spec:
from:
- group: networking.gateway.k8s.io
kind: HTTPRoute
namespace: foo
to:
- group: ""
kind: Service
目前,Gateway API 仅支持 HTTPRoute
,TCPRoute
、UDPRoute
、TLSRoute
和 GRCPRoute
还在实验阶段。Gateway API 已经得到了大量的网关和服务网格项目的支持,请在 Gateway 官方文档中查看支持状况。
服务网格主要关注的是东西向流量,即 Kubernetes 集群内部的流量,但是大部分服务网格同样提供了入口网关功能,例如 Istio。但是 Istio 的功能和 API 过于复杂,在本文中我们就以 SMI 为例来说明入口网关和服务网格的关系。
SMI(Service Mesh Interface)是 CNCF 的孵化项目,开源与 2019 年,它定义了独立于供应商的在 Kubernetes 中运行的服务网格通用标准。
下图说明 Gateway API 与服务网格 API 的重叠点。
从图中我们可以看到 Gateway API 与 SMI 在流量规范部分有明显的重叠。这些重叠导致同样的功能,需要在 Gateway API 和服务网格中重复实现。
当然,并不是所有的服务网格是完全符合 SMI 标准,Istio 是目前最流行的服务网格实现,它提供了丰富的流量管理功能,但是没有对这些功能制定单独的策略 API,而是耦合在 VirtualService
和 DestinationRule
中,如下所示。
VirtualService
DestinationRule
VirtualService
主要处理路由相关功能,而 DestinationRule
负责集群节点的开合和负载均衡。
正如上文所述,Gateway API 与服务网格之间有部分功能交集,为了减少重复开发,促成对 Gateway API 与服务网格之间共同关注点的建模,Gateway API 工作组提出了 GAMMA(Gateway API Mesh Management and Administration)倡议。
在该倡议的倡导下,那些在不同网关实现中的细节各不相同的高级流量管理功能,例如超时、重试、健康检查等,全部通过策略附件(Policy Attachment)的方式将由各个提供商来实现。你可以通过通过 targetRef
字段指定策略附件所附加到的资源对象,例如下所示:
apiVersion: networking.acme.io/v1alpha1
kind: RetryPolicy
metadata:
name: foo
spec:
override:
maxRetries: 10
default:
maxRetries: 5
targetRef:
group: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
name: foo
在这里例子中重试策略被附加到了名为 foo
和 HTTPRoute
上。策略附件附加到不同的资源对象上,其生效的优先级也不同,例如 GatewayClass 是集群级的资源,如果策略附件覆盖在它上面的话,将优先生效。
你可以给附加策略指定 override
和 default
值,其在入口和网格内不同资源上的层次结构的优先级是如下图所示。
目前,Gateway API 正在探索用来处理网格流量,并提出了一些设计方案。
2022 年 10 月 Envoy Gateway 首个开源版本 v0.2 发布,这是一个基于 Envoy 代理的遵循 Gateway API 而创建的网关,Tetrate 是该项目的核心发起者之一。Envoy Gateway 的目标是降低用户采用 Envoy 作为 API 网关的障碍,以吸引更多用户采用 Envoy。它通过入口和 L4/L7 流量路由,表达式、可扩展、面向角色的 API 设计,使其成为供应商建立 API 网关增值产品的基础。
早在 Envoy Gateway 发布之前,Envoy 作为最流行了云原生代理之一,已被大规模采用,有多款 Gateway 软件基于 Envoy 构建,Istio 服务网格使用它作为默认的 sidecar 代理,并通过 xDS 协议来配置这些分布式代理。在 Envoy Gateway 中,它同样使用 xDS 来配置 Envoy 集群,下图展示了 Envoy Gateway 的架构。
基础设施供应商会为你提供 GatewayGlass
,你可以通过创建一个 Gateway 声明来创建一个 Envoy Gateway,你在 Gateway 中的路由和策略附件会通过 xDS 协议发送给 Envoy 集群。
关于 Envoy Gateway 的进一步介绍,请阅读:
Gateway API 作为下一代 Kubernetes Ingress API,为 Kubernetes 网关供应商提供一定程度上的 API 规范,在保证其可移植性的前提下丰富了入口网关的功能,同时通过关注点分离方便不同角色的人员对网关进行管理。最后 GAMMA 倡议正在促进服务网格的入口网关与 Gateway API 的融合,策略附件可能将 Gateway API 的功能进一步扩展到东西向网关,我们拭目以待。
最后更新于 2024/12/12