GitLab 触发 Tekton 任务构建

云计算
前面我们都是通过创建一个 TaskRun 或者一个 PipelineRun 对象来触发任务,但是在实际的工作中更多的是开发人员提交代码过后来触发任务,这个时候就需要用到 Tekton 里面的 Triggers 概念了。

[[407261]]

前面我们都是通过创建一个 TaskRun 或者一个 PipelineRun 对象来触发任务,但是在实际的工作中更多的是开发人员提交代码过后来触发任务,这个时候就需要用到 Tekton 里面的 Triggers 概念了。

 

Tekton Triggers Workflow

Triggers 同样通过下面的几个 CRD 对象对 Tekton 进行了一些扩展:

  • TriggerTemplate: 创建资源的模板,比如用来创建 PipelineResource 和 PipelineRun
  • TriggerBinding: 校验事件并提取相关字段属性
  • ClusterTriggerBinding: 和 TriggerBinding 类似,只是是全局的
  • Interceptor: 处理事件以进行自定义验证或过滤
  • EventListener: 连接 TriggerBinding 和 TriggerTemplate 到事件接收器,使用从各个 TriggerBinding 中提取的参数来创建 TriggerTemplate 中指定的 resources,同样通过 interceptor 字段来指定外部服务对事件属性进行预处理

同样要使用 Tekton Triggers 就需要安装对应的控制器,可以直接通过 tektoncd/triggers 的 GitHub 仓库说明进行安装,如下所示的命令(需要注意 v0.14.2 版本需要安装两个资源清单):

  1. kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/previous/v0.14.2/release.yaml 
  2. kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/previous/v0.14.2/interceptors.yaml 

可以使用如下命令查看 Triggers 的相关组件安装状态,直到都为 Running 状态:

  1. $ kubectl get pods --namespace tekton-pipelines 
  2. NAME                                                 READY   STATUS    RESTARTS   AGE 
  3. tekton-dashboard-6fcbd956f4-vvlrz                    1/1     Running   4          15d 
  4. tekton-pipelines-controller-795dd94d96-lkbxt         1/1     Running   5          17d 
  5. tekton-pipelines-webhook-6b8964445d-mp4k6            1/1     Running   5          17d 
  6. tekton-triggers-controller-989875ff7-tlc4v           1/1     Running   0          3h16m 
  7. tekton-triggers-core-interceptors-6494c8cfc4-hb8sk   1/1     Running   0          2m10s 
  8. tekton-triggers-webhook-787849d8db-ch28w             1/1     Running   0          3h16m 

现在我们来将前面的 Jenkins Pipeline 流水线转换成使用 Tekton 来构建,代码我们已经推送到了私有仓库 GitLab,地址为:http://git.k8s.local/course/devops-demo.git。

首先我们需要完成触发器的配置,当我们提交源代码到 GitLab 的时候,需要触发 Tekton 的任务运行,所以首先需要完成这个触发器。这里就可以通过 EventListener 这个资源对象来完成,创建一个名为 gitlab-listener 的 EventListener 资源对象,文件内容如下所示:

  1. # gitlab-push-listener.yaml 
  2. apiVersion: triggers.tekton.dev/v1alpha1 
  3. kind: EventListener 
  4. metadata: 
  5.   name: gitlab-listener  # 该事件监听器会创建一个名为el-gitlab-listener的Service对象 
  6. spec: 
  7.   serviceAccountName: tekton-triggers-gitlab-sa 
  8.   triggers: 
  9.   - name: gitlab-push-events-trigger 
  10.     interceptors: 
  11.     - ref: 
  12.         name: gitlab 
  13.       params: 
  14.       - name: secretRef  # 引用 gitlab-secret 的 Secret 对象中的 secretToken 的值 
  15.         value: 
  16.           secretName: gitlab-secret 
  17.           secretKey: secretToken 
  18.       - name: eventTypes 
  19.         value: 
  20.           - Push Hook # 只接收 GitLab Push 事件 
  21.     bindings: 
  22.     - ref: devops-demo-binding 
  23.     template: 
  24.       ref: devops-demo-template 

