在这篇博客文章中,我们将展示如何使用 Gateway API 的 HTTPRoutes 在单个 Kubernetes 集群中轻松地将流量路由到部署在不同命名空间的工作负载——这个过程比以往任何时候都更简单。
之前,我们只有 Ingress API 来定义入口路由规则。它很好地为我们服务,但也存在我们必须克服的缺点和局限性,有时我们甚至不得不采用一些不太优雅的方式。其中一个局限性就是,将流量路由到与我们的 Ingress 定义在不同命名空间中的 Services。
完整的示例请参考我们创建的 Gist 。欢迎联系我们的中国合作伙伴咨询 consultant@gingxing.com。
使用 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 可能如下所示:
kind: HTTPRouteapiVersion: gateway.networking.k8s.io/v1metadata:name: echo-routenamespace: infraspec:parentRefs:- group: gateway.networking.k8s.iokind: Gatewayname: kongrules:- matches:- path:type: PathPrefixvalue: /fruitsbackendRefs:- name: bananas-echoport: 1027kind: Servicenamespace: bananasweight: 30- name: apples-echoport: 1027kind: Servicenamespace: applesweight: 70
假设我们在 bananas 和 apples 命名空间中未定义任何 ReferenceGrants,就定义这样的 HTTPRoute。在这种情况下,我们的 Gateway API 实现(在我们的案例中为 Kong Ingress Controller)将拒绝这种引用,并在 HTTPRoute 父级的状态的 ResolvedRefs 条件中通知我们这一点:
$ kubectl get httproute -n infra echo-route -o=jsonpath='{.status.parents[0].conditions}' | jq[...{"observedGeneration": 1,"reason": "RefNotPermitted","status": "False","type": "ResolvedRefs"},...]
为了解析这些引用,我们只需要为这两个命名空间创建 ReferenceGrants 即可:
kind: ReferenceGrantapiVersion: gateway.networking.k8s.io/v1beta1metadata:name: allow-apples-echo-in-infranamespace: bananasspec:from:- group: gateway.networking.k8s.iokind: HTTPRoutenamespace: infrato:- group: ""kind: Servicename: bananas-echo # This could be left empty to allow ANY service in the namespace.# A similar one for apples namespace and apples-echo service should be created as well.
ReferenceGrant 的 spec.from 和 spec.to 列表定义了我们可以从哪些资源引用我们在定义 ReferenceGrant 的命名空间中定义的资源。在我们的案例中,我们允许在 infra 命名空间中定义的 HTTPRoute 引用在 bananas 命名空间中名为 banana-echo 的 Service(因为 ReferenceGrant 在这里定义)。
有了这些设置,我们现在可以确保引用已被正确解析,并且我们的流量已按预期转发。
首先,让我们检查 Gateway 是否已解析这些引用:
$ kubectl get httproute -n infra echo-route -o=jsonpath='{.status.parents[0].conditions}' | jq[{"observedGeneration": 2,"reason": "ResolvedRefs","status": "True","type": "ResolvedRefs"},]
引用已解析后,现在我们可以确保流量按预期进行路由:
$ http 'http://${PROXY_IP}/fruits'HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 22Content-Type: text/plain; charset=utf-8Date: Mon, 06 Nov 2023 18:06:01 GMTVia: kong/3.4.2X-Kong-Proxy-Latency: 2X-Kong-Upstream-Latency: 3In namespace apples.$ http 'http://${PROXY_IP}/fruits'HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 23Content-Type: text/plain; charset=utf-8Date: Mon, 06 Nov 2023 18:06:02 GMTVia: kong/3.4.2X-Kong-Proxy-Latency: 0X-Kong-Upstream-Latency: 1In namespace bananas.
正如预期的那样,我们的流量通过部署在 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 配置会发生什么。
kind: HTTPRouteapiVersion: gateway.networking.k8s.io/v1metadata:name: routenamespace: applesspec:parentRefs:- group: gateway.networking.k8s.iokind: Gatewayname: kongnamespace: infra # We need to explicitly specify the namespace of the Gateway as now it is not in the same namespace# as our HTTPRoute (apples).rules:- matches:- path:type: PathPrefixvalue: /applesbackendRefs:- name: apples-echoport: 1027kind: Service# We can omit the namespace as the Service is in the same namespace as our HTTPRoute (apples).
在创建了上述 HTTPRoute 后,让我们查看其状态条件。
$ kubectl get -n apples httproute route -o=jsonpath='{.status.parents[0].conditions}' | jq[{"lastTransitionTime": "2023-12-07T12:31:56Z","observedGeneration": 1,"reason": "NotAllowedByListeners","status": "False","type": "Accepted"},]
我们得到了状态为 False 的 Accepted 条件,原因是 NotAllowedByListeners。这意味着我们的 Gateway 的监听器不允许将我们的 HTTPRoute 附加到它们上。默认情况下,Gateway 仅接受来自其命名空间的 Routes。如果我们想克服这个限制,可以使用 Gateway 的监听器的 allowedRoutes 字段。
在我们的示例中,我们将修改 Gateway 的配置,以允许来自 apples 和 bananas 命名空间的 HTTPRoutes。
apiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: kongnamespace: infraspec:gatewayClassName: konglisteners:- name: proxyport: 80protocol: HTTPallowedRoutes:namespaces:from: Selectorselector:matchExpressions:# Allow attaching Routes from apples and bananas namespaces.- key: kubernetes.io/metadata.nameoperator: Invalues: [apples, bananas]
在将代理监听器的 allowRoutes 更改为上述内容后,我们现在应该能够看到我们的 HTTPRoute 被 Gateway 成功接受。
$ kubectl get -n apples httproute route -o=jsonpath='{.status.parents[0].conditions}' | jq[{"lastTransitionTime": "2023-12-07T13:09:58Z","observedGeneration": 1,"reason": "Accepted","status": "True","type": "Accepted"},]
为了最终验证在 apples 命名空间中创建的 HTTPRoute 是否已成功附加到 Gateway 并进行了配置,我们可以调用预期返回 200 状态码的端点。
$ http "http://${PROXY_IP}/apples?details=true"HTTP/1.1 200 OKIn namespace apples.
完成!
结论
总结我们所学的知识,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)
-
欢迎联系我们的中国合作伙伴咨询 consultant@gingxing.com。

1222

被折叠的 条评论
为什么被折叠?



