配置 EventListener 自动暴露规则

本文档帮助你完成的内容

本文档帮助你通过自动暴露功能配置 EventListener 的自动外部暴露。你将学习:

  • 如何配置导出规则,通过 Ingress 或 Gateway API(HTTPRoute)自动暴露 EventListener
  • 如何设置会在 UI 中显示的 webhook URL
  • 如何为不同的 namespace 或环境配置不同的暴露策略
  • 如何验证 EventListener 是否已正确暴露

使用场景:当你希望系统自动为 EventListener 创建 Ingress 资源,而无需手动创建和管理 Ingress 资源时,可以使用此功能。这在需要一致 webhook URL 模式的生产环境中尤其有用。

前提条件:你应具有集群管理员权限,以便配置 TektonConfig 资源,并且应对 Kubernetes Ingress 和网络概念有基本了解。

功能概览

自动暴露控制器(内部名称为 trigger-wrapper)会读取 Tekton 系统 namespace 中的 trigger-wrapper-config ConfigMap(默认值:tekton-pipelines)。该 ConfigMap 中定义的 export-rules 决定了哪些 EventListener 应当对外暴露(Service、Ingress 等),并将生成的端点填充到 EventListener/Trigger 的状态中。

INFO

技术说明:内部组件名称是 trigger-wrapper,但你不需要记住这一点。你只需要通过 TektonConfig 配置导出规则,其余工作由系统自动处理。

配置入口

在 Alauda Tekton 中,建议通过 TektonConfig 自定义资源管理此配置。将规则定义嵌入到 spec.pipeline.options.configMaps.trigger-wrapper-config.data.config 下,例如:

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  pipeline:
    options:
      configMaps:
        trigger-wrapper-config:
          data:
            config: |
              export-rules:
                - name: test-webhooks
                  host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
                  ingressClass: nginx
                  urlPathPrefix: /triggers
                  externalHosts:
                    - "https://webhooks.example.com"
                    - "https://backup.webhooks.example.com"
                  namespaceSelector:
                    matchNames:
                      - "*"

Operator 会将此 spec 同步到 Tekton 系统 namespace(默认值:tekton-pipelines)中的 trigger-wrapper-config ConfigMap。更新后,自动暴露控制器会刷新其缓存,并根据新规则协调资源。

INFO

说明:ConfigMap 名称 trigger-wrapper-config 是内部技术名称。你通过上面所示的 TektonConfig 管理配置,不需要直接与该 ConfigMap 交互。

字段参考

