这篇文章已超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否仍然准确。

使用 Gateway API 演进 Kubernetes 网络

Ingress 资源是 Kubernetes 的众多成功案例之一。它创造了一个多样化的 Ingress 控制器生态系统,这些控制器以标准化和一致的方式在数十万个集群中使用。这种标准化帮助用户采用了 Kubernetes。然而,在 Ingress 创建五年后,出现了碎片化的迹象,演变成了不同但惊人相似的 CRD过度使用的注解 (annotations)。正是这种使得 Ingress 普及的可移植性也限制了它的未来。

在 2019 年圣地亚哥 Kubecon 上,一群热情的贡献者齐聚一堂,讨论 Ingress 的演进。讨论延续到了街对面的酒店大堂,从中产生的成果后来被称为 Gateway API。这次讨论基于几个关键假设:

  1. 作为自定义 API,底层路由匹配、流量管理和服务暴露的 API 标准已经商品化,对其实现者和用户提供的价值很小。
  2. 可以通过通用的核心 API 资源表示 L4/L7 路由和流量管理。
  3. 可以以不牺牲核心 API 用户体验的方式,为更复杂的功能提供可扩展性。

介绍 Gateway API

这催生了允许 Gateway API 在 Ingress 基础上改进的设计原则:

  • 表达能力 (Expressiveness) - 除了 HTTP 主机/路径匹配和 TLS 外,Gateway API 还可以表达诸如 HTTP 头部操作、流量加权与镜像、TCP/UDP 路由以及其他在 Ingress 中仅通过自定义注解才能实现的功能。
  • 面向角色的设计 (Role-oriented design) - API 资源模型反映了路由和 Kubernetes 服务网络中常见的职责分离。
  • 可扩展性 (Extensibility) - 资源允许在 API 内的各个层级附加任意配置。这使得在最合适的地方进行细粒度定制成为可能。
  • 灵活的一致性 (Flexible conformance) - Gateway API 定义了不同的符合性级别 - 核心(强制支持)、扩展(如果支持则可移植)和自定义(不保证可移植性),这些统称为灵活一致性。这促进了一个高度可移植的核心 API(如 Ingress),同时为 Gateway 控制器的实现者提供了灵活性。

Gateway API 是什么样的?

Gateway API 引入了几种新的资源类型:

  • GatewayClass 是集群范围的资源,充当模板以明确定义由此派生的 Gateway 的行为。这在概念上类似于 StorageClass,但用于网络数据平面。
  • Gateway 是 GatewayClass 的部署实例。它们是执行路由的数据平面的逻辑表示,可以是集群内代理、硬件负载均衡器或云负载均衡器。
  • Route 不是单一资源,而是代表许多不同的协议特定 Route 资源。HTTPRoute 具有匹配、过滤和路由规则,这些规则应用于可以处理 HTTP 和 HTTPS 流量的 Gateway。类似地,还有 TCPRouteUDPRouteTLSRoute,它们也具有协议特定的语义。此模型还允许 Gateway API 未来逐步扩展其协议支持。

The resources of the Gateway API

Gateway 控制器实现

好消息是,尽管 Gateway 处于 Alpha 阶段,但已经有几个Gateway 控制器实现可以运行。由于它是一个标准化规范,以下示例可以在任何一个实现上运行,并且功能应该完全相同。请查看入门指南,了解如何安装和使用这些 Gateway 控制器之一。

动手实践 Gateway API

在以下示例中,我们将演示不同 API 资源之间的关系,并引导你完成一个常见用例:

  • foo 团队将其应用部署在 foo Namespace 中。他们需要控制其应用不同页面的路由逻辑。
  • bar 团队在同一 Kubernetes 集群的 bar Namespace 中运行。他们希望能够对其应用进行蓝绿部署以降低风险。
  • 平台团队负责管理 Kubernetes 集群中所有应用的负载均衡器和网络安全。

