Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S

这篇具有很好参考价值的文章主要介绍了Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、为什么是jenkinsfile

上文我们说了pipeline,已为本文铺路不少,接下里就是将之串联起来。
先想说下,为什么是jenkinsfile, 因为jenkins job还支持pipeline方式。
Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S,ci/cd,jenkins
这种方式,不建议实际使用,仅限于测试或调试groovy代码。

下面贴出来,我们的使用方式。好处是:采用分布式的思想,改动git上的jenkinsfile,就可以让所有的job更新。
Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S,ci/cd,jenkins

二、jenkinsfile的参数

这也有两种方式,我反而又不建议你写在jenkinsfile里。

  • Job (建议方式,因为每个工程的参数不一样,需要持久化保存)
  • jenkinsfile

Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S,ci/cd,jenkins
对于java语言来说, 我梳理了以下几个必须参数:

  • jarName
  • port
  • projectName(消息通知)
  • codeUrl
  • branch

为了一些额外需求,我们还定义了几个扩展参数:

  • packageType(打包方式,mvn或者gradle。默认为mvn)
  • robotKey(消息通知的机器人robot,默认为空)
  • childModule(子模块, 用于一个多module的项目打包,指定某模块以发布。默认为空)

三、groovy编码的几点建议

1、变量一定要使用trim()方法

举例,shell命令读取程序版本号,返回值如果没有使用trim(),会额外多一个换行符。-- 后期在使用该变量拼接的时候,很容易就把明明一行执行的,硬生生地被拆成了两行执行。

// 读取java应用的版本号
def getAppVersion(packagePath) {
    def appVersion = sh returnStdout: true,
            script: """
                    grep 'git.build.version' ${packagePath}/classes/git.properties | cut -d'=' -f2 | sed 's/\\r//'
                    """
    // trim()
    return appVersion.trim()
}

// 镜像版本号
def dockerImageVersion = appVersion + "-001"

docker build -f ${dockerfileName} -t ${repoProject}/${appName}:${dockerImageVersion} .
// 如果你没有使用trim()的话, 上面的这行代码,就会变成:
docker build -f ${dockerfileName} -t ${repoProject}/${appName}:${dockerImageVersion}
// 我还在纳闷,怎么最后的.被谁吃掉了呢。。。
// 当你期望的是
docker build -f /opt/Dockerfile -t xxx/devops-service:1.0.7-001 .

// 实际却是:
docker build -f /opt/Dockerfile -t xxx/devops-service:1.0.7

2、引入pipeline library

这里的名称,对应前文配置中的name

为了避免jenkinsfile的代码量过于复杂,我们往往会抽取出公共的方法。

@Library('jenkinslib') _

def tools = new com.xhtech.devops.tools()

tools.PrintMes("pull code!!!", "green")

3、读取参数

这里的参数分为两种,一是自定义,一是系统自带。

  • 字符串类型的变量,后面都紧跟着trim()方法。
// JOB_NAME是系统自带
String jobName = "${env.JOB_NAME}".trim()

// jarName是我们在job的参数化构建中配置
String jarName = "${env.jarName}".trim()

4、运行shell命令

// 正确的写法,必须由script括起来
script {
    sh "mvn clean package -Dmaven.test.skip=true -U"                
}

5、切换目录

dir("${env.WORKSPACE}") 

6、指定容器

默认容器是jnlp, 如果你的Pod配置了多个容器,docker image的相关操作就必须在docker容器里执行。

  • container(‘docker’),这里的docker就是对应PodTemplate中的容器名称。
container('docker') {
    dir("${env.WORKSPACE}") {
        docker.buildAndPushImage(jarName, port, dockerImageVersion, packagePath, dockerfileName)
    }
}

7、归档archiveArtifacts

把版本号写入到文件,并且归档

dir("${env.WORKSPACE}") {
    sh "echo ${appVersion} > version_${appVersion}.txt"

    archiveArtifacts artifacts: 'version_*.txt', followSymlinks: false
}

Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S,ci/cd,jenkins

8、设置操作的超时时间

timeout(time: 1, unit: "MINUTES") {
  // 具体操作,预计在1分钟内完成
}

9、指定工作空间

我们把工作空间持久化到某个目录,而不是放在Pod里。这样的好处是:起到了缓存的作用,不会随着Pod的销毁而需重建。

// 我们会对/opt/.m2进行持久化操作
String sharefile = "/opt/.m2"
String jobName = "${env.JOB_NAME}".trim()

String PROJECT_WORKSPACE = "$sharefile/java-workspaces/$jobName"