export-rules 中的每一项都代表一种发布策略。重要字段如下:

  • name – 规则名称,也用于生成 Service/Ingress 名称。 避免名称冲突:共享的 Ingress 名称是将规则名称规范化为有效的 DNS-1123 子域名后的结果(转换为小写,将 [a-z0-9-] 之外的字符替换为 -,连续的 - 会被折叠)。此规范化过程会丢失信息,因此只在这些字符上不同的规则名会解析为同一个 Ingress,并相互覆盖——例如 a_b、a.b 和 A-B 最终都会变成 a-b。请为每条规则指定一个已经是不同且有效的 DNS-1123 子域名的名称(小写字母、数字和 -);不要依赖 _、. 或字母大小写来区分两条规则。

  • ingressClass(可选)– 要使用的 Ingress controller,例如 nginx、traefik。

  • host(可选)– 由 Ingress 匹配的主机名。留空则接受所有 host。重要:配置域名时,请确保 DNS 解析已正确配置(本地测试时也可以添加到 /etc/hosts)。该域名必须能被将发送 webhook 的系统解析。

  • externalHosts(可选)– 作用:定义会显示在 UI 中并填充到 EventListener 的 status.addresses 字段中的 webhook URL。

    可以将其理解为:外部系统(如 GitHub、GitLab)用于向你的 EventListener 发送 webhook 的“公网地址”。

    工作方式:

    • 控制器会将每个 externalHosts URL 与生成的路径组合:${externalHost}/<urlPathPrefix>/<eventlistener-namespace>/<eventlistener-name>
    • 例如:externalHosts: ["https://webhooks.example.com"] + urlPathPrefix: /triggers → 最终 URL:https://webhooks.example.com/triggers/my-namespace/my-listener
    • 这些 URL 会显示在 EventListener 的 status.addresses 字段中,便于直接复制到 GitHub/GitLab webhook 配置

    常见场景:

    场景externalHosts 中填写什么示例
    标准 HTTPS 域名带 https:// 的公网域名"https://webhooks.example.com"
    带自定义端口的 LoadBalancer带端口号的域名/IP"https://webhooks.example.com:8443"
    多个访问入口备用 URL 数组["https://primary.com", "https://backup.com"]
    基于 IP 的访问(无域名)带 IP 地址的 HTTP"http://192.168.1.100"(但将 host 字段留空)
    ACP 平台平台 URL + cluster 路径"https://192.168.1.100/clusters-rewrite/test"

    如果填写错误会怎样?

    • ✅ Ingress 仍然可以正常工作(此字段不影响 Ingress 创建)
    • ❌ 用户会在 UI 中看到错误的 webhook URL
    • ❌ 将 status.addresses 中的 URL 复制到 GitHub/GitLab 会失败
    • 🔧 修复方式:在 TektonConfig 中更新 externalHosts 值,控制器会刷新 EventListener 状态

    与 host 字段的主要区别:

    字段用途由谁使用示例
    hostIngress 路由规则(HTTP Host header 匹配)Kubernetes Ingresswebhooks.example.com(仅域名,无协议)
    externalHosts面向用户的 webhook URL,用于 UI 显示EventListener status.addresseshttps://webhooks.example.com(包含协议的完整 URL)

    经验法则:

    • 如果你可以通过 https://webhooks.example.com:8443/triggers/ns/el 访问 webhook,那么请填写:externalHosts: ["https://webhooks.example.com:8443"]
    • 控制器会自动追加路径

    重要说明:

    • 始终包含协议(http:// 或 https://)
    • 如果你的 LoadBalancer 使用非标准端口,请包含自定义端口
    • 不要在 urlPathPrefix 中包含路径(例如 /triggers)——控制器会自动将其追加到 externalHosts 的末尾
    • 如果不确定,请先留空并检查实际可访问的 URL,然后再更新配置
  • urlPathPrefix(可选)– 路径前缀;默认值为 /triggers。最终在 Ingress 中渲染的路径为 ${urlPathPrefix}/${eventlistener-namespace}/${eventlistener-name}。始终以 / 开头,并避免尾部斜杠。

  • namespaceSelector.matchNames(可选)– 此规则允许的 namespace。使用 "*" 可匹配所有 namespace。

  • labelSelector(可选)– Kubernetes LabelSelector,用于筛选 EventListener。

  • tls(可选)– Ingress 的 TLS 配置。每个条目指定 hosts(主机名列表)和 secretName(包含证书的 TLS Secret 名称)。

  • annotations(可选)– Ingress 的额外注解。适用于 cert-manager、nginx 特定设置等。只会应用你提供的注解;控制器不再注入任何 controller-specific 注解(例如 nginx.ingress.kubernetes.io/rewrite-target)。生成的 Ingress 路径使用 pathType: Exact 且不进行重写,因此该暴露方式适用于任何 Ingress controller(nginx、traefik、ALB 等),而不只是 nginx。

  • type(可选)– 暴露资源:Ingress(默认)或 HTTPRoute(Gateway API)。留空时为向后兼容默认使用 Ingress。参见 Gateway API (HTTPRoute) mode。

  • gateway(可选)– 当 type: HTTPRoute 时必需。用于引用 HTTPRoute 所附加的父级 Gateway:name(必填)、namespace(默认为 Tekton 系统 namespace)、可选的 sectionName 和 port。

Namespace 匹配当前仅支持 matchNames。如果你需要基于标签选择 namespace,请显式列出这些 namespace。

到 Ingress 资源的字段映射

下表展示了导出规则字段如何映射到生成的 Ingress 资源:

导出规则字段Ingress 资源字段说明
namemetadata.nameIngress 资源名称设置为规则名称
ingressClassspec.ingressClassName指定由哪个 Ingress controller 处理该 Ingress
hostspec.rules[].hostIngress 规则的主机名。如果为空或 "*",则匹配所有 host。注意: 不支持将 IP 地址作为 host 值。如果使用 IP,请将 host 留空,或配置一个解析到该 IP 的域名。
urlPathPrefixspec.rules[].http.paths[].path(使用 pathType: Exact)与 namespace 和 EventListener 名称组合后形成精确路径:${urlPathPrefix}/${namespace}/${eventlistener-name}
tlsspec.tlsHTTPS 的 TLS 配置。每个条目映射到 spec.tls[].hosts 和 spec.tls[].secretName
annotationsmetadata.annotations只会应用你提供的注解;不会注入由控制器管理的注解
namespaceSelectorN/A用于筛选 EventListener,不直接映射到 Ingress
labelSelectorN/A用于筛选 EventListener,不直接映射到 Ingress
externalHostsN/A用于填充 EventListener 的 status.addresses,不直接映射到 Ingress

映射示例:

给定以下导出规则:

export-rules:
  - name: test-webhooks
    host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    ingressClass: nginx
    urlPathPrefix: /triggers
    tls:
      - hosts:
          - webhooks.example.com
        secretName: webhooks-tls-secret
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
WARNING

DNS 配置:当在 host 字段中使用域名时,请确保 DNS 记录已配置为将该域名解析到你的 Ingress controller 的 IP。对于本地测试,你可以将条目添加到 /etc/hosts(Linux/Mac)或 C:\Windows\System32\drivers\etc\hosts(Windows)。

生成的 Ingress 将具有:

  • metadata.name:test-webhooks
  • spec.ingressClassName:nginx
  • spec.rules[0].host:webhooks.example.com
  • spec.rules[0].http.paths[].path:/triggers/${namespace}/${eventlistener-name}(针对每个匹配的 EventListener)
  • spec.tls[0].hosts:["webhooks.example.com"]
  • spec.tls[0].secretName:webhooks-tls-secret
  • metadata.annotations:包含 cert-manager.io/cluster-issuer 和由控制器管理的注解

请求流图

externalHosts 会告诉外部客户端应调用哪个 URL。Ingress 按 host 和精确路径 ${urlPathPrefix}/${namespace}/${eventlistener} 匹配请求,并转发到 Tekton 系统 namespace 中的 ExternalName Service,该 Service 解析到 EventListener sink Service。由于 sink 接受任意路径,后端会原样接收完整路径(不重写)。

配置示例

示例 1:带自定义前缀的通配 host

export-rules:
  - name: wildcard-host
    urlPathPrefix: /hooks/default
    ingressClass: nginx
    namespaceSelector:
      matchNames:
        - cicd

结果:Ingress 暴露 /hooks/default/${namespace}/${eventlistener}。由于 host 为空,将接受任意 hostname——这非常适合外部网关分配公网域名的场景。

示例 2:共享 hostname 和前缀

export-rules:
  - name: all-listeners
    host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    urlPathPrefix: /triggers
    ingressClass: nginx
    namespaceSelector:
      matchNames:
        - "*"

结果:每个 EventListener 都显示为 https://webhooks.example.com/triggers/${namespace}/${eventlistener};后端看到的路径保持不变。

示例 3:按环境划分的规则

export-rules:
  - name: staging-gitlab
    host: gitlab-staging.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    urlPathPrefix: /staging/gitlab
    namespaceSelector:
      matchNames:
        - staging-tools
    labelSelector:
      matchLabels:
        webhook-type: gitlab

  - name: prod-github
    host: github-prod.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    urlPathPrefix: /prod/github
    ingressClass: traefik
    namespaceSelector:
      matchNames:
        - prod-tools
    labelSelector:
      matchLabels:
        webhook-type: github

结果:

  • GitLab webhooks:https://gitlab-staging.example.com/staging/gitlab/${namespace}/${eventlistener}
  • GitHub webhooks:https://github-prod.example.com/prod/github/${namespace}/${eventlistener}

示例 4:按团队范围发布,使用默认前缀

export-rules:
  - name: team-a
    urlPathPrefix: /triggers
    namespaceSelector:
      matchNames:
        - team-a

结果:仅暴露 team-a 中的 EventListener,访问路径为 /triggers/team-a/${eventlistener}。

示例 5:多个外部端点并调整前缀

export-rules:
  - name: multi-endpoints
    host: webhook.internal.local  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    urlPathPrefix: /internal/hooks
    externalHosts:
      - https://webhooks.example.com/hooks/
      - https://backup.example.com/api/hooks
    namespaceSelector:
      matchNames:
        - ci-tools

结果:

  • Ingress 在内部提供 webhook.internal.local/internal/hooks/${namespace}/${eventlistener}。
  • 对外你可以发布 https://webhooks.example.com/hooks/internal/hooks/${namespace}/${eventlistener} 和 https://backup.example.com/api/hooks/internal/hooks/${namespace}/${eventlistener}。
  • 后端 Service 始终接收 /internal/hooks/${namespace}/${eventlistener}。

示例 6:配置 TLS/HTTPS

选项 A:使用预先创建的 Secret 手动配置 TLS

  1. 创建一个包含证书的 TLS Secret:

    kubectl create secret tls webhooks-tls-secret \
      --cert=path/to/cert.pem \
      --key=path/to/key.pem \
      -n tekton-pipelines
  2. 使用 TLS 配置你的导出规则:

    export-rules:
      - name: secure-webhooks
        host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
        urlPathPrefix: /triggers
        ingressClass: nginx
        tls:
          - hosts:
              - webhooks.example.com
            secretName: webhooks-tls-secret
        namespaceSelector:
          matchNames:
            - "*"

控制器会使用指定的 Secret 自动为 Ingress 配置 TLS。

选项 B:使用 cert-manager 进行自动证书管理

使用 cert-manager 注解配置你的导出规则:

export-rules:
  - name: cert-manager-webhooks
    host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    urlPathPrefix: /triggers
    ingressClass: nginx
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
      # Optional: additional nginx SSL settings
      nginx.ingress.kubernetes.io/ssl-protocols: "TLSv1.2 TLSv1.3"
    namespaceSelector:
      matchNames:
        - "*"

cert-manager 会自动:

  • 创建一个 Certificate 资源
  • 从 Let's Encrypt(或你配置的 issuer)获取证书
  • 创建一个 TLS Secret
  • 使用 TLS 配置更新 Ingress

选项 C:TLS 与注解组合使用

你可以将手动 TLS 配置与额外注解组合使用:

export-rules:
  - name: custom-tls-with-annotations
    host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
    urlPathPrefix: /triggers
    ingressClass: nginx
    tls:
      - hosts:
          - webhooks.example.com
        secretName: custom-tls-secret
    annotations:
      nginx.ingress.kubernetes.io/ssl-protocols: "TLSv1.2 TLSv1.3"
      nginx.ingress.kubernetes.io/ssl-ciphers: "HIGH:!aNULL:!MD5"
    namespaceSelector:
      matchNames:
        - "*"

说明: 当同时配置 tls 和 cert-manager 注解时,tls 配置优先生效。若要实现自动证书管理,请仅使用 cert-manager 注解,而不要配置 tls。

Gateway API (HTTPRoute) mode

除了 Ingress 之外,还可以通过设置 type: HTTPRoute,让导出规则通过 Gateway API 暴露 EventListener。对于没有 Ingress controller(或没有可用 ingressClass),但运行了如 Envoy Gateway 之类 Gateway 实现的集群,这是推荐模式。现有 Ingress 行为保持不变,Gateway 模式同样会保留 status.addresses,因此 UI 和 Git webhook 注册仍可正常工作。

前提条件:

  • 已安装 Gateway API CRD 和一个 Gateway 实现(例如 Envoy Gateway)。如果缺少 CRD,控制器会保持在仅 Ingress 模式,并在任何 type: HTTPRoute 规则上记录 warning 事件。
  • 已存在一个父级 Gateway。其监听器的 allowedRoutes.namespaces 必须允许 Tekton 系统 namespace(默认 tekton-pipelines),因为生成的 HTTPRoute 会创建在该 namespace 中。控制器不会修改 Gateway;它只读取 HTTPRoute 的 Accepted condition。
  • 在此模式下,externalHosts 是必需的——它是 status.addresses 的来源。

示例:

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  pipeline:
    options:
      configMaps:
        trigger-wrapper-config:
          data:
            config: |
              export-rules:
                - name: gateway-webhooks
                  type: HTTPRoute
                  host: webhooks.example.com
                  urlPathPrefix: /triggers
                  externalHosts:
                    - "https://webhooks.example.com"
                  gateway:
                    name: eg
                    namespace: envoy-gateway-system
                  namespaceSelector:
                    matchNames:
                      - "*"

控制器会创建的资源:

  • 在系统 namespace 中,为每个匹配的 EventListener 创建一个 HTTPRoute,其中包含一个 path.type: Exact 匹配(${urlPathPrefix}/${namespace}/${eventlistener})、一个指向你的 Gateway 的 parentRefs 条目,以及一个跨 namespace 的 backendRefs 条目,直接指向 EventListener sink Service(el-<name>,端口 8080)。不使用 URLRewrite filter——sink 会接受完整路径。
  • 在 EventListener 的 namespace 中,为每个 EventListener 创建一个 ReferenceGrant,并通过 to.name 限定到该单一 sink Service,以便系统 namespace 中的 HTTPRoute 可以跨 namespace 引用它(最小权限)。

模式特定的字段行为:ingressClass、tls 和 annotations 仅适用于 Ingress 模式,在 type: HTTPRoute 时会被忽略。若要在 Gateway 模式下使用 HTTPS,请在 Gateway 的监听器上终止 TLS——参见下方的 Gateway API mode 下的 HTTPS。

验证:

# HTTPRoutes are created in the system namespace, named per (EventListener, rule).
kubectl get httproute -n tekton-pipelines

# ReferenceGrants are created in each EventListener's namespace.
kubectl get referencegrant -n <eventlistener-namespace>

只有当 HTTPRoute 被其 Gateway Accepted 后,status.addresses(以及 Trigger 注解中的端点)才会发布。如果地址没有出现,请检查 kubectl get httproute <name> -n tekton-pipelines -o yaml 中的 status.parents[].conditions——Accepted: False 或 ResolvedRefs: False 通常意味着 Gateway 监听器不允许该系统 namespace,或者 sink Service 不可达。

Gateway API mode 下的 HTTPS

在 Gateway API 中,TLS 是在Gateway 监听器上终止的,而不是在 HTTPRoute 上——在此模式下,trigger-wrapper 从不管理证书(tls 字段仅适用于 Ingress 模式)。要通过 HTTPS 提供 EventListener,请将导出规则附加到一个具有 HTTPS 监听器的 Gateway,该监听器的 tls.certificateRefs 指向你的证书 Secret,并通过 gateway.sectionName(或 gateway.port)将规则固定到该监听器。

1. 一个带有 HTTPS 监听器的 Gateway(由平台/集群管理员管理):

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
  namespace: envoy-gateway-system
spec:
  gatewayClassName: eg
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: webhooks.example.com
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: webhooks-tls
      allowedRoutes:
        namespaces:
          from: All

证书 Secret(上面的 webhooks-tls,其中包含 tls.crt / tls.key)和 Gateway 均由集群/平台管理。allowedRoutes.names.from 必须允许 Tekton 系统 namespace,因为生成的 HTTPRoute 会创建在该 namespace 中。

2. 通过 gateway.sectionName 将导出规则固定到该 HTTPS 监听器:

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  pipeline:
    options:
      configMaps:
        trigger-wrapper-config:
          data:
            config: |
              export-rules:
                - name: gateway-webhooks-https
                  type: HTTPRoute
                  host: webhooks.example.com
                  urlPathPrefix: /triggers
                  externalHosts:
                    - "https://webhooks.example.com"
                  gateway:
                    name: eg
                    namespace: envoy-gateway-system
                    sectionName: https
                  namespaceSelector:
                    matchNames:
                      - "*"

说明:

  • 将规则的 host 设置为监听器的 hostname,以使 HTTPRoute hostname 与 TLS SNI 匹配,并在 externalHosts 中使用 https:// scheme,以便发布的 status.addresses 声明为 HTTPS。
  • gateway.sectionName 会将 HTTPRoute 固定到命名监听器;当监听器按端口区分时,请改用 gateway.port(或同时使用)。如果两者都省略,Gateway 会将该路由附加到任意兼容的监听器。
  • trigger-wrapper 只会创建 HTTPRoute(及其 ReferenceGrant);它不会创建或修改 Gateway、监听器或证书 Secret。

配置流程

  1. 编辑 TektonConfig 资源(参见 配置入口)。
  2. 应用更改:kubectl apply -f tektonconfig.yaml。
  3. 等待 Operator 将 ConfigMap 下发;随后自动暴露控制器会自动协调新的资源。

验证与排查

验证 ConfigMap 内容

检查 ConfigMap 是否包含预期配置:

kubectl get configmap trigger-wrapper-config -n tekton-pipelines -o yaml

预期输出(正常):

apiVersion: v1
kind: ConfigMap
metadata:
  name: trigger-wrapper-config
  namespace: tekton-pipelines
data:
  config: |
    export-rules:
      - name: test-webhooks
        host: webhooks.example.com  # Ensure DNS resolution is configured (or add to /etc/hosts for testing)
        ingressClass: nginx
        urlPathPrefix: /triggers
        externalHosts:
          - "https://webhooks.example.com"
          - "https://backup.webhooks.example.com"
        namespaceSelector:
          matchNames:
            - "*"

检查要点:

  • ConfigMap 存在并包含 config 键
  • export-rules 数组与 TektonConfig 规格一致
  • YAML 语法有效(没有解析错误)

验证 Ingress 对象

检查是否为匹配的导出规则创建了 Ingress 资源:

# The shared Ingress is created in the Tekton system namespace (default:
# tekton-pipelines), NOT in the EventListener's namespace, and it is named
# after the export rule (not after the EventListener).
kubectl get ingress -n tekton-pipelines

重要:在系统 namespace 中,每条导出规则只会创建一个共享 Ingress。其名称就是规则的 name,并且每个匹配的 EventListener 都会对应一个 pathType: Exact 路径(${urlPathPrefix}/${namespace}/${eventlistener})。不会在 EventListener 自己的 namespace 中为每个 EventListener 单独创建 Ingress。

预期输出(正常):

NAME                CLASS   HOSTS                    ADDRESS   PORTS   AGE
<export-rule-name>  nginx   webhooks.example.com     ...        80      5m

检查要点:

  • 对每一条至少匹配一个 EventListener 的导出规则,都会存在一个共享 Ingress
  • HOSTS 字段与导出规则中指定的 host 一致(为空/* 表示所有 host)
  • Ingress 已分配 ADDRESS(可能需要几分钟)
  • 检查 kubectl get ingress <rule-name> -n tekton-pipelines -o yaml,确认每个匹配的 EventListener 都有一个 pathType: Exact 路径
  • 如果没有看到 Ingress,请确认 namespace 与 matchNames 匹配,且 EventListener 标签与 labelSelector 匹配

检查 EventListener 地址

验证 EventListener 状态中是否包含生成的 webhook 地址:

# Replace <el-name> with your EventListener name and <namespace> with the namespace where it's deployed
# For example, if your EventListener is named 'hello-listener' in the 'tekton-triggers-demo' namespace:
kubectl get eventlistener hello-listener -n tekton-triggers-demo \
  -o jsonpath='{.status.addresses}' | jq

预期输出(正常):

[
  {
    "url": "https://webhooks.example.com/triggers/<namespace>/<el-name>"
  },
  {
    "url": "https://backup.webhooks.example.com/triggers/<namespace>/<el-name>"
  }
]

检查要点:

  • addresses 数组包含与 externalHosts 配置匹配的 URL
  • URL 应符合以下模式:<externalHost>/<urlPathPrefix>/<eventlistener-namespace>/<eventlistener-name>
  • 如果 addresses 为空或缺失,EventListener 可能没有匹配到任何导出规则

检查 Trigger 注解

检查存储在 Trigger 注解中的导出元数据:

# Replace <trigger-name> with your Trigger name and <namespace> with the namespace where it's deployed
# For example, if your Trigger is named 'my-trigger' in the 'tekton-triggers-demo' namespace:
kubectl get trigger my-trigger -n tekton-triggers-demo \
  -o jsonpath='{.metadata.annotations.triggers\.tekton\.dev/eventlistener-info}' | jq

预期输出(正常):

[
  {
    "name": "my-eventlistener",
    "namespace": "my-namespace",
    "endpoints": [
      "https://webhooks.example.com/triggers/my-namespace/my-eventlistener",
      "https://backup.webhooks.example.com/triggers/my-namespace/my-eventlistener"
    ],
    "relevance": {
      "score": 1000,
      "namespaceScore": 1000,
      "labelScore": 1000,
      "namespaceSelector": {
        "matchNames": ["my-namespace"]
      },
      "matchType": "direct"
    }
  }
]

检查要点:

  • 注解包含一个 EventListener 信息数组
  • 每个条目都包含 name、namespace、endpoints 和 relevance 字段
  • endpoints 数组与 EventListener 的 status.addresses 一致
  • relevance.score 表示 EventListener 与 Trigger 的匹配程度(越高越好)
  • 如果注解缺失,可能是 Trigger 没有找到任何匹配的 EventListener

排查提示

  • 如果某条规则未生效:

    • 确认 namespace 已列在 matchNames 中(或者使用 "*" 匹配所有 namespace)
    • 检查 EventListener 标签是否满足 labelSelector 要求
    • 确保 EventListener 处于 Ready 状态
  • labelSelector 配置错误:

    • 会在控制器日志中显示为解析错误
    • 检查控制器日志:kubectl logs -n tekton-pipelines -l app=tektoncd-enhancement-controller
  • 删除规则(或切换其 type):

    • 会级联删除该规则生成的资源(Ingress + ExternalName Service,或 HTTPRoute + ReferenceGrant)
    • 在 Ingress 和 HTTPRoute 之间切换规则时,会清理旧模式的资源并创建新资源
    • 将 export-rules 设置为空数组会禁用所有外部暴露
    • 当没有规则匹配时,EventListener 的 status.addresses 会被清空
  • 使用 IP 地址而不是域名:

    • 问题:Kubernetes Ingress 资源不支持将 IP 地址作为 host 值。如果你在 host 中配置 IP 地址(例如 host: 192.168.1.100),Ingress 将无法创建或无法正常工作。

    • 方案 1:将 host 留空或设为 "*" 以接受所有 host。Ingress 会不考虑 host header 而匹配请求:

      export-rules:
        - name: ip-based-webhooks
          host: ""  # or omit the host field entirely
          urlPathPrefix: /triggers
          externalHosts:
            - "http://192.168.1.100"  # Use IP in externalHosts for client reference
          namespaceSelector:
            matchNames:
              - "*"
    • 方案 2:配置一个解析到你的 IP 地址的域名,然后在 host 字段中使用该域名:

      1. 配置 DNS 解析:添加一个 A 记录,将你的域名指向该 IP 地址(例如,webhooks.example.com → 192.168.1.100)

      2. 使用该域名配置导出规则:

        export-rules:
          - name: domain-webhooks
            host: webhooks.example.com  # Domain that resolves to your IP. Ensure DNS resolution is configured (or add to /etc/hosts for testing)
            urlPathPrefix: /triggers
            externalHosts:
              - "http://192.168.1.100"  # Or use the domain: "http://webhooks.example.com"
            namespaceSelector:
              matchNames:
                - "*"
    • 注意:externalHosts 可以包含 IP 地址或 URL,因为它只用于填充 EventListener 的 status.addresses,不会影响 Ingress 创建。不过,Ingress 本身在 host 字段中必须使用有效的主机名(或留空)。

通过使用 TektonConfig 维护 ConfigMap,你可以灵活控制 Tekton EventListener 向外部系统的暴露方式。在更新期间关注控制器日志,以确认协调过程成功完成。