乔克
乔克
Published on 2024-11-15 / 22 Visits
0
0

Tekton系列之实践篇-如何用Jenkins来管理Tekton

在《Tekton 系列之实践篇 - 由 Jenkins 改成 Tekton》中,我们可以将 Jenkinsfile 改成 Tekton Pipeline,但是 Tekton 有一个很大的问题是不能很好的划分权限,特别是在 Dashboard 上根本就做权限控制,那如果在实际中使用的话权限不明会带来很多问题,比如谁删了什么,谁执行了什么都不知道。

如果你公司有自动化运维平台,可以接入 Tekton,如果没有就需要在 Github 上找是否有相关的 Dashboard 或者平台,可惜我什么都没有…

目前我使用的 Kubesphere 来管理 K8s 集群以及流水线,所以我就在想怎么使用 kubesphere 管理。不过截止目前版本,Kubesphere 的流水线引擎还是 Jenkins,除非二开,不然没办法直接继承 Tekton,期待 Kubesphere 把 Tekton 也加入(https://github.com/kubesphere/community/blob/master/sig-advocacy-and-outreach/summer-ospp/kubeSphere-tekton-integration_zh-CN.md)。

那应该怎么做呢?我想到一个很牛逼(SB)的办法,如下:
图片.pngkubesphere-tekton.png

看懂了么?

其实就是继续使用 Jenkins 做 Kubesphere 的流水线引擎,然后将 Jenkins 和 Tekton 进行打通,这样是不是间接使用了 Tekton?这是不是一个很牛逼(SB)的 idea?

但是悲剧来了,Jenkins 的 Tekton 插件要求 Jenkins 最低的版本是 2.263,而 Kubesphere 的 Jenkins 版本是 2.49,而且升级非常麻烦,麻烦到官方都不建议升级的地步。所以这里只能退而求其次,进使用 Jenkins 来进行实验了。

部署 Jenkins

Jenkins 的部署方式有很多,这里采用 Helm 的方式来部署,简单快捷。

首先需要安装 Helm 命令,见文档(https://helm.sh/docs/intro/install/)。

接着安装 Jenkins,如下:

helm repo add jenkinsci https://charts.jenkins.io
helm repo update
# 我习惯把CHART下载到本地,方便管理
helm pull jenkinsci/jenkins
# 这里有一步解压的过程,然后进入Jenkins目录进行部署
# 部署
kubectl create ns devops
helm install jenkins -n devops .

部署完成后即可进行登录了。

访问地址要么使用 NodePort,要么使用 ingress,这里没有展示配置过程。

安装 Jenkins 插件

为了实现上面的需求,我找到一个 Jenkins 插件可以用来管理 Tekton,插件名叫 tekton-client-plugin
tekton-client-plugin(https://github.com/jenkinsci/tekton-client-plugin)。

tekton-client-plugin 用来打通 Jenkins 和 Tekton,功能也不复杂,可以到文档(https://plugins.jenkins.io/tekton-client/#documentation)进行学习。

如果 Jenkins 版本大于 2.263,可以直接在插件中心下载,如下:
图片.png

配置权限

这里是权限是 Jenkins 操作 Tekton 的权限,如下:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tekton-role
  namespace: tekton-devops-pipeline
rules:
  - apiGroups:
      - ""
    resources:
      - pods
      - pods/log
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - tekton.dev
    resources:
      - tasks
      - taskruns
      - pipelines
      - pipelineruns
    verbs:
      - create
      - delete
      - deletecollection
      - get
      - list
      - patch
      - update
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tekton-role-binding
  namespace: tekton-devops-pipeline
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: tekton-role
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: devops

注意授权的 serviceaccount 和 namespace。

编写 Jenkinsfile

要使用的 Jenkinsfile 其实很简单。但是由于我们是多分支发布,所以 Jenkinsfile 如下:

pipeline {
  agent any

  parameters {
        choice(description: '选择分支',  name: 'BRANCH_NAME', choices: ['dev', 'test', 'uat', 'pre', 'prod'])
    }

  stages {
    stage('deploy to dev'){
        when{
          expression {
            return "$BRANCH_NAME".contains('dev')
          }
        }
        steps{
            tektonCreateRaw input: 'deploy/dev/pipeline.yaml', inputType: 'FILE', namespace: 'tekton-devops-pipeline'
        }
    }
    stage('deploy to test'){
        when{
          expression {
            return "$BRANCH_NAME".contains('test')
          }
        }
        steps{
            tektonCreateRaw input: 'deploy/test/pipeline.yaml', inputType: 'FILE', namespace: 'tekton-devops-pipeline'
        }
    }
    stage('deploy to uat'){
        when{
          expression {
            return "$BRANCH_NAME".contains('uat')
          }
        }
        steps{
            tektonCreateRaw input: 'deploy/uat/pipeline.yaml', inputType: 'FILE', namespace: 'tekton-devops-pipeline'
        }
    }
    stage('deploy to pre'){
        when{
          expression {
            return "$BRANCH_NAME".contains('pre')
          }
        }
        steps{
            tektonCreateRaw input: 'deploy/pre/pipeline.yaml', inputType: 'FILE', namespace: 'tekton-devops-pipeline'
        }
    }
    stage('deploy to prod'){
        when{
          expression {
            return "$BRANCH_NAME".contains('prod')
          }
        }
        steps{
            tektonCreateRaw input: 'deploy/prod/pipeline.yaml', inputType: 'FILE', namespace: 'tekton-devops-pipeline'
        }
    }
  }
}

Tekton 的 PipelineRun 按目录分级,如下(这里只是为了方便,其实可以只用一个 PipelineRun):
图片.png

弄完过后,就可以创建流水线了,如下创建一个 hello-world-test 的流水线。
图片.png

然后选择对应的分支进行部署。可以看到触发了 Tekton 的 PipelineRun,如下:
图片.png

不过 Jenkins 这边还有如下问题:

[Checks API] No suitable checks publisher found.
Failed: null
java.lang.NullPointerException
	at org.waveywaves.jenkins.plugins.tekton.client.build.create.CreateRaw.createPipelineRun(CreateRaw.java:278)
	at org.waveywaves.jenkins.plugins.tekton.client.build.create.CreateRaw.createWithResourceSpecificClient(CreateRaw.java:168)
	at org.waveywaves.jenkins.plugins.tekton.client.build.create.CreateRaw.runCreate(CreateRaw.java:429)
	at org.waveywaves.jenkins.plugins.tekton.client.build.create.CreateRaw.perform(CreateRaw.java:393)
	at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:101)
	at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:71)
	at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)

[Checks API] No suitable checks publisher found.

虽然报这个错,但是 Tekton PipelineRun 触发没问题,具体原因还待排查,这就非常尴尬了。看到下面这一串串的红色,心凉了一半(Tekton 实际是可以允许成功)。
图片.png

最后

其实这篇实践不算完成,Jenkins 的问题还没有解决,在网上查了半天资料也没什么效果,很多说是 Jenkins Check-API 插件的原因,但是没有去测试。

不过,从理论上用 Jenkins 来管理 Tekton 是可行的,而且对于 Jenkins 重度用户来说,也算是比较不错的事情。当然我更想使用类似于 Kubesphere 这类来管理,期待 Kubesphere 把 Tekton 集成进去。


Comment