使用 Gateway API 在命名空间之间发送流量
在这篇博客文章中,我们将展示如何使用 Gateway API 的 HTTPRoutes 在单个 Kubernetes 集群中轻松地将流量路由到部署在不同命名空间的工作负载——这个过程比以往任何时候都更简单。
之前,我们只有 Ingress API 来定义入口路由规则。它很好地为我们服务,但也存在我们必须克服的缺点和局限性,有时我们甚至不得不采用一些不太优雅的方式。其中一个局限性就是,将流量路由到与我们的 Ingress 定义在不同命名空间中的 Services。
完整的示例请参考我们创建的 Gist 。
使用 ReferenceGrants 实现跨命名空间的 HTTPRoute 和 Service 引用
假设我们想要将 Kubernetes 集群分成三个命名空间,每个团队一个:
infra - 用于部署公司的 API Gateway 以及配置其行为所需的资源(即 Ingress、Gateway、HTTPRoute 等)。
apples - 用于部署 apples 团队管理的工作负载。
bananas - 用于部署 bananas 团队管理的工作负载。
在 Ingress API 中,要使用一个 Service,我们必须确保在 Ingress 规则中引用的 Service 定义在与 Ingress 相同的命名空间中。因此,如果我们想在 infra 命名空间中创建一个 Ingress,并使用来自 apples 和 bananas 命名空间的 Service,我们就必须使用一些非标准的变通方法——比如在 Ingress 命名空间中创建一个额外的 ExternalName Service,该 Service 指向另一个命名空间中 Service 的 FQDN。更多内容可以参考 Stack Overflow 上的这两个讨论(点击这里1 和 点击这里2.)。
好消息是?使用 Gateway API 不再需要这些变通方法,因为这些用例从一开始就被考虑在内了。
在 Gateway API 中,Ingress 的等价物是 HTTPRoute 资源。根据设计,它可以在单个规则中使用多个 Service 作为其后端,以便使用用户定义的权重对流量进行负载均衡。更重要的是,只要在 Service 的命名空间中定义了 ReferenceGrant 对象,允许在指定的资源(例如 HTTPRoute)中引用它,那么这些 Service 就可以部署在任何命名空间中。
假设我们希望在 infra 命名空间中定义一个 HTTPRoute,将发送到 /fruits 端点的 70% 的流量路由到团队的 bananas Service(部署在 bananas 命名空间中),其余的流量则路由到团队的 apples Service(部署在 apples 命名空间中)。这样的 HTTPRoute 可能如下所示:
假设我们在 bananas 和 apples 命名空间中未定义任何 ReferenceGrants,就定义这样的 HTTPRoute。在这种情况下,我们的 Gateway API 实现(在我们的案例中为 Kong Ingress Controller)将拒绝这种引用,并在 HTTPRoute 父级的状态的 ResolvedRefs 条件中通知我们这一点:
为了解析这些引用,我们只需要为这两个命名空间创建 ReferenceGrants 即可:
ReferenceGrant 的 spec.from 和 spec.to 列表定义了我们可以从哪些资源引用我们在定义 ReferenceGrant 的命名空间中定义的资源。在我们的案例中,我们允许在 infra 命名空间中定义的 HTTPRoute 引用在 bananas 命名空间中名为 banana-echo 的 Service(因为 ReferenceGrant 在这里定义)。
有了这些设置,我们现在可以确保引用已被正确解析,并且我们的流量已按预期转发。
首先,让我们检查 Gateway 是否已解析这些引用:
引用已解析后,现在我们可以确保流量按预期进行路由:
正如预期的那样,我们的流量通过部署在 infra 命名空间中的 Gateway 被路由到部署在 apples 和 bananas 团队的命名空间中的 Service。
跨命名空间的 HTTPRoute 共享 Gateway
既然我们已知 ReferenceGrant 可以作为将来自不同命名空间的 Service 用作 Gateway API Routes 的后端的补救措施,那么现在让我们思考一下公司基础设施的另一种略有不同的场景。
我们不想为基础设施(Gateway、HTTPRoutes 等)设置单独的命名空间,而是希望允许团队在他们的命名空间中定义 HTTPRoute,以便他们可以对入口流量规则进行更多的控制。我们命名空间的特性将如下:
infra - 用于部署我们公司的 API Gateway(即 Gateway、GatewayClass)。
apples - 用于部署团队 apples 管理的工作负载和 Gateway API Routes,允许入口流量进入。
bananas - 用于部署团队 bananas 管理的工作负载和 Gateway API Routes,允许入口流量进入。
首先,让我们在团队的 apples 命名空间中创建一个 HTTPRoute,看看默认的 Gateway 配置会发生什么。
在创建了上述 HTTPRoute 后,让我们查看其状态条件。
我们得到了状态为 False 的 Accepted 条件,原因是 NotAllowedByListeners。这意味着我们的 Gateway 的监听器不允许将我们的 HTTPRoute 附加到它们上。默认情况下,Gateway 仅接受来自其命名空间的 Routes。如果我们想克服这个限制,可以使用 Gateway 的监听器的 allowedRoutes 字段。
在我们的示例中,我们将修改 Gateway 的配置,以允许来自 apples 和 bananas 命名空间的 HTTPRoutes。
在将代理监听器的 allowRoutes 更改为上述内容后,我们现在应该能够看到我们的 HTTPRoute 被 Gateway 成功接受。
为了最终验证在 apples 命名空间中创建的 HTTPRoute 是否已成功附加到 Gateway 并进行了配置,我们可以调用预期返回 200 状态码的端点。
完成!
结论
总结我们所学的知识,Gateway 的监听器的 allowedRoutes 和 ReferenceGrant 都是有用的 Gateway API 工具。它们允许明确配置 Gateway 控制器在解析可能在 Gateway API 对象定义中出现的跨命名空间引用时将遵循的规则。
如果您想进一步了解这个主题,以下是一些可能有用的参考链接:
跨命名空间路由(https://gateway-api.sigs.k8s.io/guides/multiple-ns/) - 来自 Gateway API 官方文档的指南
Gateway 监听器的 AllowedRoutes API 参考(https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.AllowedRoutes)
ReferenceGrant API 参考(https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1alpha2.ReferenceGrant)
版权声明: 本文为 InfoQ 作者【Gingxing】的原创文章。
原文链接:【http://xie.infoq.cn/article/e4a9e82824d1145761c84db0c】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论