设置事件监听器

TIP

要深入理解事件监听器的概念、架构和原理,请参考 深入理解事件监听器 文档。

概述

事件监听器是 Tekton Triggers 中的核心资源,负责接收和处理来自外部系统的事件(如 Webhook)。当外部系统触发事件时,事件监听器会根据配置的触发器创建 Kubernetes 资源(如 PipelineRun)。

主要特性

事件监听器具有以下主要特性:

  • 事件监听:提供一个 HTTP 端点以接收来自外部系统的 Webhook 事件
  • 事件过滤:使用拦截器验证和过滤接收到的事件
  • 资源创建:根据触发器定义自动创建 Kubernetes 资源
  • 扩展性:支持自定义拦截器和各种事件源
  • 安全性:内置多种安全机制,如 Webhook 验证

配置说明

基本结构

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: eventlistener
spec:
  serviceAccountName: tekton-triggers-sa  # 可选,用于指定 ServiceAccount
  resources:
    kubernetesResource:
      serviceType: NodePort  # 服务类型
      servicePort: 80       # 服务端口
      spec:
        template:
          spec:
            containers:
              - resources:    # 资源限制
                  requests:
                    memory: "64Mi"
                    cpu: "250m"
                  limits:
                    memory: "128Mi"
                    cpu: "500m"
  triggers:                  # 触发器配置
    - name: trigger-1       # 触发器名称
      interceptors:         # 拦截器配置
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "header.match('X-GitHub-Event', 'pull_request')"
      bindings:            # 触发器绑定
        - ref: pipeline-binding
      template:            # 触发器模板
        ref: pipeline-template

主要字段描述

spec.resources.kubernetesResource

用于配置事件监听器的 Kubernetes 资源:

  • serviceType: 服务类型(NodePort/ClusterIP/LoadBalancer)
  • servicePort: 服务端口
  • spec: Pod 模板配置

spec.triggers

定义一组触发器配置:

  • name: 触发器名称
  • interceptors: 拦截器配置列表
  • bindings: 触发器绑定配置
  • template: 触发器模板配置

安全配置

事件监听器支持多种安全配置:

  1. ServiceAccount:通过 spec.serviceAccountName 指定运行权限。确保指定的 ServiceAccount 配置了相应的权限。
  2. 拦截器验证:使用 CEL 拦截器进行事件验证。
  3. TLS:支持配置 HTTPS 证书。

权限指南

为了正确触发管道和任务,事件监听器使用的 ServiceAccount 需要以下权限:

权限资源描述
get, list, watchconfigmaps读取 ConfigMaps
get, list, watchsecrets读取 Secrets
get, list, watchserviceaccounts读取 ServiceAccounts
create, get, list, watch, patch, updatedeployments管理 Deployments
create, get, list, watch, patch, updateservices管理 Services
create, get, list, watch, patch, updatepods管理 Pods
create, get, list, watch, patch, updateevents管理 Events
createpipelineruns创建 PipelineRuns
createtaskruns创建 TaskRuns
get, list, watchclustertriggerbindings读取 ClusterTriggerBindings
get, list, watchtriggerbindings读取 TriggerBindings
get, list, watchclusterinterceptors读取 ClusterInterceptors
get, list, watchinterceptors读取 Interceptors
get, list, watchtriggers读取 Triggers
get, list, watchtriggertemplates读取 TriggerTemplates
get, list, watcheventlisteners读取 EventListeners