agent {
    kubernetes {
        inheritFrom 'jnlp-maven'
        customWorkspace "${PROJECT_WORKSPACE}"
    }
}

10、清理空间

安装jenkins plugin: Workspace Cleanup

// 文档地址: https://plugins.jenkins.io/ws-cleanup/

stage('Clean Workspace') {
    steps {
        cleanWs()
    }
}

四、完整的java-k8s.jenkinsfile


#!groovy

@Library('jenkinslib') _

String sharefile = "/opt/.m2"
String dockerfileName = sharefile + "/" + "Dockerfile"

// java代码仓库gitlab的ssh密钥
String gitlabCredentialsId = "ffcbbd41-1e6a-49ec-8277-87a1299606dd"

def tools = new com.xxtech.devops.tools()
def http = new com.xxtech.devops.http()
def docker = new com.xxtech.devops.docker()
def helm = new com.xxtech.devops.helm()

// OA:项目管理--研发项目--产品列表中的英文名称
String projectName = "${env.projectName}".trim()

// jenkins job
String jobName = "${env.JOB_NAME}".trim()

// jar包的名称
String jarName = "${env.jarName}".trim()
// java应用的端口
int port = "${env.port}"
// java代码的git仓库地址
String codeUrl = "${env.codeUrl}".trim()
// java代码的git分支
String branch = "${env.branch}".trim()

// 消息通知的机器人robot
String robotKey = "${env.robotKey}".trim()

// 打包方式,mvn或者gradle
String packageType = "${env.packageType}".trim()

// 构建者
String buildUser = ""

// 版本号, 由jenkins去读取
String appVersion = ""

//docker image version
String dockerImageVersion = ""

// 子模块, 用于一个多module的项目打包,指定某模块以发布
String childModule = "${env.childModule}".trim()
String packagePath = "target"
if (childModule && childModule != "null" && childModule.trim() != "") {
    tools.PrintMes("build package for childModule: " + childModule, "green")
    packagePath = childModule + "/target"
}

// 判断是否为gradle打包
boolean gradlePackage = packageType.equalsIgnoreCase("gradle")
if (gradlePackage) {
    packagePath = "build/libs"
}
String gradleUserHome = "$sharefile/java-gradle-homes"
String gradleProjectCacheDir = "$gradleUserHome/$jobName"

// workspace
String PROJECT_WORKSPACE = "$sharefile/java-workspaces/$jobName"

// 校验不能为空
if (!projectName) {
    tools.PrintMes("projectName is null", "red")
    return
}

if (!jarName) {
    tools.PrintMes("jarName is null", "red")
    return
}

if (!codeUrl) {
    tools.PrintMes("codeUrl is null", "red")
    return
}

if (!branch) {
    tools.PrintMes("branch is null", "red")
    return
}

//根据jobName读取环境区分
String[] jobInfoArray = jobName.split("_")
// 环境
String buildEnv = jobInfoArray[0]