由于 EventListener 创建完成后会生成一个 Listener 的服务,用来对外暴露用于接收事件响应,比如上面我们创建的对象名为 gitlab-listener,创建完成后会生成一个名为 el-gitlab-listener 的 Service 对象,由于我们 GitLab 本身就在集群内部,所以我们用 Service 的 DNS 形式来访问 EventListener 即可,如果你想暴露到集群外部则可以使用 NodePort 或者 Ingress 的形式。

另外需要注意的是在上面的 EventListener 对象中我们添加了 interceptors 属性,其中有一个内置的 gitlab 拦截器,GitLab 拦截器包含验证和过滤来自 GitLab 的请求逻辑, 比如我们可以配置 WebHook 的 Secret Token,可以通过 Secret 对象引入进来:

  1. interceptors: 
  2. - ref: 
  3.     name: gitlab 
  4.   params: 
  5.   - name: secretRef  # 引用 gitlab-secret 的 Secret 对象中的 secretToken 的值 
  6.     value: 
  7.       secretName: gitlab-secret 
  8.       secretKey: secretToken 
  9.   - name: eventTypes 
  10.     value: 
  11.       - Push Hook # 只接收 GitLab Push 事件 

对应的 Secret 资源对象如下所示,一个用于 WebHook 的 Secret Token,另外一个是用于 GitLab 登录认证使用的:

  1. # gitlab-secret.yaml 
  2. apiVersion: v1 
  3. kind: Secret 
  4. metadata: 
  5.   name: gitlab-secret 
  6. type: Opaque 
  7. stringData: 
  8.   secretToken: '1234567' 
  9. --- 
  10. apiVersion: v1 
  11. kind: Secret 
  12. metadata: 
  13.   name: gitlab-auth 
  14.   annotations: 
  15.     tekton.dev/git-0: http://git.k8s.local 
  16. type: kubernetes.io/basic-auth 
  17. stringData: 
  18.   username: root 
  19.   password: admin321 