可参照的 ClusterRole:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: eventlistener-role
rules:
- apiGroups: [""]
  resources: ["configmaps", "secrets", "serviceaccounts"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["create", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
  resources: ["services", "pods", "events"]
  verbs: ["create", "get", "list", "watch", "patch", "update"]
- apiGroups: ["tekton.dev"]
  resources: ["pipelineruns", "taskruns"]
  verbs: ["create"]
- apiGroups: ["triggers.tekton.dev"]
  resources:
    - "clustertriggerbindings"
    - "triggerbindings"
    - "clusterinterceptors"
    - "interceptors"
    - "triggers"
    - "triggertemplates"
    - "eventlisteners"
  verbs: ["get", "list", "watch"]

用户指南

部署事件监听器需要根据环境的规模和实际网络状况进行规划,以下是如何根据规划不同配置的说明:

规模

在不同的规划场景中,可以使用不同的配置以满足不同的要求。

规模触发器数量资源设置
小规模2(触发器)* 100(命名空间)* 10(管道)= 2,000 触发器/集群中等,两个以上副本
中规模2(触发器)* 1,000(命名空间)* 10(管道)= 20,000 触发器/集群中等,两个以上副本,按命名空间部署不同的事件监听器

网络配置

根据环境的优先级和可用网络资源,可以选择不同的网络配置。

网络配置协议描述
官方域名和证书https通过 ClusterIP + Ingress 设置 TLS 证书
自定义域名和证书https使用自签名证书进行 TLS。注意:工具端配置存在风险,并非所有工具/平台都支持跳过或忽略 TLS 验证。
NodePorthttp通过 NodePort + 集群/节点 IP 设置可访问地址

小规模 + HTTPS + ALB Ingress 配置示例

前提条件

  1. 域名配置正确,相应的证书已到位。
  2. 已部署并正确配置 ALB。

配置示例

创建命名空间(可选)

确保有一个命名空间以便于管理事件监听器及其他权限;这里以 tekton-webhooks 为例。

kubectl create namespace tekton-webhooks

创建事件监听器

将以下 YAML 保存为 eventlistener.yaml

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: eventlistener
  namespace: tekton-webhooks
  labels:
    el.tekton.dev/namespaces: all
    el.tekton.dev/size: small
spec:
  serviceAccountName: "eventlistener" # 自定义 SA
  # 监听所有 NS 的触发器
  namespaceSelector:
    matchNames:
    - '*'
  # 声明 Kubernetes 资源,默认为 Deployment
  resources:
    kubernetesResource:
      serviceType: ClusterIP # ClusterIP 服务类型
      servicePort: 80  # 服务端口(容器端口)
      replicas: 2 # 副本数
      spec: # Deployment 规格
        template:
          metadata:
            labels:
              el.tekton.dev/namespaces: all
              el.tekton.dev/size: small
          spec: {}
kubectl apply -f eventlistener.yaml

创建 ClusterRole

以下 YAML 用于 eventlistener-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: eventlistener-role
rules:
- apiGroups: [""]
  resources: ["configmaps", "secrets", "serviceaccounts"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["create", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
  resources: ["services", "pods", "events"]
  verbs: ["create", "get", "list", "watch", "patch", "update"]
- apiGroups: ["tekton.dev"]
  resources: ["pipelineruns", "taskruns"]
  verbs: ["create"]
- apiGroups: ["triggers.tekton.dev"]
  resources:
    - "clustertriggerbindings"
    - "triggerbindings"
    - "clusterinterceptors"
    - "interceptors"
    - "triggers"
    - "triggertemplates"
    - "eventlisteners"
  verbs: ["get", "list", "watch"]
kubectl apply -f eventlistener-role.yaml

创建 ServiceAccount 并设置权限

创建一个绑定,使用上述的 ClusterRole 和 ServiceAccount。

kubectl -n tekton-webhooks create serviceaccount eventlistener
kubectl create clusterrolebinding tekton-webhooks:eventlistener:eventlistener-role --clusterrole=eventlistener-role --serviceaccount=tekton-webhooks:eventlistener

创建 Ingress 和 TLS 秘密

INFO

需要将 <host> 设置为对应的域名和证书信息。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: eventlistener-ingress
  annotations:
    ### 注意 ALB 不需要设置 ingressClassName
    ## kubernetes.io/ingress.class: "nginx" ## 根据 ingress class 的变化进行更新,并记得添加相应的 ingress 注解。
    ### 以下配置应根据要求自定义:
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ### 注意 ALB 不需要设置 ingressClassName
  ## ingressClassName: alb ## 根据需要的 ingress 类进行更改
  tls:
  - hosts:
    - <host> # 域名设置
    secretName: <tls secret> # 包含 TLS 证书的秘密名称
  rules:
  - host: <host> # 域名设置
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: el-eventlistener 
            port:
              number: 80

验证 Webhook 配置

您可以使用以下 curl 测试配置是否正常。

curl -k -X POST -H 'Content-Type: application/json' -d '{"hello": "world"}' <host>

## 以下是预期的返回格式:
$> {
  "eventListener": "eventlistener",
  "namespace": "tekton-webhooks",
  "eventListenerUID": "8a7edab2-b426-453a-9f92-xxxxxx",
  "eventID": "aefd3b5b-2b19-4a14-b411-xxxxxxx"
}

最佳实践

  1. 资源限制

    • 为事件监听器 Pods 设置适当的资源请求和限制。
    • 根据实际负载调整副本数量。
  2. 安全性

    • 使用 HTTPS 和 Webhook 秘密。
    • 配置最低权限的 ServiceAccount。
    • 使用拦截器验证所有传入的事件。
  3. 可用性

    • 通过 LoadBalancer 或 Ingress 暴露服务。
    • 配置适当的健康检查。
    • 实施高可用部署。
  4. 监控

    • 监控事件监听器日志。
    • 设置适当的警报机制。
    • 跟踪事件处理性能。

常见问题

  1. 事件未触发管道

    • 检查拦截器配置。
    • 验证 Webhook 配置。
    • 查看事件监听器日志。
  2. 权限问题

    • 确认 ServiceAccount 权限。
    • 检查 Role 和 RoleBinding。
    • 验证命名空间访问权限。
  3. 性能问题

    • 调整资源限制。
    • 优化拦截器配置。
    • 考虑横向扩展。

参考链接