Tekton实战系列之Tekton Trigger

150次阅读

共计 13262 个字符,预计需要花费 34 分钟才能阅读完成。

Tekton Trigger

什么是 Tekton Trigger

Tekton Trigger 是 Tekton 的一个组件,它可以从各种来源的事件中检测并提取需要信息,然后根据这些信息来运行TaskRun 和 PipelineRun,还可以将提取出来的信息传递给它们以满足不同的运行要求。

其核心组件如下:

  • EventListener:时间监听器,是外部事件的入口 ,通常需要通过HTTP方式暴露,以便于外部事件推送,比如配置Gitlab的Webhook。
  • Trigger:指定当EventListener检测到事件发生时会发生什么,它会定义TriggerBinding、TriggerTemplate以及可选的Interceptor。
  • TriggerTemplate:用于模板化资源,根据传入的参数实例化Tekton对象资源,比如TaskRun、PipelineRun等。
  • TriggerBinding:用于捕获事件中的字段并将其存储为参数,然后会将参数传递给TriggerTemplate。
  • ClusterTriggerBinding:和TriggerBinding相似,用于提取事件字段,不过它是集群级别的对象。
  • Interceptor:拦截器,在TriggerBinding之前运行,用于负载过滤、验证、转换等处理,只有通过拦截器的数据才会传递给TriggerBinding。

工作原理图如下:

Tekton实战系列之Tekton Trigger

核心组件

TriggerTemplate

TriggerTemplate 可以模块化 Tekton 资源的资源,可以使传入的参数在资源模板中的任何位置被使用,它就好比我们定义了一个对象,这个对象可以接收外部的参数,在对象内部把接收到的参数再传递给 Tekton 资源对象进行使用。

TriggerTemplate 的定义很简单,如下:

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: pipeline-template
spec:
  params:  # 参数的定义,从外部接收的参数
  - name: gitrevision
    description: The git revision
    default: main
  - name: gitrepositoryurl
    description: The git repository url
  - name: message
    description: The message to print
    default: This is the default message
  - name: contenttype
    description: The Content-Type of the event
  resourcetemplates: # 资源模板,将参数传递给资源模板,实例化一个PipelineRun对象
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: simple-pipeline-run-
    spec:
      pipelineRef:
        name: simple-pipeline
      params:
      - name: message
        value: $(tt.params.message)
      - name: contenttype
        value: $(tt.params.contenttype)
      resources:
      - name: git-source
        resourceSpec:
          type: git
          params:
          - name: revision
            value: $(tt.params.gitrevision)
          - name: url
            value: $(tt.params.gitrepositoryurl)

从上面可以看出,resourcetemplates字段中就是定义的资源模板,上面定义的PipelineRun的资源,里面的语法和定义一个PipelineRun CRD一致,就像Deployment的Template中定义的Pod资源和单独定义Pod资源的语义一样。

params字段定义我们需要从外部获得的参数,这个参数后续会传递给resourcetemplates以完成其资源实例化。

TriggerBinding

TriggerBinding用于将事件进行绑定,通过捕获事件中的字段并将其存储为参数。

其定义方式如下:

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: pipeline-binding
spec:
  params:
  - name: gitrevision
    value: $(body.head_commit.id)
  - name: gitrepositoryurl
    value: $(body.repository.url)
  - name: contenttype
    value: $(header.Content-Type)

TriggerBinding接收从EventListener传递过来的参数,然后传给TriggerTemplate,在TriggerTemplate上实例化资源对象。

TriggerBinding提供TriggerTemplate需要的参数,参数以key-value的方式存储并传递。其中的value是通过$()中包裹得JSONPath表达式来提取

Trigger

用于指定当事件发生时需要做什么,它会定义TriggerBinding、TriggerTemplate以及可选的Interceptor。

如下:

apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
  name: trigger
spec:
  interceptors:
    - ref:
        name: "cel"
      params:
        - name: "filter"
          value: "header.match('X-GitHub-Event', 'pull_request')"
        - name: "overlays"
          value:
            - key: extensions.truncated_sha
              expression: "body.pull_request.head.sha.truncate(7)"
  bindings:
  - ref: pipeline-binding
  template:
    ref: pipeline-template

上面定义了interceptorsbindingstemplate,一当EventListener收到事件,就会触发这个Trigger,先经过interceptors进行拦截筛选,然后再传给bindingstemplate

ClusterTriggerBinding

ClusterTriggerBinding和TriggerBinding功能一样,从名字就可以看到,ClusterTriggerBinding是集群级别的,可以作用于任何namespace。

其定义和TriggerBinding一样,如下:

apiVersion: triggers.tekton.dev/v1beta1
kind: ClusterTriggerBinding
metadata:
  name: pipeline-clusterbinding