由于 EventListener 对象需要访问其他资源对象,所以需要声明 RBAC,如下所示:

  1. # event-listener-rbac.yaml 
  2. apiVersion: v1 
  3. kind: ServiceAccount 
  4. metadata: 
  5.   name: tekton-triggers-gitlab-sa 
  6. secrets: 
  7.   - name: gitlab-secret 
  8.   - name: gitlab-auth 
  9.   - name: harbor-auth 
  10. --- 
  11. apiVersion: rbac.authorization.k8s.io/v1 
  12. kind: Role 
  13. metadata: 
  14.   name: tekton-triggers-gitlab-minimal 
  15. rules: 
  16.   # EventListeners need to be able to fetch all namespaced resources 
  17.   - apiGroups: ['triggers.tekton.dev'
  18.     resources: 
  19.       ['eventlisteners''triggerbindings''triggertemplates''triggers'
  20.     verbs: ['get''list''watch'
  21.   - apiGroups: [''
  22.     # configmaps is needed for updating logging config 
  23.     resources: ['configmaps'
  24.     verbs: ['get''list''watch'
  25.   # Permissions to create resources in associated TriggerTemplates 
  26.   - apiGroups: ['tekton.dev'
  27.     resources: ['pipelineruns''pipelineresources''taskruns'
  28.     verbs: ['create'
  29.   - apiGroups: [''
  30.     resources: ['serviceaccounts'
  31.     verbs: ['impersonate'
  32.   - apiGroups: ['policy'
  33.     resources: ['podsecuritypolicies'
  34.     resourceNames: ['tekton-triggers'
  35.     verbs: ['use'
  36. --- 
  37. apiVersion: rbac.authorization.k8s.io/v1 
  38. kind: RoleBinding 
  39. metadata: 
  40.   name: tekton-triggers-gitlab-binding 
  41. subjects: 
  42.   - kind: ServiceAccount 
  43.     name: tekton-triggers-gitlab-sa 
  44. roleRef: 
  45.   apiGroup: rbac.authorization.k8s.io 
  46.   kind: Role 
  47.   name: tekton-triggers-gitlab-minimal 
  48. --- 
  49. kind: ClusterRole 
  50. apiVersion: rbac.authorization.k8s.io/v1 
  51. metadata: 
  52.   name: tekton-triggers-gitlab-clusterrole 
  53. rules: 
  54.   # EventListeners need to be able to fetch any clustertriggerbindings 
  55.   - apiGroups: ['triggers.tekton.dev'
  56.     resources: ['clustertriggerbindings''clusterinterceptors'
  57.     verbs: ['get''list''watch'
  58. --- 
  59. apiVersion: rbac.authorization.k8s.io/v1 
  60. kind: ClusterRoleBinding 
  61. metadata: 
  62.   name: tekton-triggers-gitlab-clusterbinding 
  63. subjects: 
  64.   - kind: ServiceAccount 
  65.     name: tekton-triggers-gitlab-sa 
  66.     namespace: default 
  67. roleRef: 
  68.   apiGroup: rbac.authorization.k8s.io 
  69.   kind: ClusterRole 
  70.   name: tekton-triggers-gitlab-clusterrole 

然后接下来就是最重要的 TriggerBinding 和 TriggerTemplate 对象了,我们在上面的 EventListener 对象中将两个对象组合在一起:

  1. bindings: 
  2.   - ref: gitlab-push-binding # TriggerBinding 对象 
  3. template: 
  4.   ref: gitlab-echo-template # TriggerTemplate 对象 

这样就可以将 TriggerBinding 中的参数传递到 TriggerTemplate 对象中进行模板化。比如这里我们定义一个如下所示的 TriggerBinding 对象:

  1. apiVersion: triggers.tekton.dev/v1alpha1 
  2. kind: TriggerBinding 
  3. metadata: 
  4.   name: devops-demo-binding 
  5. spec: 
  6.   params: 
  7.     - name: gitrevision 
  8.       value: $(body.checkout_sha) 
  9.     - name: gitrepositoryurl 
  10.       value: $(body.repository.git_http_url) 

这里需要注意的是参数的值我们是通过读取 GitLab WebHook 发送过来的数据值,通过 $() 包裹的 JSONPath 表达式来提取的,关于表达式的更多用法可以查看官方文档说明,至于能够提取哪些参数值,则可以查看 WebHook 的说明,比如这里我们是 GitLab Webhook 的 Push Hook,对应的请求体数据如下所示:

  1.   "object_kind""push"
  2.   "before""95790bf891e76fee5e1747ab589903a6a1f80f22"
  3.   "after""da1560886d4f094c3e6c9ef40349f7d38b5d27d7"
  4.   "ref""refs/heads/master"
  5.   "checkout_sha""da1560886d4f094c3e6c9ef40349f7d38b5d27d7"
  6.   "user_id": 4, 
  7.   "user_name""John Smith"
  8.   "user_username""jsmith"
  9.   "user_email""john@example.com"
  10.   "user_avatar""https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80"
  11.   "project_id": 15, 
  12.   "project":{ 
  13.     "id": 15, 
  14.     "name":"Diaspora"
  15.     "description":""
  16.     "web_url":"http://example.com/mike/diaspora"
  17.     "avatar_url":null
  18.     "git_ssh_url":"git@example.com:mike/diaspora.git"
  19.     "git_http_url":"http://example.com/mike/diaspora.git"
  20.     "namespace":"Mike"
  21.     "visibility_level":0, 
  22.     "path_with_namespace":"mike/diaspora"
  23.     "default_branch":"master"
  24.     "homepage":"http://example.com/mike/diaspora"
  25.     "url":"git@example.com:mike/diaspora.git"
  26.     "ssh_url":"git@example.com:mike/diaspora.git"
  27.     "http_url":"http://example.com/mike/diaspora.git" 
  28.   }, 
  29.   "repository":{ 
  30.     "name""Diaspora"
  31.     "url""git@example.com:mike/diaspora.git"
  32.     "description"""
  33.     "homepage""http://example.com/mike/diaspora"
  34.     "git_http_url":"http://example.com/mike/diaspora.git"
  35.     "git_ssh_url":"git@example.com:mike/diaspora.git"
  36.     "visibility_level":0 
  37.   }, 
  38.   "commits": [ 
  39.     { 
  40.       "id""b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327"
  41.       "message""Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information"
  42.       "title""Update Catalan translation to e38cb41."
  43.       "timestamp""2011-12-12T14:27:31+02:00"
  44.       "url""http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327"
  45.       "author": { 
  46.         "name""Jordi Mallach"
  47.         "email""jordi@softcatala.org" 
  48.       }, 
  49.       "added": ["CHANGELOG"], 
  50.       "modified": ["app/controller/application.rb"], 
  51.       "removed": [] 
  52.     }, 
  53.     { 
  54.       "id""da1560886d4f094c3e6c9ef40349f7d38b5d27d7"
  55.       "message""fixed readme"
  56.       "title""fixed readme"
  57.       "timestamp""2012-01-03T23:36:29+02:00"
  58.       "url""http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7"
  59.       "author": { 
  60.         "name""GitLab dev user"
  61.         "email""gitlabdev@dv6700.(none)" 
  62.       }, 
  63.       "added": ["CHANGELOG"], 
  64.       "modified": ["app/controller/application.rb"], 
  65.       "removed": [] 
  66.     } 
  67.   ], 
  68.   "total_commits_count": 4 

请求体中的任何属性都可以提取出来,作为 TriggerBinding 的参数,如果是其他的 Hook 事件,对应的请求体结构可以查看 GitLab 文档说明。

这样我们就可以在 TriggerTemplate 对象中通过参数来读取上面 TriggerBinding 中定义的参数值了,定义一个如下所示的 TriggerTemplate 对象,声明一个 TaskRun 的模板,定义的 Task 任务也非常简单,只需要在容器中打印出代码的目录结构即可:

  1. apiVersion: triggers.tekton.dev/v1alpha1 
  2. kind: TriggerTemplate 
  3. metadata: 
  4.   name: devops-demo-template 
  5. spec: 
  6.   params: # 定义参数,和 TriggerBinding 中的保持一致 
  7.     - name: gitrevision 
  8.     - name: gitrepositoryurl 
  9.   resourcetemplates: # 定义资源模板 
  10.     - apiVersion: tekton.dev/v1beta1 
  11.       kind: TaskRun # 定义 TaskRun 模板 
  12.       metadata: 
  13.         generateName: gitlab-run- # TaskRun 名称前缀 
  14.       spec: 
  15.         serviceAccountName: tekton-triggers-gitlab-sa 
  16.         taskSpec: # Task 任务声明 
  17.           resources: 
  18.             inputs: # 定义一个名为 source 的 git 输入资源 
  19.               - name: source 
  20.                 type: git 
  21.           steps: 
  22.             - name: show-path 
  23.               image: ubuntu # 定义一个执行步骤,列出代码目录结构 
  24.               script: | 
  25.                 #! /bin/bash 
  26.                 ls -la $(resources.inputs.source.path) 
  27.         resources: # 声明具体的输入资源参数 
  28.           inputs: 
  29.             - name: source # 和 Task 中的资源名保持一直 
  30.               resourceSpec: # 资源声明 
  31.                 type: git 
  32.                 params: 
  33.                   - name: revision 
  34.                     value: $(tt.params.gitrevision) # 读取参数值 
  35.                   - name: url 
  36.                     value: $(tt.params.gitrepositoryurl) 

需要注意在最后的 pipelineresource 中引用参数值的时候使用了一个 tt 的前缀。定义完过后,直接创建上面的资源对象,创建完成后会自动生成 EventListener 的 Pod 和 Service 对象:

  1. $ kubectl get svc -l eventlistener=gitlab-listener 
  2. NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE 
  3. el-gitlab-listener   ClusterIP   10.108.146.82   <none>        8080/TCP   7m56s 
  4. $ kubectl get pod -l eventlistener=gitlab-listener 
  5. NAME                                  READY   STATUS    RESTARTS   AGE 
  6. el-gitlab-listener-6b84cc6d8f-ppfhp   1/1     Running   0          7m9s 
  7. $ kubectl get eventlistener 
  8. NAME              ADDRESS                                                    AVAILABLE   REASON                       READY   REASON 
  9. gitlab-listener   http://el-gitlab-listener.default.svc.cluster.local:8080   False       MinimumReplicasUnavailable   False 

接下来我们就可以到 GitLab 的项目中配置 WebHook,注意需要配置 Secret Token,我们在上面的 Secret 对象中声明过:

 

Secret Token

创建完成后,我们可以测试下该 WebHook 的 Push events 事件,直接点击测试即可(如果使用自定义的域名则需要在 coredns 中添加映射),正常会返回 Hook executed successfully: HTTP 202 的提示信息,这个时候在 Kubernetes 集群中就会出现如下所示的任务 Pod:

  1. $ kubectl get pods -l triggers.tekton.dev/eventlistener=gitlab-listener 
  2. NAME                         READY   STATUS      RESTARTS   AGE 
  3. gitlab-run-lnqzv-pod-lp8lw   0/2     Completed   0          3m18s 
  4. $ kubectl get taskrun -l triggers.tekton.dev/eventlistener=gitlab-listener 
  5. NAME               SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME 
  6. gitlab-run-lnqzv   True        Succeeded   3m11s       2m48s 
  7. $ tkn taskrun logs gitlab-run-lnqzv 
  8. [git-source-source-hfrw6] {"level":"info","ts":1624446684.0399015,"caller":"git/git.go:169","msg":"Successfully cloned http://git.k8s.local/course/devops-demo.git @ 581b1986b6c038ca98a362e6a0b8e9acb55893e8 (grafted, HEAD) in path /workspace/source"
  9. [git-source-source-hfrw6] {"level":"info","ts":1624446684.0660462,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/source"
  10.  
  11. [show-path] total 36 
  12. [show-path] drwxr-xr-x 4 root root  163 Jun 23 11:11 . 
  13. [show-path] drwxrwxrwx 3 root root   20 Jun 23 11:11 .. 
  14. [show-path] -rw-r--r-- 1 root root 1804 Jun 23 11:11 .drone.yml 
  15. [show-path] drwxr-xr-x 8 root root  177 Jun 23 11:11 .git 
  16. [show-path] -rw-r--r-- 1 root root  192 Jun 23 11:11 .gitignore 
  17. [show-path] -rw-r--r-- 1 root root  375 Jun 23 11:11 Dockerfile 
  18. [show-path] -rw-r--r-- 1 root root 5101 Jun 23 11:11 Jenkinsfile 
  19. [show-path] -rw-r--r-- 1 root root  174 Jun 23 11:11 README.md 
  20. [show-path] -rw-r--r-- 1 root root   97 Jun 23 11:11 go.mod 
  21. [show-path] -rw-r--r-- 1 root root 3370 Jun 23 11:11 go.sum 
  22. [show-path] drwxr-xr-x 3 root root  101 Jun 23 11:11 helm 
  23. [show-path] -rw-r--r-- 1 root root  471 Jun 23 11:11 main.go 

到这里我们就完成了通过 GitLab 的 Push 事件来触发 Tekton 的一个任务。

gitlab push events

接下来我们再来实现将我们的应用通过 Tekton 来自动部署到 Kubernetes 集群中。

 

责任编辑:姜华 来源: k8s技术圈
相关推荐

2021-04-27 22:32:01

TektonKubernetesCI

2022-04-14 07:51:39

TektonTaskRun

2022-04-25 08:07:45

TektonArgocdCI和CD

2022-03-21 09:40:48

TektonJenkinsPipeline

2022-06-02 10:18:24

函数计算异步

2023-01-03 10:38:04

函数计算技术

2023-04-18 08:17:11

GitLab持续集成

2022-04-08 09:53:56

TektonJenkinsKubesphere

2022-08-11 16:29:32

Tekton流水线迁移工作流

2023-08-18 10:24:52

GitLabCI 流水线

2021-06-28 14:13:35

Jenkins服务器程序

2022-07-27 07:39:45

Kubernetes云原生

2011-02-25 10:02:04

ibmdwWebsphere

2017-03-13 09:12:00

TCP数据结构请求包

2021-07-09 06:40:59

TektonArgo CD GitOps

2021-05-13 18:23:53

Tekton云原生Kubernetes

2021-06-26 14:22:34

Tekton流水线Kubernetes

2021-06-28 06:32:46

Tekton Kubernetes Clone

2022-04-01 10:51:33

TektonArgoCDGitOps

2023-11-16 09:30:27

系统任务
点赞
收藏

51CTO技术栈公众号