pipeline {
    agent {
        kubernetes {
            inheritFrom 'jnlp-maven'
            customWorkspace "${PROJECT_WORKSPACE}"
        }
    }

    options {
        timestamps()  //日志会有时间
        skipDefaultCheckout()  //删除隐式checkout scm语句
        disableConcurrentBuilds() //禁止并行
        timeout(time: 1, unit: 'HOURS')  //流水线超时设置1h
    }

    stages {
        stage('Get UserInfo') {
            steps {
                wrap([$class: 'BuildUser']) {
                    script {
                        def BUILD_USER = "${env.BUILD_USER}"
                        def BUILD_USER_ID = "${env.BUILD_USER_ID}"

                        buildUser = BUILD_USER + "(" + BUILD_USER_ID + ")"
                    }
                }
            }
        }

        stage('Pull Code') {
            steps {
                script {
                    tools.PrintMes("pull code!!!", "green")
                    // 拉取代码:git协议
                    git branch: "$branch", credentialsId: "$gitlabCredentialsId", url: "$codeUrl"
                }
            }
            post {
                failure {
                    //当此Pipeline失败时打印消息
                    script {
                        tools.PrintMes("pull code failure!!!", "red")
                        http.imNotify(projectName, "FAIL", buildEnv, "pull code failure", branch, buildUser, robotKey)
                    }
                }
            }
        }

        stage('Compile') {
            steps {
                script {
                    tools.PrintMes("compile!!!", "green")
                    container('maven') {
                        dir("${env.WORKSPACE}") {
                            if (gradlePackage) {
                                sh "$sharefile/gradle-7.6/bin/gradle build -x test --build-cache -g $gradleUserHome --no-daemon --project-cache-dir $gradleProjectCacheDir"
                            } else {
                                sh "mvn clean package -Dmaven.test.skip=true -U  -s  $sharefile/settings.xml"
                            }
                        }
                    }
                }
            }
            post {
                failure {
                    //当此Pipeline失败时打印消息
                    script {
                        tools.PrintMes("compile failure!!!", "red")
                        http.imNotify(projectName, "FAIL", buildEnv, "compile failure", branch, buildUser, robotKey)
                    }
                }
            }
        }

        stage('Get Version') {
            steps {
                script {
                    tools.PrintMes("Get Version!!!", "green")
                    appVersion = tools.getAppVersion(packagePath)
                    // 输出程序的版本号
                    tools.PrintMes("get version: ${appVersion}", "green")
                }
            }
            post {
                failure {
                    //当此Pipeline失败时打印消息
                    script {
                        tools.PrintMes("Get Version failure!!!", "red")
                        http.imNotify(projectName, "FAIL", buildEnv, "Get Version failure", branch, buildUser, robotKey)
                    }
                }
            }
        }

        stage('Push Docker Image') {
            steps {
                script {
                    tools.PrintMes("Push Docker Image!!!", "green")
                    def currentTime = sh returnStdout: true,
                            script: """
                                    date +%m%d%H%M%S
                                    """
                    // 注意:这里的分隔符不能使用冒号, trim()
                    dockerImageVersion = appVersion + "-" + currentTime.trim()
                    tools.PrintMes("Docker Image Version: ${dockerImageVersion}", "green")

                    container('docker') {
                        dir("${env.WORKSPACE}") {
                            docker.buildAndPushImage(jarName, port, dockerImageVersion, packagePath, dockerfileName)
                        }
                    }
                }
            }
            post {
                failure {
                    //当此Pipeline失败时打印消息
                    script {
                        tools.PrintMes("Push Docker Image failure!!!", "red")
                        http.imNotify(projectName, "FAIL", buildEnv, "Push Docker Image failure", branch, buildUser, robotKey)
                    }
                }
            }
        }

        stage('Clean Workspace') {
            steps {
                script {
                    tools.PrintMes("Clean Workspace!!!", "green")
                    cleanWs()
                }
            }
            post {
                failure {
                    script {
                        //当此Pipeline失败时打印消息
                        tools.PrintMes("Clean Workspace failure!!!", "red")
                        http.imNotify(projectName, "FAIL", buildEnv, "Clean Workspace failure", branch, buildUser, robotKey)
                    }
                }
            }
        }

        stage('Update Helm Yaml') {
            steps {
                script {
                    tools.PrintMes("Update Helm Yaml!!!", "green")

                    helm.updateYaml(jarName, dockerImageVersion)
                }
            }
            post {
                failure {
                    script {
                        //当此Pipeline失败时打印消息
                        tools.PrintMes("Update Helm Yaml failure!!!", "red")
                        http.imNotify(projectName, "FAIL", buildEnv, "Update Helm Yaml failure", branch, buildUser, robotKey)
                    }
                }
            }
        }
    }

    post {
        success {
            //当此Pipeline成功时打印消息
            timeout(time: 1, unit: "MINUTES") {
                script {
                    tools.PrintMes("archive jar, send the message of build successfully to user", "green")
                    container('maven') {
                        dir("${env.WORKSPACE}") {
                            sh "echo ${appVersion} > version_${appVersion}.txt"

                            archiveArtifacts artifacts: 'version_*.txt', followSymlinks: false
                        }

                        http.imNotify(projectName, "SUCCESS", buildEnv, "OK", branch, buildUser, robotKey)
                    }
                }
            }
        }
    }
}

五、消息通知

  • TODO: 我们对于构建成功的消息内容,增加程序版本号。

Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S,ci/cd,jenkins
具体消息通知的实现,就不在本文的范畴。

写在末尾的话

后期,我们有空,就Jenkins集群、插件(包括二次开发插件)等话题,聊一聊我们的实际使用情况。文章来源地址https://www.toymoban.com/news/detail-537070.html

