Skip to content

ListenerSet

原文:https://gateway-api.sigs.k8s.io/guides/user-guides/listener-set/

ListenerSet 允许团队把 port、hostname 和 TLS 证书 放在独立资源里定义,而不是把所有这些都堆在一个最多 64 个 listener 的 Gateway 资源里。这套机制支撑起一种可分权管理的模型,特别适合大规模、多租户环境。

基于此,你可能在以下场景下会用到 ListenerSet:

  • 多租户:可以让不同团队各自创建自己的 ListenerSet,共享同一个 Gateway 和底层负载均衡基础设施。
  • 大规模部署:借助 ListenerSet,单个 Gateway 可以拥有超过 64 个 listener。团队间也可以共用同一份 ListenerSet 配置,避免重复。
  • 单 Gateway 持有更多证书:由于单个 Gateway 现在可以拥有超过 64 个 listener,因此一个 Gateway 就可以为更多后端转发加密流量,每个后端都可以使用自己的证书。这种做法与服务级别的证书诉求天然契合,例如 Istio Ambient MeshKnative

下图展示了 ListenerSet 如何帮助把多租户环境中的路由配置去中心化

  • 团队 1 和团队 2 各自管理自己命名空间内的 Service 和 HTTPRoute 资源。
  • 每个 HTTPRoute 都引用一个本命名空间内的 ListenerSet。这样,每个团队就能自主决定他们的路由如何对外暴露(协议、端口、TLS 证书等)。
  • 两个团队的 ListenerSet 共享一个独立命名空间中的 Gateway。另一个 Gateway 团队可以负责集中基础设施的搭建与管理,或按需执行统一策略。
mermaid
flowchart TD
  subgraph team1 namespace
    SVC1[Services]
    HR1[HTTPRoutes]
    LS1[ListenerSet]
  end

  subgraph team2 namespace
    SVC2[Services]
    HR2[HTTPRoutes]
    LS2[ListenerSet]
  end

  subgraph shared namespace
    GW[Gateway]
  end

  HR1 -- "parentRef" --> LS1
  LS1 -- "parentRef" --> GW
  HR1 -- "backendRef" --> SVC1

  HR2 -- "parentRef" --> LS2
  LS2 -- "parentRef" --> GW
  HR2 -- "backendRef" --> SVC2

使用 ListenerSet

Gateway 配置

默认情况下,Gateway 不允许 ListenerSet 被附加进来。用户可以通过配置 Gateway 的 allowedListeners 字段显式启用这种行为,指定允许哪些命名空间贡献 listener。

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: parent-gateway
spec:
  allowedListeners:
    namespaces:
      from: Same

ListenerSet 配置

ListenerSet 通过 parentRef 引用其父 Gateway:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
  name: workload-listeners
spec:
  parentRef:
    name: parent-gateway
    kind: Gateway
    group: gateway.networking.k8s.io

路由附加(Route Attachment)

要把 HTTPRoute(或任何其它 Route 类型)附加到 ListenerSet 上,HTTPRoute 必须在 parentRefs 中把该 ListenerSet 列为父资源

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httproute-example
spec:
  parentRefs:
  - name: workload-listeners
    kind: ListenerSet
    group: gateway.networking.k8s.io
    sectionName: second

Listener 冲突

由于多个 ListenerSet 可以附加到同一个 Gateway,因此需要规则来管理冲突。一个 Listener 是否能被一组 Listener(无论这组 Listener 是位于同一个 ListenerSet 对象里,还是分布在附加到同一个 Gateway 的多个 ListenerSet 中)所区分,取决于 Port、Protocol,以及(依协议而定)Hostname 这三者的组合。

当 Listener 之间无法被区分时,会用 Listener 优先级规则 来解决冲突、决定哪个 Listener 生效。把它当作一场比赛来想通常最直观——"赢家"就是那个实际生效的 Listener。规则如下(在比较项相等时继续向下一条):

  • 父 Gateway 自身的 Listener 优先级最高
  • 创建时间最早的 ListenerSet 优先。
  • 字典序最靠前的 ListenerSet 优先。

的 ListenerSet 会被打上 Accepted: true 标记;的 ListenerSet 会被打上 Accepted: false Conflicted: true 标记。

与 Gateway API 中的所有其它冲突解决规则一样,这套规则也是为了保证流量稳定——也就是说,新增一个冲突的 ListenerSet 永远不会"抢走"已有的配置。

示例

下面这个示例展示一个带一个 HTTP listenerGateway,以及两个子级 HTTPS ListenerSet(各自拥有独立的 hostname 和证书)。只有 belongs-to: shared-gateway 这个 label 的命名空间中的 ListenerSet 才会被接受:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: parent-gateway
spec:
  gatewayClassName: example
  allowedListeners:
    namespaces:
      from: Selector
      selector:
        matchLabels:
          belongs-to: shared-gateway
  listeners:
  - name: foo
    hostname: foo.com
    protocol: HTTP
    port: 80
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-1-ns
  labels:
    belongs-to: shared-gateway
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
  name: first-workload-listeners
  namespace: team-1-ns
spec:
  parentRef:
    namespace: default
    name: parent-gateway
    kind: Gateway
    group: gateway.networking.k8s.io
  listeners:
  - name: first
    hostname: first.foo.com
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        group: ""
        name: first-workload-cert
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-2-ns
  labels:
    belongs-to: shared-gateway
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
  name: second-workload-listeners
  namespace: team-2-ns
spec:
  parentRef:
    namespace: default
    name: parent-gateway
    kind: Gateway
    group: gateway.networking.k8s.io
  listeners:
  - name: second
    hostname: second.foo.com
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        group: ""
        name: second-workload-cert

基于 MIT 协议发布