jenkins-gitops-ci

阅读量: zyh 2020-03-26 14:32:11
Categories: > Tags:

目的

gitlab 推送后,jenkins 可以自动执行流水线。

流程:

用户推送代码到gitlab工程 -》 gitlab 收到推送信息到 jenkins webhook -》Jenkins 收到gitlab的事件 -》根据 Jenkins 流水线工程配置的可执行事件来启动流水线工程 -》 执行pipeline(从配置的scm里获取) -》根据 pipeline 执行代码拉取、代码测试、代码打包、docker镜像包、docker镜像推送。

涉及到的插件

涉及到的账户

操作步骤

  1. gitlab - 管理中心 - 设置 - 网络 - 外发请求 - 允许Webhook和服务对本地网络的请求(启用)

    ✨仅当jenkins通过内网访问gitlab的时候需要.

  2. 在 gitlab 上创建 Jenkins 专属用户 jenkins.

  3. 生成 jenkins 用户拉取代码的凭证

    ✨当jenkins通过ssh方式拉取代码:

    jenkins 创建证书凭据,并将公钥放在 gitlab 专属用户 jenkins 上

    ✨当jenkins通过http方式拉取代码:

    gitlab 专属用户 jenkins 创建 read_repository 级别的访问令牌

  4. 生成 jenkins 回传工程执行过程到 gitlab ci 的凭证

    ✨创建 API级别的访问令牌,且用户必须是 git 项目 Maintainer 用户,否则 jenkins 无法将工程结果回传给 gitlab

  5. 在 jenkins 上添加拉取代码的凭据gitlab-jenkins-ro-token

    ✨以 http 方式为例,凭据类型 Username with password。password是 gitlab 专属用户 jenkins 的read_repository级别的访问令牌

  6. 授权 Jenkins 访问 gitlab api。

    1. jenkins 安装 gitlab 插件,并创建凭据gitlab-jenkins-api-token,凭据类型为Gitlab api token,将 gitlab 专属用户 jenkins 的API级别的访问令牌填入。
    2. jenkins 启用和配置 gitlab 插件。

image-20220327163856124

  1. 流水线工程启用 gitlab 事件推送,从而获取 jenkins 提供 webhook 地址,便于 gitlab 将代码变更事件推送到 jenkins.

✨截图里黑色区域,即为jenkins为当前流水线工程创建的webhook地址

image-20220327164429407

点击【高级】,即可弹出高级配置,从而可以给 webhook 地址创建 token

image-20220327164615263

  1. 打开对应的 gitlab 工程 - 设置 - webhooks,将上一步骤里的 webhooks 地址和 token 填入其中。

  2. 将Pipeline文件Jenkinsfile放入gitlab工程中,并将jenkins工程的pipeline通过scm指向gitlab工程。

    ✨scm调用gitlab-jenkins-ro-token凭据。

配置仓库的Jenkinsfile

pipeline{
    agent {
        node {
            label "agent01"
        }
    }
    options {
        gitLabConnection('gitlab')          // 链接到 gitlab 上
    }
    environment {
	    dockerImage = ""                                                                  // 空的环境变量名
    }
    stages {
        stage("set custom env"){
            steps{
                script{
                    imageName = env.GIT_URL.split("/|\\.")[-2]
                    imageTag = env.GIT_COMMIT.take(8)                                 // 获取 git commit short id
                    appVersion = env.BRANCH_NAME + "-" + imageTag                     // 镜像标签
                    if (env.BRANCH_NAME == 'master') {
                        registryCredential = "registry-apps_acr-rw"                       // 镜像注册表登录凭据名,需提前在jenkins凭据功能里添加
	                    registryUrl = "https://registry-vpc.cn-zhangjiakou.aliyuncs.com/" // 镜像注册表地址
	                    registryNamespace = "pj-zjk-it"                                   // gitlab组/registry命名空间
                    } else {
                        registryCredential = "registry-jenkins_harbor-rw"                       
	                    registryUrl = "https://localhbgg.pengwin.com:10443" 
	                    registryNamespace = env.GIT_URL.split("/|\\.")[-3]
                    }
                }
            }
        }
        stage("code: pull") {
            steps {
                cleanWs()
                script {
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'running'
                    try {
                        checkout scm
                    } catch(Exception ex) {
                        updateGitlabCommitStatus name: env.STAGE_NAME, state: 'failed'
                        throw ex;
                    }
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'success'
                }
            }
        }
        stage("code: test") {
            steps {
                script {
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'running'
                    try {
                        echo "单元测试"
                    } catch(Exception ex) {
                        updateGitlabCommitStatus name: env.STAGE_NAME, state: 'failed'
                        throw ex;
                    }
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'success'
                }
            }
        }
        stage('docker: build') {
			steps {
                script {
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'running'
                    try {
                        dockerImage = docker.build( registryNamespace + "/" + imageName + ":" +appVersion, "docker")  
                        // build方法接收两个参数,第一个是镜像tag,第二个是dockerfile在代码里的相对目录
                    } catch(Exception ex) {
                        updateGitlabCommitStatus name: env.STAGE_NAME, state: 'failed'
                        throw ex;
                    }
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'success'
                }
			}
		}
        stage('docker: push') {
			steps {
                script {
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'running'
                    try {
                        docker.withRegistry( registryUrl, registryCredential ) {   // 登录注册表
                            dockerImage.push()                                     // dockerImage 即上一阶段的 dockerImage 变量.
                        }
                    } catch(Exception ex) {
                        updateGitlabCommitStatus name: env.STAGE_NAME, state: 'failed'
                        throw ex;
                    }
                    updateGitlabCommitStatus name: env.STAGE_NAME, state: 'success'
                }
			}
		}
    }
    post {
        success{
            updateGitlabCommitStatus name: env.STAGE_NAME, state: 'success'
            //成功清理工作空间,失败保留现场
            cleanWs()
        }
        failure{
            updateGitlabCommitStatus name: env.STAGE_NAME, state: 'failed'
            //成功清理工作空间,失败保留现场
            cleanWs()
        }
    }
}