到了这里,关于Devops系列六(CI篇之jenkinsfile)jenkins将gitlab helm yaml和argocd 串联,自动部署到K8S的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DevOps-Jenkins-CI持续集成操作

    创建个web项目 我这里直接用Spring Web自动生成的demos 启动项目,访问展示如下默认页面信息 在项目下新建docker目录,新增Dockerfile、docker-compose.yml文件 Dockerfile文件,将mytest.jar 复制到容器的/usr/local/目录下,在/usr/local执行命令java -jar mytest.jar docker-compose.yml文件,当前目录以D

    2024年03月13日
    浏览(45)
  • docker部署Jenkins(Jenkins+Gitlab+Maven实现CI/CD)

          GitLab是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务,可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。       GitLab是由GitLabInc.开发,使用MIT许可证的基于

    2024年02月03日
    浏览(36)
  • gitlab+jenkins+harbor实现CI/CD(2)——初级

    git安装 jenkins主机上安装docker-ce 配置仓库证书 测试 创建项目 创建一个freestyle project 在jenkins主机获取密钥 在gitlab上传公钥 在jenkins上传私钥 输入测试命令后保存 点击立即构建 查看控制台输出 工作路径 构建触发器,定时触发 安装插件 gitlab和 Cloudbee docker 配置gitlab 在网络设

    2024年02月09日
    浏览(38)
  • DevOps搭建(十九)-Jenkins+K8s自动化CI搭建详细步骤

    完整的pipeline-auto.yml脚本如下 完整的Jenkinsfile脚本如下 在Jenkins插件管理中搜索GitLab插件进行安装。 进入Jenkins项目配置里的 构建触发器 ,勾选如下选项: 从系统管理-系统配置-Gitlab将验证去掉,生产最好配置保证安全。 如果是GitLab和Jenkins在同一台服务器,需要开启允许请求

    2024年01月23日
    浏览(67)
  • 使用 Jenkins、Gitlab、Harbor、Helm、k8s 来实现流水线作业

    使用 Jenkins、Gitlab、Harbor、Helm、Kubernetes 来实现一个完整的持续集成和持续部署的流水线作业 开发人员提交代码到 Gitlab 代码仓库 通过 Gitlab 配置的 Jenkins Webhook 触发 Pipeline 自动构建 Jenkins 触发构建构建任务,根据 Pipeline 脚本定义分步骤构建 先进行代码静态分析,单元测试

    2024年04月27日
    浏览(27)
  • devops完整搭建教程(gitlab、jenkins、harbor、docker)

    DevOps(Development Operations)是一种软件开发方法论和工作流程,旨在促进软件开发团队和运维团队之间的协作与沟通,以实现更高效的软件交付和运营。 持续集成(Continuous Integration,CI):开发团队将代码频繁地集成到共享存储库中,确保代码的一致性和稳定性。 持续交付(

    2024年02月19日
    浏览(44)
  • GitLab+Jenkins搭建DevOps一体化运维平台

    ​ 大家拿到代码后,要如何运行呢?导入IDEA,然后启动?开发过程可定没有问题,那生产环境呢?在现在互联网大环境下,越来越要求开发运维一体化。如果对于企业级的项目管理方式不了解,那么开发工作将举步维艰。这一节课主要带大家快速理解一下电商项目的运维部

    2024年02月09日
    浏览(37)
  • 快速构建一个 GitLab + Jenkins + Harbor 的云原生 DevOps 环境

    今天我们要搭建一条怎样的工具链呢?且看效果图: GitLab + Jenkins + Harbor Toolchain Workflow 首先我们需要完成 GitLab、Jenkins 和 Harbor 三个工具的部署; 接着我们需要在 GitLab 上创建一个代码库,并且在 Jenkins 上创建相应的流水线,这个流程最好也自动化(确实可以自动化); 然后

    2024年02月15日
    浏览(31)
  • DevOps系列文章-Kubernetes实现CI与CD配置

    基于 Kubernetes 实现 CI/CD 配置,其实和往常那些 CI/CD 配置并没有太大区别。都是通过 提交代码,拉取代码,构建代码,发布代码来实现的。 只不过要是通过 K8s 来实现的话,则是需要将构建好的代码打包成镜像,通过镜像的方式来运行。 CI/CD 流程图: 开发将代码提交代码仓

    2024年02月05日
    浏览(68)
  • DevOps系列文章 之 SnakeYAML解析与序列化YAML

    如何使用SnakeYAML库将 YAML文档转换为Java对象,以及JAVA对象如何序列化为YAML文档 。 在DevOps平台系统中是基础的能力支持,不管是spring boot 的配置还是K8S 资源清单yaml 要在项目中使用SnakeYAML,需要添加Maven依赖项(可在此处找到最新版本) 该 YAML 类是API的入口点: 由于实现不

    2024年02月13日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包