spec:
  params:
    - name: gitrevision
      value: $(body.head_commit.id)
    - name: gitrepositoryurl
      value: $(body.repository.url)
    - name: contenttype
      value: $(header.Content-Type)

Interceptor

Interceptor是在TriggerBinding运行之前的事件处理器,可以做一些预处理,比如账户密码验证,再比如一些事件方式验证,如gitlab的push event。只有通过了Interceptor,才会把有效数据传递给TriggerBinding。

Tekton Trigger目前支持两种Interceptor的实现方式:

  • 独立Interceptor
  • 传统Interceptor(将被废弃)

独立Interceptor是ClusterInterceptor自定义资源的实例,可以在下面介绍的EventListener中引用这些Interceptor以及所需的参数。传统的Interceptor就是在EventListener中完全定义,不过这种方式将被废弃。

目前已经内置了以下Interceptor:

  • Webhook Interceptor
  • Github Interceptor
  • Gitlab Interceptor
  • Bitbucket Interceptor
  • CEL Interceptor

这里以Gitlab Interceptor为例。Gitlab Interceptor包括验证和过滤的逻辑,它可以验证Webhook的来源,也可以验证指定标准过滤传入的事件。如下:

interceptors:
- ref:
    name: "gitlab"
  params:
  - name: "secretRef"
    value:
      secretName: foo
      secretKey: bar
  - name: "eventTypes"
    value: ["Push Hook"]

也可以直接在EventListener中定义,如下:

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: gitlab-listener-interceptor
spec:
  serviceAccountName: tekton-triggers-example-sa
  triggers:
    - name: foo-trig
      interceptors:
        - gitlab:
            secretRef:
              secretName: foo
              secretKey: bar
            eventTypes:
              - Push Hook
      bindings:
        - ref: pipeline-binding
      template:
        ref: pipeline-template

EventListener

EventListener是一个Kubernetes对象,用于监听Kubernetes上指定端口的事件,然后会接收传入的事件并指定一个或多个触发器。

EventListener实际上是Tekton的另一种客户端形式,只是它是基于HTTP事件的,通过HTTP的方式可以绕过常规的认证路径,比如kubeconfig等,我们知道,任何需要通过kube-apiserver的事件都需要认证、鉴权等一系列操作,那HTTP方式是如何实现的呢?我们在创建一个简单的nginx deployment的时候,可以看到yaml文件里会自动生成一个default的serviceaccount,这个default就是用于认证、鉴权的。所以要使用EventListener,就需要让它拥有自己的serviceaccount,并且这个serviceaccount需要Tekton资源操作的权限才能让Event正常的和Tekton进行交互。

EventListener 的定义示例如下:

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: gitlab-listener
spec:
  serviceAccountName: tekton-triggers-example-sa
  triggers:
    - name: gitlab-push-events-trigger
      interceptors:
        - name: "verify-gitlab-payload"
          ref:
            name: "gitlab"
            kind: ClusterInterceptor
          params:
            - name: secretRef
              value:
                secretName: "gitlab-secret"
                secretKey: "secretToken"
            - name: eventTypes
              value:
                - "Push Hook"
      bindings:
        - name: gitrevision
          value: $(body.checkout_sha)
        - name: gitrepositoryurl
          value: $(body.repository.git_http_url)
      template:
        spec:
          params:
            - name: gitrevision
            - name: gitrepositoryurl
          resourcetemplates:
            - apiVersion: tekton.dev/v1alpha1
              kind: TaskRun
              metadata:
                generateName: gitlab-run-
              spec:
                taskSpec:
                  inputs:
                    resources:
                      - name: source
                        type: git
                  steps:
                    - image: ubuntu
                      script: |
                        #! /bin/bash
                        ls -al $(inputs.resources.source.path)
                inputs:
                  resources:
                    - name: source
                      resourceSpec:
                        type: git
                        params:
                          - name: revision
                            value: $(tt.params.gitrevision)
                          - name: url
                            value: $(tt.params.gitrepositoryurl)

安装

$ kubectl apply -f https://raw.githubusercontent.com/honest1y/kubernetes_yaml/master/devops/tekton/triggers/install.yaml
$ kubectl apply -f https://raw.githubusercontent.com/honest1y/kubernetes_yaml/master/devops/tekton/triggers/interceptors.yaml

安装完成后,可以看到如下Pod。

$ kubectl get po -n tekton-pipelines
NAME                                                 READY   STATUS    RESTARTS   AGE
tekton-dashboard-8587979b74-j4fm6                    1/1     Running   0          2d18h
tekton-pipelines-controller-bc5bc8857-hw4kw          1/1     Running   0          2d18h
tekton-pipelines-webhook-8595755454-5k86t            1/1     Running   0          3d13h
tekton-triggers-controller-b5869cfcb-nnsjq           1/1     Running   0          2d22h
tekton-triggers-core-interceptors-85fc599556-64ml4   1/1     Running   0          3d13h
tekton-triggers-webhook-7bf6cfbb4c-6vkzt             1/1     Running   0          3d13h