以下 foo-route 执行对 foo Namespace 中各种 Service 的路径匹配,并且还有一个指向 404 服务器的默认路由。这通过 foo.example.com/loginfoo.example.com/home 分别暴露 foo-auth 和 foo-home Service。

kind: HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
  name: foo-route
  namespace: foo
  labels:
    gateway: external-https-prod
spec:
  hostnames:
  - "foo.example.com"
  rules:
  - matches:
    - path:
        type: Prefix
        value: /login
    forwardTo:
    - serviceName: foo-auth
      port: 8080
  - matches:
    - path:
        type: Prefix
        value: /home
    forwardTo:
    - serviceName: foo-home
      port: 8080
  - matches:
    - path:
        type: Prefix
        value: /
    forwardTo:
    - serviceName: foo-404
      port: 8080

在同一 Kubernetes 集群的 bar Namespace 中运行的 bar 团队也希望将其应用暴露到互联网,但他们也想控制自己的金丝雀和蓝绿部署。以下 HTTPRoute 配置了以下行为:

  • 对于指向 bar.example.com 的流量:

    • 将 90% 的流量发送到 bar-v1
    • 将 10% 的流量发送到 bar-v2
  • 对于指向 bar.example.com 且 HTTP 头部包含 env: canary 的流量:

    • 将所有流量发送到 bar-v2

The routing rules configured for the bar-v1 and bar-v2 Services

kind: HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
  name: bar-route
  namespace: bar
  labels:
    gateway: external-https-prod
spec:
  hostnames:
  - "bar.example.com"
  rules:
  - forwardTo:
    - serviceName: bar-v1
      port: 8080
      weight: 90
    - serviceName: bar-v2
      port: 8080
      weight: 10
  - matches:
    - headers:
        values:
          env: canary
    forwardTo:
    - serviceName: bar-v2
      port: 8080

Route 和 Gateway 绑定

因此,我们有两个 HTTPRoute 匹配并将流量路由到不同的 Service。你可能想知道,这些 Service 可通过哪里访问?通过哪些网络或 IP 暴露?

Route 如何暴露给客户端由Route 绑定控制,它描述了 Route 和 Gateway 如何建立双向关系。当 Route 绑定到 Gateway 时,意味着它们的集体路由规则已配置在底层负载均衡器或代理上,并且 Route 可通过 Gateway 访问。因此,Gateway 是一个网络数据平面的逻辑表示,可以通过 Route 进行配置。

How Routes bind with Gateways

管理委托

Gateway 和 Route 资源的划分允许集群管理员将部分路由配置委托给各个团队,同时保留集中控制权。以下 Gateway 资源在端口 443 上暴露 HTTPS,并使用由集群管理员控制的证书终止该端口上的所有流量。

kind: Gateway
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
  name: prod-web
spec:
  gatewayClassName: acme-lb
  listeners:  
  - protocol: HTTPS
    port: 443
    routes:
      kind: HTTPRoute
      selector:
        matchLabels:
          gateway: external-https-prod
      namespaces:
        from: All
    tls:
      certificateRef:
        name: admin-controlled-cert

以下 HTTPRoute 显示了 Route 如何通过其 kind (HTTPRoute) 和资源标签 (gateway=external-https-prod) 来确保它匹配 Gateway 的选择器。

# Matches the required kind selector on the Gateway
kind: HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
  name: foo-route
  namespace: foo-ns
  labels:

    # Matches the required label selector on the Gateway
    gateway: external-https-prod
...

面向角色的设计

将所有这些结合起来,你就拥有了一个可以安全地由多个团队共享的单一负载均衡基础设施。Gateway API 不仅是用于高级路由的更具表达能力的 API,还是一个面向角色的 API,专为多租户基础设施设计。其可扩展性确保它将适应未来的用例,同时保持可移植性。最终,这些特性将使 Gateway API 能够很好地适应不同的组织模型和实现,并持续发展。

尝试使用并参与其中

有许多资源可供查看以了解更多信息。