栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 前沿技术 > 云计算

Tekton系列之实践篇-由Jenkins改成Tekton

云计算 更新时间:发布时间: 百科书网 趣学号


Tekton系列之实践篇-由Jenkins改成Tekton

在《​​Tekton系列之实践篇-我的第一条Pipeline​​》中我们已经实现了第一条流水线,但是这条流水线还是比较简单,完成了基础的功能。这篇文章带你怎么根据Jenkins的Jenkinsfile来定制自己的Tekton Pipeline。

首先我们来看看Jenkinsfile中是什么样子,如下:

// 引入方法
def dingmes = new org.devops.sendDingTalk()
def BUILD_USER
def IS_IMAGE_PUSH

pipeline {
agent {
kubernetes {
label "jenkins-slave-${UUID.randomUUID().toString()}"
yaml """
apiVersion: v1
kind: Pod
spec:
nodeSelector:
kubernetes.io/hostname: node-2
containers:
- name: gradle
image: registry.cn-hangzhou.aliyuncs.com/coolops/builder-gradle:v2
command: ['cat']
tty: true
volumeMounts:
- name: caches
mountPath: /root/.gradle/caches/
- name: indocker
mountPath: /var/run/docker.sock
- name: helm
image: registry.cn-hangzhou.aliyuncs.com/coolops/helm3:3.2.4
command: ['cat']
tty: true
- name: sonar
image: registry.cn-hangzhou.aliyuncs.com/coolops/gradle:5.6.4-jdk11
command: ['cat']
tty: true
volumeMounts:
- name: sonarcache
mountPath: /root/.gradle/caches/
volumes:
- name: caches
hostPath:
path: "/data/jenkins-job/${JOB_NAME}/gradle/"
- name: indocker
hostPath:
path: "/var/run/docker.sock"
- name: sonarcache
hostPath:
path: "/data/jenkins-job/${JOB_NAME}/sonar/"
"""
}
}
environment {
APP_NAME = "${params.APP_NAME}"
DOCKER_CREDENTIAL_ID = 'dockerhub-token'
GIT_CREDENTIAL_ID = 'git-token'
SONAR_CREDENTIAL_ID = 'sonar-token'
KUBECONFIG_CREDENTIAL_ID = 'kubeconfig-token'
REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'
DOCKERHUB_NAMESPACE = 'coolops'
CHART = 'coolops/rd'
CHART_USERNAME=xxx
CHART_PASSWORD=xxx
IMG_REPO = "$REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME"
IMG_TAG = "$GIT_COMMIT"
COMMON_ARGS = "--set image.repository=$IMG_REPO
--set image.tag=$IMG_TAG
--set ingress.hosts[0].paths[0]=/ "
}

parameters {
choice(description: '通过 Gradle --refresh-dependencies 参数进行 Jar 包强制刷新', name: 'refresh', choices: ['false', 'true'])
}

options {
timeout(time: 30, unit: 'MINUTES')
}

stages {
stage('Checkout SCM') {
steps {
checkout(scm)
}
}
stage('Build & Push') {
steps {
container('gradle') {
withCredentials([usernamePassword(credentialsId: "$DOCKER_CREDENTIAL_ID", passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh '''
export EXIST_IMG=$(docker pull $IMG_REPO:$IMG_TAG &>/dev/null && echo true || echo false)
echo $EXIST_IMG
if [ $refresh == "true" -o $EXIST_IMG == "false" ]
then
echo "开始编译并推送镜像" ;
$refresh && gradle clean bootJar --configure-on-demand --build-cache --refresh-dependencies || gradle clean bootJar --configure-on-demand --build-cache
docker build -f Dockerfile -t $IMG_REPO:$IMG_TAG . ;
docker push $IMG_REPO:$IMG_TAG ;
else
echo "镜像已存在,跳过编译";
fi
'''
}
}
}
}
stage('helm3 add repo') {
steps {
container('helm') {
withCredentials([kubeconfigContent(credentialsId : 'kubeconfig-token' ,variable : 'kubconfig' ,)]) {
sh '''
set +x
mkdir ~/.kube/
echo "$kubconfig" > ~/.kube/config
'''
sh 'helm repo add coolops https://repomanage.rdc.aliyun.com/helm_repositories/66465-coolops --username=${CHART_USERNAME} --password=${CHART_PASSWORD}'
}
}
}
}
}
stage('Deploy To Dev') {
environment {
NAMESPACE = 'coolops-dev'
ENV = 'dev'
}
when {
expression {
return "$BRANCH_NAME".contains('dev')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To test') {
environment {
NAMESPACE = 'coolops-test'
ENV = 'test'
}
when {
expression {
return "$BRANCH_NAME".contains('test')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To Uat') {
environment {
NAMESPACE = 'coolops-uat'
ENV = 'uat'
}
when {
expression {
return "$BRANCH_NAME".contains('uat')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}

stage('Deploy To Pre') {
environment {
NAMESPACE = 'coolops-pre'
ENV = 'pre'
}
when {
expression {
return "$BRANCH_NAME".contains('pre')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To Prod') {
environment {
NAMESPACE = 'coolops-prod'
ENV = 'prod'
}
when {
expression {
return "$BRANCH_NAME".contains('prod')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
// 扫描
stage('Sonarqube Scanner') {
when {
expression {
return "$JOB_NAME".contains('skip')
}
}
steps {
timeout(time:20,unit:'MINUTES'){
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
container('sonar') {
sh 'gradle sonarqube
-x test
-Dsonar.host.url=http://sonar.coolops.cn
-Dsonar.login=c17650fa820d985daf1f29d8a3f685d789e47e45'
}
}
}
}
}
}
}

整体的Jenkinsfile我做了一些删减,但是整个流程是没变的,咋一看是不是同样很简单?我将步骤整理如下:

  • 从代码仓库拉取代码。
  • 编译代码并推送到仓库。
  • 根据不同的分支推送到不同的环境。
  • 代码扫描。

    整体的流程和上一篇文章没太大不同,区别在于:

  • 多分支流水线发布。
  • 由kubectl改成了helm chart。
  • 新增了代码扫描。

    这里采用Helm Chart来部署应用,我使用的是阿里云的Chart仓库。不会使用的朋友可以通过阿里云-->云效DevOps-->研发-->私有仓库进行申请。


    Tekton系列之实践篇-由Jenkins改成Tekton

    我们现在先创建Task,然后再组装Pipeline。

    使用Helm Chart发布应用Task

    我们在之前的文章中使用的是kubectl来发布应用,由于在我实际的使用过程中,是使用的Helm来管理的,为了保持一致,这里先创建一个Helm发布应用的Task。

    在创建之前,我们先来看看有哪些地方是需要参数的:

  • namespace:由于我是不同环境不同的namespace,所以在多分支发布的时候需要指定namespace。
  • app_name:应用名。
  • chart_name:helm chart 名。
  • args:helm chart 的其他参数。

    所以我们定义的Task如下:

    apiVersion: tekton.dev/v1alpha1
    kind: Task
    metadata:
    name: helm-to-k8s
    spec:
    workspaces:
    - name: source
    - name: kubernetesconfig
    mountPath: /root/.kube
    params:
    - name: IMAGE
    - name: TAG
    - name: NAMESPACE
    - name: BRANCH_NAME
    - name: CHART_NAME
    - name: CHART_USERNAME
    - name: CHART_PASSWORD
    - name: APP_NAME
    steps:
    - name: run-helm
    image: registry.cn-hangzhou.aliyuncs.com/coolops/helm3:3.2.4
    workingDir: $(workspaces.source.path)
    script: |
    helm repo add coolops https://repomanage.rdc.aliyun.com/helm_repositories/66465-coolops --username=$(params.CHART_USERNAME) --password=$(params.CHART_PASSWORD)
    common_args="--set image.repository=$(params.IMAGE) --set image.tag=$(params.TAG) --set ingress.hosts[0].paths[0]=/"
    helm -n $(params.NAMESPACE) upgrade $(params.APP_NAME) $(params.CHART_NAME) ${common_args} ||
    helm -n $(params.NAMESPACE) install $(params.APP_NAME) $(params.CHART_NAME) ${common_args}

    代码扫描Task

    由于在Jenkins中使用了代码扫描,所以这里加一个代码扫描的Task,如下:

    apiVersion: tekton.dev/v1alpha1
    kind: Task
    metadata:
    name: sonar-scanner
    spec:
    workspaces:
    - name: source
    params:
    - name: SONAR_USERNAME
    - name: SONAR_PASSWORD
    - name: SONAR_URL
    - name: APP_NAME
    steps:
    - name: sonar-scanner
    image: registry.cn-hangzhou.aliyuncs.com/coolops/sonar-scanner:2.2.0
    workingDir: $(workspaces.source.path)
    script: |
    scanTime=`date +%F-%H-%M-%S`
    sonar-scanner -Dsonar.host.url=$(params.SONAR_URL)
    -Dsonar.projectKey=$(params.APP_NAME)
    -Dsonar.projectName=$(params.APP_NAME)
    -Dsonar.projectVersion=${scanTime}
    -Dsonar.login=$(params.SONAR_USERNAME)
    -Dsonar.password=$(params.SONAR_PASSWORD)
    -Dsonar.projectDescription="$(workspaces.source.path)"

    需要新增的Task就这两个,接下来就是组装Pipeline了,多分支发布也是在Pipeline中组装。

    整合Pipeline

    在整合Pipeline之前,还是先来梳理一下流程:

  • 拉代码。
  • 编译构建、推送镜像。
  • 发布应用----多环境。
  • 代码扫描。
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
    name: rd-pipeline
    spec:
    workspaces: # 声明 workspaces
    - name: rd-repo-pvc
    - name: docker-config
    - name: kubernetes-config
    params:
    # 定义代码仓库
    - name: git_url
    - name: revision
    type: string
    default: "master"
    - name: gitInitImage
    type: string
    default: "registry.cn-hangzhou.aliyuncs.com/coolops/tekton-git-init:v0.29"
    # 定义镜像参数
    - name: pathToDockerfile
    description: The path to the build context, used by Kaniko - within the workspace
    default: .
    - name: imageUrl
    description: Url of image repository
    - name: imageTag
    description: Tag to apply to the built image
    default: latest
    - name: chart_name
    type: string
    default: coolops/coolops-rd
    - name: chart_username
    type: string
    - name: chart_password
    type: string
    - name: app_name
    type: string
    - name: namespace
    type: string
    default: default
    # 定义代码扫描
    - name: sonar_username
    type: string
    default: admin
    - name: sonar_password
    type: string
    default: admin
    - name: sonar_url
    type: string
    tasks: # 添加task到流水线中
    - name: clone
    taskRef:
    name: git-clone
    workspaces:
    - name: output
    workspace: rd-repo-pvc
    params:
    - name: url
    value: $(params.git_url)
    - name: revision
    value: $(params.revision)
    - name: gitInitImage
    value: $(params.gitInitImage)
    - name: unit-test
    workspaces: # 传递 workspaces
    - name: source
    workspace: rd-repo-pvc
    taskRef:
    name: unit-test
    runAfter:
    - clone
    - name: build-push-image
    params:
    - name: pathToDockerfile
    value: $(params.pathToDockerfile)
    - name: imageUrl
    value: $(params.imageUrl)
    - name: imageTag
    value: $(tasks.clone.results.commit)
    taskRef:
    name: build-push-image
    runAfter:
    - unit-test
    workspaces: # 传递 workspaces
    - name: source
    workspace: rd-repo-pvc
    - name: dockerconfig
    workspace: docker-config
    - name: deploy-to-dev
    when:
    - input: $(params.revision)
    operator: in
    values:
    - dev
    taskRef:
    name: helm-to-k8s
    params:
    - name: IMAGE
    value: $(params.imageUrl)
    - name: TAG
    value: $(tasks.clone.results.commit)
    - name: BRANCH_NAME
    value: $(params.revision)
    - name: CHART_NAME
    value: $(params.chart_name)
    - name: CHART_USERNAME
    value: $(params.chart_username)
    - name: CHART_PASSWORD
    value: $(params.chart_password)
    - name: APP_NAME
    value: $(params.app_name)
    - name: NAMESPACE
    value: coolops-dev
    workspaces:
    - name: source
    workspace: rd-repo-pvc
    - name: kubernetesconfig
    workspace: kubernetes-config
    runAfter:
    - build-push-image
    - name: deploy-to-test
    when:
    - input: $(params.revision)
    operator: in
    values:
    - test
    taskRef:
    name: helm-to-k8s
    params:
    - name: IMAGE
    value: $(params.imageUrl)
    - name: TAG
    value: $(tasks.clone.results.commit)
    - name: BRANCH_NAME
    value: $(params.revision)
    - name: CHART_NAME
    value: $(params.chart_name)
    - name: CHART_USERNAME
    value: $(params.chart_username)
    - name: CHART_PASSWORD
    value: $(params.chart_password)
    - name: APP_NAME
    value: $(params.app_name)
    - name: NAMESPACE
    value: coolops-test
    workspaces:
    - name: source
    workspace: rd-repo-pvc
    - name: kubernetesconfig
    workspace: kubernetes-config
    runAfter:
    - build-push-image
    - name: deploy-to-pre
    when:
    - input: $(params.revision)
    operator: in
    values:
    - pre
    taskRef:
    name: helm-to-k8s
    params:
    - name: IMAGE
    value: $(params.imageUrl)
    - name: TAG
    value: $(tasks.clone.results.commit)
    - name: BRANCH_NAME
    value: $(params.revision)
    - name: CHART_NAME
    value: $(params.chart_name)
    - name: CHART_USERNAME
    value: $(params.chart_username)
    - name: CHART_PASSWORD
    value: $(params.chart_password)
    - name: APP_NAME
    value: $(params.app_name)
    - name: NAMESPACE
    value: coolops-pre
    workspaces:
    - name: source
    workspace: rd-repo-pvc
    - name: kubernetesconfig
    workspace: kubernetes-config
    runAfter:
    - build-push-image
    - name: deploy-to-prod
    when:
    - input: $(params.revision)
    operator: in
    values:
    - prod
    taskRef:
    name: helm-to-k8s
    params:
    - name: IMAGE
    value: $(params.imageUrl)
    - name: TAG
    value: $(tasks.clone.results.commit)
    - name: BRANCH_NAME
    value: $(params.revision)
    - name: CHART_NAME
    value: $(params.chart_name)
    - name: CHART_USERNAME
    value: $(params.chart_username)
    - name: CHART_PASSWORD
    value: $(params.chart_password)
    - name: APP_NAME
    value: $(params.app_name)
    - name: NAMESPACE
    value: coolops-prod
    workspaces:
    - name: source
    workspace: rd-repo-pvc
    - name: kubernetesconfig
    workspace: kubernetes-config
    runAfter:
    - build-push-image
    - name: sonar-scanner
    when:
    - input: $(params.revision)
    operator: in
    values:
    - test
    taskRef:
    name: sonar-scanner
    runAfter:
    - clone
    params:
    - name: SONAR_USERNAME
    value: $(params.sonar_username)
    - name: SONAR_PASSWORD
    value: $(params.sonar_password)
    - name: SONAR_URL
    value: $(params.sonar_url)
    - name: APP_NAME
    value: $(params.app_name)
    workspaces:
    - name: source
    workspace: rd-repo-pvc

    编排一个PipelineRun运行一下,如下:

    apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
    name: test-hello-world-pipeline-run
    spec:
    pipelineRef:
    name: rd-pipeline
    params:
    - name: revision
    value: test
    - name: git_url
    value: https://gitee.com/coolops/devops-hello-world.git
    - name: imageUrl
    value: registry.cn-hangzhou.aliyuncs.com/coolops/devops-hello-world
    - name: imageTag
    value: latest
    - name: pathToDockerfile
    value: Dockerfile
    - name: chart_username
    value: username
    - name: chart_password
    value: password
    - name: app_name
    value: hello-world
    - name: sonar_username
    value: username
    - name: sonar_password
    value: password
    - name: sonar_url
    value: http://sonarqube.coolops.cn
    workspaces:
    - name: rd-repo-pvc
    volumeClaimTemplate:
    spec:
    accessModes:
    - ReadWriteOnce
    storageClassName: openebs-hostpath
    resources:
    requests:
    storage: 1Gi
    - name: docker-config
    secret:
    secretName: docker-config
    - name: kubernetes-config
    secret:
    secretName: kubernetes-config
    serviceAccountName: tekton-build-sa

    运行效果如下:


    Tekton系列之实践篇-由Jenkins改成Tekton

    上面只是把应用部署到同一个集群得不同namespace下,在实际情况下可能有多个集群,我们只需要指定不同的kubernetes-config即可,当然, 需保证Tekton所在的集群能与其他集群相通。

    sonar上的扫描结果如下:


    Tekton系列之实践篇-由Jenkins改成Tekton

    总结

    从Jenkins迁移到Tekton,主要就是Pipeline的改写,但是从整体来看并不复杂,因为Jenkins中的过程都是定义好的,我们只需要按它的步骤改造成Tekton适配的语法即可。

  • 转载请注明:文章转载自 www.051e.com
    本文地址:http://www.051e.com/it/797035.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 ©2023-2025 051e.com

    ICP备案号:京ICP备12030808号