使用Tekton Trigger

上面已经安装好了Tekton Trigger,下面我们将正式接入Tekton Trigger实现自动持续部署。

创建webhook认证secret及RBAC授权

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-secret
type: Opaque
stringData:
  secretToken: "1234567"
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-build-sa
secrets:
  - name: ccr-auth
  - name: gitlab-auth
  - name: gitlab-secret
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: tekton-triggers-gitlab-minimal
rules:
# EventListeners need to be able to fetch all namespaced resources
- apiGroups: ["triggers.tekton.dev"]
  resources: ["eventlisteners", "triggerbindings", "triggertemplates",
"triggers"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
# configmaps is needed for updating logging config
  resources: ["configmaps"]
  verbs: ["get", "list", "watch"]
# Permissions to create resources in associated TriggerTemplates
- apiGroups: ["tekton.dev"]
  resources: ["pipelineruns", "pipelineresources", "taskruns"]
  verbs: ["create"]
- apiGroups: [""]
  resources: ["serviceaccounts"]
  verbs: ["impersonate"]
- apiGroups: ["policy"]
  resources: ["podsecuritypolicies"]
  resourceNames: ["tekton-triggers"]
  verbs: ["use"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tekton-triggers-gitlab-binding
subjects:
- kind: ServiceAccount
  name: tekton-build-sa
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: tekton-triggers-gitlab-minimal
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tekton-triggers-gitlab-clusterrole
rules:
  # EventListeners need to be able to fetch any clustertriggerbindings
- apiGroups: ["triggers.tekton.dev"]
  resources: ["clustertriggerbindings", "clusterinterceptors"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tekton-triggers-gitlab-clusterbinding
subjects:
- kind: ServiceAccount
  name: tekton-build-sa
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: tekton-triggers-gitlab-clusterrole

定义Trigger Template

PipelineRun的YAML文件,可以看到有参数gitrevision、gitrepositoryurl、image、image_tag、namespace等,所以在定义Trigger Template的时候需要这些参数传递进去。

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: argo-template
spec:
  params: # 定义参数,和 TriggerBinding 中的保持一致
    - name: gitrevision
    - name: gitrepositoryurl
  resourcetemplates: # 定义资源模板
    - apiVersion: tekton.dev/v1beta1
      kind: PipelineRun # 定义 pipeline 模板
      metadata:
        generateName: gitlab-run- # TaskRun 名称前缀
      spec:
        serviceAccountName: tekton-build-sa
        pipelineRef:
          name: pipeline
        workspaces:
          - name: go-repo-pvc
            persistentVolumeClaim:
              claimName: go-repo-pvc
        params:
          - name: git_url
            value: $(tt.params.gitrepositoryurl)
          - name: git_infra_url
            value: git.srelife.cn/web/demo-helm.git
          - name: image
            value: "ccr.ccs.tencentyun.com/mervingz/webhook-demo"
          - name: image_tag
            value: "$(tt.params.gitrevision)"
          - name: argocd_url
            value: argocd-server.argocd.svc.cluster.local
          - name: argocd_secret
            value: argocd-auth
          - name: app_name
            value: demo-web

定义Trigger Binding

Trigger Template的入参都可以通过PushEvent中获取,PushEvent里的数据需要通过Trigger Binding来绑定。

Trigger Binding 可通过 CRD 创建,也可以在 EventListener 中直接指定。

定义EventListener

上面创建好Trigger Template和Trigger Binding,接下来就是创建EventListener,把Template和Binding关联起来。

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: gitlab-listener # 该事件监听器会创建一个名为el-gitlab-listener的 Service 对象
spec:
  serviceAccountName: tekton-build-sa
  triggers:
  - name: gitlab-push-events-trigger
    interceptors:
    - ref:
        name: gitlab
      params:
      - name: secretRef # 引用 gitlab-secret 的 Secret 对象中的 secretToken 的值
        value:
          secretName: gitlab-secret
          secretKey: secretToken
      - name: eventTypes
        value:
          - Push Hook # 只接收 GitLab Push 事件
    bindings: # 定义TriggerBinding,配置参数
    - name: gitrevision
      value: $(body.checkout_sha)
    - name: gitrepositoryurl
      value: $(body.repository.git_http_url)
    template:
      ref: argo-template #在argo部署后添加

这里的tekton-build-sa是需要我们创建的,如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-build-sa
secrets:
  - name: ccr-auth
  - name: gitlab-auth
---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tekton-clusterrole-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: tekton-build-sa
  namespace: default

---
apiVersion: v1
kind: Secret
metadata:
  name: ccr-auth
type: kubernetes.io/basic-auth
stringData:
    username: ''
    password: ''

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: go-repo-pvc
spec:
  resources:
    requests:
      storage: 10Gi
  volumeMode: Filesystem
  storageClassName: cbs 
  accessModes:
    - ReadWriteOnce

现在需要新增一个Gitlab的Webhook的Secret Token,如下:

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-auth
  annotations:
    tekton.dev/git-0: http://git.srelife.cn
type: kubernetes.io/basic-auth
stringData:
  username: ''
  password: ''

当创建完 EventListener 过后,会在当前 namespace 下生成一个 service 和 deployment,如下:

$ kubectl get po
NAME                                 READY   STATUS      RESTARTS   AGE
el-gitlab-listener-d497f968d-crspc   1/1     Running     0          2d22h

我们需要把这个service暴露出去,创建Ingress如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: el-gitlab-listener
  namespace: default
spec:
  ingressClassName: nginx-pub
  rules:
  - host: el.webhook.srelife.cn
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: el-gitlab-listener
            port:
              number: 8080

创建Webhook

Tekton实战系列之Tekton Trigger

可以测试一下,并查看更多的信息,需要的信息都是从Request中获取,如下:

{
  "object_kind": "push",
  "event_name": "push",
  "before": "1ea073f6d28caddcd4896dcb1e545b59ba90fb82",
  "after": "d8ad21c72cbaecd09c978263bacae641c22777e4",
  "ref": "refs/heads/master",
  "checkout_sha": "d8ad21c72cbaecd09c978263bacae641c22777e4",
  "message": null,
  "user_id": 1,
  "user_name": "Administrator",
  "user_username": "root",
  "user_email": null,
  "user_avatar": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
  "project_id": 2,
  "project": {
    "id": 2,
    "name": "demo-web",
    "description": null,
    "web_url": "http://git.srelife.cn/web/demo-web",
    "avatar_url": null,
    "git_ssh_url": "git@git.srelife.cn:web/demo-web.git",
    "git_http_url": "http://git.srelife.cn/web/demo-web.git",
    "namespace": "web",
    "visibility_level": 20,
    "path_with_namespace": "web/demo-web",
    "default_branch": "master",
    "ci_config_path": null,
    "homepage": "http://git.srelife.cn/web/demo-web",
    "url": "git@git.srelife.cn:web/demo-web.git",
    "ssh_url": "git@git.srelife.cn:web/demo-web.git",
    "http_url": "http://git.srelife.cn/web/demo-web.git"
  },
  "commits": [
    {
      "id": "d8ad21c72cbaecd09c978263bacae641c22777e4",
      "message": "1\n",
      "title": "1",
      "timestamp": "2023-02-03T20:44:23+08:00",
      "url": "http://git.srelife.cn/web/demo-web/-/commit/d8ad21c72cbaecd09c978263bacae641c22777e4",
      "author": {
        "name": "Mervinwang",
        "email": "[REDACTED]"
      },
      "added": [

      ],
      "modified": [
        "main.go"
      ],
      "removed": [

      ]
    },
    {
      "id": "3e52572ea946a889a1e41e372864a2458a10aaa7",
      "message": "123\n",
      "title": "123",
      "timestamp": "2023-02-03T20:40:40+08:00",
      "url": "http://git.srelife.cn/web/demo-web/-/commit/3e52572ea946a889a1e41e372864a2458a10aaa7",
      "author": {
        "name": "Mervinwang",
        "email": "[REDACTED]"
      },
      "added": [

      ],
      "modified": [
        "main.go"
      ],
      "removed": [

      ]
    },
    {
      "id": "1ea073f6d28caddcd4896dcb1e545b59ba90fb82",
      "message": "1\n",
      "title": "1",
      "timestamp": "2023-02-03T20:33:08+08:00",
      "url": "http://git.srelife.cn/web/demo-web/-/commit/1ea073f6d28caddcd4896dcb1e545b59ba90fb82",
      "author": {
        "name": "Mervinwang",
        "email": "[REDACTED]"
      },
      "added": [

      ],
      "modified": [
        "main.go"
      ],
      "removed": [

      ]
    }
  ],
  "total_commits_count": 3,
  "push_options": {
  },
  "repository": {
    "name": "demo-web",
    "url": "git@git.srelife.cn:web/demo-web.git",
    "description": null,
    "homepage": "http://git.srelife.cn/web/demo-web",
    "git_http_url": "http://git.srelife.cn/web/demo-web.git",
    "git_ssh_url": "git@git.srelife.cn:web/demo-web.git",
    "visibility_level": 20
  }
}

到目前为止,就可以实现代码提交到Gitlab,然后通过Webhook自动触发Tekton Pipeline了。

正文完
 
mervinwang
版权声明:本站原创文章,由 mervinwang 2023-02-06发表,共计13262字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
文章搜索