最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從繁瑣到簡(jiǎn)潔的Jenkins?Pipeline腳本優(yōu)化實(shí)踐

 更新時(shí)間:2023年12月13日 08:58:36   作者:對(duì)你無可奈何  
這篇文章主要為大家介紹了從繁瑣到簡(jiǎn)潔的Jenkins?Pipeline腳本優(yōu)化實(shí)踐示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

在持續(xù)集成的過程中,Jenkins Pipeline 是非常關(guān)鍵的一環(huán)。它定義了如何自動(dòng)編譯、測(cè)試和部署代碼。隨著項(xiàng)目的不斷發(fā)展,Pipeline 的復(fù)雜性也在不斷上升,這就需要我們持續(xù)優(yōu)化 Pipeline 腳本,以提高代碼的可讀性和維護(hù)性。本文將介紹一次從繁瑣Pipeline腳本到精簡(jiǎn)Pipeline腳本的轉(zhuǎn)化過程,以及這種轉(zhuǎn)化所帶來的好處。

原始的 Pipeline 腳本:

注: loader其實(shí)已經(jīng)廢棄了

pipeline {

    agent { label  "build01" }
    stages {
        stage("GetCode"){
            agent { label  "build01" }
            steps{
                script{
                    println("下載代碼 --> 分支: ${env.branchName}")
                    checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]],
                    doGenerateSubmoduleConfigurations: false,
                        extensions: [[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true]],
                    submoduleCfg: [],
                        userRemoteConfigs: [[credentialsId: 'xxxx',
                        url: "${env.gitHttpURL}"]]])
                }
            }
        }    
        stage('docker build dataloader-game-ucenter') {
            agent { label  "build01" }
            when {
                environment name: 'dataloader', value: 'true'
            }

            steps {
                sh ''' cd dataloader
                    docker build  --build-arg NODE_ENV=game-ucenter  -t swr.cn-north-4.myhuaweicloud.com/master-metaspace/dataloader-game-ucenter:$data .'''
                withCredentials([usernamePassword(credentialsId: 'hw-registry', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
                    sh "docker login -u ${dockerUser} -p ${dockerPassword} swr.cn-north-4.myhuaweicloud.com"
                    sh "docker push swr.cn-north-4.myhuaweicloud.com/master-metaspace/dataloader-game-ucenter:$data"
                }
            }
        }
        stage('docker build datawriter-game-ucenter') {
            agent { label  "build01" }
            when {
                environment name: 'datawriter', value: 'true'
            }

            steps {
                sh ''' cd datawriter-game-ucenter
                    docker build  --build-arg NODE_ENV=game-ucenter  -t swr.cn-north-4.myhuaweicloud.com/master-metaspace/datawriter-game-ucenter:$data .'''
                withCredentials([usernamePassword(credentialsId: 'hw-registry', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
                    sh "docker login -u ${dockerUser} -p ${dockerPassword} swr.cn-north-4.myhuaweicloud.com"
                    sh "docker push swr.cn-north-4.myhuaweicloud.com/master-metaspace/datawriter-game-ucenter:$data"
                }
            }
        }   
        stage('docker build game-ucenter') {
            agent { label  "build01" }
            when {
                environment name: 'game-ucenter', value: 'true'
            }

            steps {
                sh ''' cd game-ucenter
                    docker build  --build-arg NODE_ENV=game-ucenter  -t swr.cn-north-4.myhuaweicloud.com/master-metaspace/game-ucenter:$data .'''
                withCredentials([usernamePassword(credentialsId: 'hw-registry', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
                    sh "docker login -u ${dockerUser} -p ${dockerPassword} swr.cn-north-4.myhuaweicloud.com"
                    sh "docker push swr.cn-north-4.myhuaweicloud.com/master-metaspace/game-ucenter:$data"
                }
            }
        }              
        stage('develop') {

            parallel {
                stage("develop datawriter-game-ucenter") {
                    when {
                        environment name: 'datawriter-game-ucenter', value: 'true'
                    }
                    agent { label  "huaweiyun-xx" }
                    steps {
                        sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/master-metaspace/datawriter-game-ucenter.tpl > /home/jenkins/workspace/yaml/master-metaspace/datawriter-game-ucenter.yaml"
                        sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/master-metaspace/datawriter-game-ucenter.yaml --namespace=master-metaspace --context=master"
                    }
                }
                stage("develop dataloader-game-ucenter") {
                    when {
                        environment name: 'dataloader', value: 'true'
                    }
                    agent { label  "huaweiyun-xx" }
                    steps {
                        sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/master-metaspace/dataloader-game-ucenter.tpl > /home/jenkins/workspace/yaml/master-metaspace/dataloader-game-ucenter.yaml"
                        sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/master-metaspace/dataloader-game-ucenter.yaml --namespace=master-metaspace --context=master"
                    }
                }
                stage("develop game-ucenter") {
                    when {
                        environment name: 'game-ucenter', value: 'true'
                    }
                    agent { label  "huaweiyun-xx" }
                    steps {
                        sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/master-metaspace/game-ucenter.tpl > /home/jenkins/workspace/yaml/master-metaspace/game-ucenter.yaml"
                        sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/master-metaspace/game-ucenter.yaml --namespace=master-metaspace --context=master"
                    }
                }                                  
            }
        }
    }
}

在優(yōu)化之前,我們的 Jenkins Pipeline 腳本中包含了多個(gè)獨(dú)立定義的 stage,每個(gè) stage 中都有重復(fù)的結(jié)構(gòu)和指令:

  • 明確指定了 agent。
  • 在每個(gè) stage 的 steps 中,都使用了類似的腳本來操作 git、構(gòu)建 docker 鏡像和部署到 Kubernetes。
  • 使用了冗長(zhǎng)的 shell 腳本來綁定變量和執(zhí)行部署。

這種寫法雖然直觀,但存在以下問題:

  • 代碼冗余:相同的任務(wù)(例如構(gòu)建與部署)重復(fù)編寫了多次。
  • 低效的修改:一旦需要調(diào)整構(gòu)建或部署流程,需要同時(shí)修改多個(gè)類似的代碼段。
  • 可讀性差:過于細(xì)碎的腳本內(nèi)容使得新成員閱讀和理解這個(gè) Pipeline 變得困難。

轉(zhuǎn)化的原因與過程

簡(jiǎn)化 agent 的聲明

pipeline {
    agent none // Use none at the top level, each stage will define its own agent.
    }

在原始腳本中,每個(gè) stage 都重復(fù)指定相同的 agent,這是不必要的。轉(zhuǎn)化后,我們?cè)?pipeline 的頂層使用 agent none 聲明,表示不在這一層級(jí)指定執(zhí)行者,這樣各個(gè) stage 就可以根據(jù)需求獨(dú)立地聲明自己的 agent。

將環(huán)境變量統(tǒng)一管理

我們創(chuàng)建一個(gè) environment 部分來集中定義環(huán)境變量,簡(jiǎn)化了變量的管理,并且當(dāng)需要修改時(shí)只要在一個(gè)地方進(jìn)行調(diào)整即可。

environment {
        REGISTRY = "swr.cn-north-4.myhuaweicloud.com/master-metaspace"
        KUBE_CONFIG = "--namespace=master-metaspace --context=master"
        KUBE_YAML_PATH = "/home/jenkins/workspace/yaml/master-metaspace"
        // Assume that 'data' is defined elsewhere or injected as a parameter.
    }

使用共用方法減少代碼重復(fù)

對(duì)于 Docker 鏡像的構(gòu)建和推送操作,每個(gè)應(yīng)用幾乎執(zhí)行相同的步驟。我們提取了一個(gè)方法 buildAndPushDockerImage 來代替在每個(gè) stage 里重復(fù)定義的步驟,這樣不但減小了腳本體積,也提升了代碼的復(fù)用性。

def buildAndPushDockerImage(String imageName, String tag) {
    sh "cd $imageName && docker build --build-arg NODE_ENV=$imageName -t $REGISTRY/$imageName:$tag ."
    withCredentials([usernamePassword(credentialsId: 'hw-registry', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
        sh "docker login -u $dockerUser -p $dockerPassword $REGISTRY"
        sh "docker push $REGISTRY/$imageName:$tag"
    }
}

同理,部署到 Kubernetes 的指令也被提取到了 deployToKubernetes 方法中,進(jìn)一步去重。

def deployToKubernetes(String kubernetesComponent) {
    String templateFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.tpl"
    String outputFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.yaml"
    sh "sed -e 's/{data}/$data/g' $templateFile > $outputFile"
    sh "sudo kubectl apply -f $outputFile $KUBE_CONFIG"
}

結(jié)構(gòu)的并行化

將 Docker 構(gòu)建步驟組合為一個(gè)并行執(zhí)行的 stage,這樣不僅可以縮短整個(gè)流水線的執(zhí)行時(shí)間,還可以使得結(jié)構(gòu)更加清晰。

stage("Docker Builds") {
            parallel {
                stage('Build dataloader-game-ucenter') {
                    agent { label "build01" }
                    when { environment name: 'dataloader', value: 'true' }
                    steps {
                        buildAndPushDockerImage("dataloader-game-ucenter", env.data, env.BASE_WORKSPACE)
                    }
                }
                stage('Build datawriter-game-ucenter') {
                    agent { label "build01" }
                    when { environment name: 'datawriter', value: 'true' }
                    steps {
                        buildAndPushDockerImage("datawriter-game-ucenter", env.data, env.BASE_WORKSPACE)
                    }
                }
                stage('Build game-ucenter') {
                    agent { label "build01" }
                    when { environment name: 'game-ucenter', value: 'true' }
                    steps {
                        buildAndPushDockerImage("game-ucenter", env.data, env.BASE_WORKSPACE)
                    }
                }
            }
        }

轉(zhuǎn)化后的好處

轉(zhuǎn)換后的pipeline如下:

pipeline {
    agent none // Use none at the top level, each stage will define its own agent.
    environment {
        REGISTRY = "swr.cn-north-4.myhuaweicloud.com/master-metaspace"
        KUBE_CONFIG = "--namespace=master-metaspace --context=master"
        KUBE_YAML_PATH = "/home/jenkins/workspace/yaml/master-metaspace"
        // Assume that 'data' is defined elsewhere or injected as a parameter.
        BASE_WORKSPACE = "xxxxxxx" // 定義一個(gè)基礎(chǔ)工作空間路徑
    }
    stages {
        stage("GetCode") {
            agent { label "build01" }
            steps {
                script {
                    checkout scm: [
                        $class: 'GitSCM',
                        branches: [[name: env.branchName]],
                        extensions: [[$class: 'CloneOption', depth: 1, noTags: false, shallow: true]],
                        userRemoteConfigs: [[credentialsId: 'xxxx', url: env.gitHttpURL]]
                    ]
                }
            }
        }
        stage("Docker Builds") {
            parallel {
                stage('Build dataloader-game-ucenter') {
                    agent { label "build01" }
                    when { environment name: 'dataloader', value: 'true' }
                    steps {
                        buildAndPushDockerImage("dataloader-game-ucenter", env.data, env.BASE_WORKSPACE)
                    }
                }
                stage('Build datawriter-game-ucenter') {
                    agent { label "build01" }
                    when { environment name: 'datawriter', value: 'true' }
                    steps {
                        buildAndPushDockerImage("datawriter-game-ucenter", env.data, env.BASE_WORKSPACE)
                    }
                }
                stage('Build game-ucenter') {
                    agent { label "build01" }
                    when { environment name: 'game-ucenter', value: 'true' }
                    steps {
                        buildAndPushDockerImage("game-ucenter", env.data, env.BASE_WORKSPACE)
                    }
                }
            }
        }
        stage('Development Deployment') {
            parallel {
                stage("Deploy datawriter-game-ucenter") {
                    when { environment name: 'datawriter-game-ucenter', value: 'true' }
                    agent { label  "huaweiyun-xx" }
                    steps {
                        deployToKubernetes("datawriter-game-ucenter")
                    }
                }
                stage("Deploy dataloader-game-ucenter") {
                    when { environment name: 'dataloader', value: 'true' }
                    agent { label  "huaweiyun-xx" }
                    steps {
                        deployToKubernetes("dataloader-game-ucenter")
                    }
                }
                stage("Deploy game-ucenter") {
                    when { environment name: 'game-ucenter', value: 'true' }
                    agent { label  "huaweiyun-xx" }
                    steps {
                        deployToKubernetes("game-ucenter")
                    }
                }
            }
        }
    }
}
// Define methods outside pipeline to avoid repetition
def buildAndPushDockerImage(String imageName, String tag, String workspacePath) {
    sh "cd ${workspacePath} && echo 'Current directory: \$(pwd)'" // 使用基礎(chǔ)工作空間變量
    sh "cd ${workspacePath}/${imageName}&& docker build --build-arg NODE_ENV=$imageName -t $REGISTRY/$imageName:$tag ."
    withCredentials([usernamePassword(credentialsId: 'hw-registry', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
        sh "docker login -u $dockerUser -p $dockerPassword $REGISTRY"
        sh "docker push $REGISTRY/$imageName:$tag"
    }
}
def deployToKubernetes(String kubernetesComponent) {
    String templateFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.tpl"
    String outputFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.yaml"
    sh "sed -e 's/{data}/$data/g' $templateFile > $outputFile"
    sh "sudo kubectl apply -f $outputFile $KUBE_CONFIG"
}
  • 代碼結(jié)構(gòu)清晰:每個(gè)階段的職責(zé)更加明確,整個(gè) Pipeline 結(jié)構(gòu)變得簡(jiǎn)單易懂。
  • 維護(hù)成本降低:通用操作被封裝成方法,避免了重復(fù)代碼,當(dāng)流程需要修改時(shí),只需在一個(gè)地方更新。
  • 執(zhí)行效率提升:使用 parallel 來并行構(gòu)建 Docker 鏡像降低了整體構(gòu)建時(shí)間。
  • 可擴(kuò)展性增加:如果將來要增加新的鏡像構(gòu)建或者 Kubernetes 部署,只需很少的修改即可。

總結(jié)來說,通過優(yōu)化 Jenkins Pipeline 腳本,我們不僅提高了流程的效率,還大大減小了維護(hù)成本。在持續(xù)集成和持續(xù)部署的實(shí)踐中,擁有一個(gè)簡(jiǎn)潔和高效的 Pipeline 是至關(guān)重要的。

特意強(qiáng)調(diào)的

environment 添加了BASE_WORKSPACE,why?
在Jenkins中,當(dāng)你在一個(gè)Pipeline中使用并行步驟執(zhí)行作業(yè)時(shí),默認(rèn)情況下,每個(gè)并行的分支都會(huì)創(chuàng)建一個(gè)新的工作空間目錄,格式一般為workspace@2、workspace@3等,這樣做是為了避免各個(gè)分支之間產(chǎn)生文件系統(tǒng)上的沖突。

這樣帶來的后果就是:

構(gòu)建過程中就會(huì)出現(xiàn)No such file or directory這樣的報(bào)錯(cuò):

所以這里引入了BASE_WORKSPACE

environment {
        REGISTRY = "swr.cn-north-4.myhuaweicloud.com/master-metaspace"
        KUBE_CONFIG = "--namespace=master-metaspace --context=master"
        KUBE_YAML_PATH = "/home/jenkins/workspace/yaml/master-metaspace"
        // Assume that 'data' is defined elsewhere or injected as a parameter.
        BASE_WORKSPACE = "/home/jenkins2/workspace/test6" // 定義一個(gè)基礎(chǔ)工作空間路徑
    }

build過程中引入了:

sh "cd ${workspacePath} && echo 'Current directory: \$(pwd)'"

確保并行步驟中引用到正確的工作空間目錄!

注: 以上腳本代碼轉(zhuǎn)換后的pipeline使用chatgpt生成,并多次修訂!

以上就是從繁瑣到簡(jiǎn)潔的Jenkins Pipeline腳本優(yōu)化實(shí)踐的詳細(xì)內(nèi)容,更多關(guān)于Jenkins Pipeline腳本優(yōu)化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot實(shí)現(xiàn)SSE(Server-Sent?Events)的完整指南

    SpringBoot實(shí)現(xiàn)SSE(Server-Sent?Events)的完整指南

    本文展示了如何在Spring?Boot應(yīng)用中實(shí)現(xiàn)SSE,通過簡(jiǎn)單的步驟和代碼示例,你可以輕松地在你的Web應(yīng)用中添加實(shí)時(shí)數(shù)據(jù)推送功能,需要的朋友可以參考下
    2025-09-09
  • Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題案例詳解

    Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題案例詳解

    這篇文章主要介紹了Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題,結(jié)合具體演繹哲學(xué)家進(jìn)餐問題的案例形式詳細(xì)分析了死鎖機(jī)制與原理,需要的朋友可以參考下
    2019-10-10
  • SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼

    SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼

    本文主要介紹了SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java jdk安裝及javac命令無效解決方案

    Java jdk安裝及javac命令無效解決方案

    這篇文章主要介紹了Java jdk安裝及javac命令無效解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • java多線程通過CompletableFuture組裝異步計(jì)算單元

    java多線程通過CompletableFuture組裝異步計(jì)算單元

    這篇文章主要為大家介紹了java多線程通過CompletableFuture組裝異步計(jì)算單元,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Java Synchronized鎖升級(jí)原理及過程剖析

    Java Synchronized鎖升級(jí)原理及過程剖析

    這篇文章主要為大家詳細(xì)介紹一下Java中Synchronized鎖升級(jí)原理及過程,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2022-08-08
  • 詳解kafka中的消息分區(qū)分配算法

    詳解kafka中的消息分區(qū)分配算法

    kafka有分區(qū)機(jī)制,一個(gè)主題topic在創(chuàng)建的時(shí)候,會(huì)設(shè)置分區(qū)。如果只有一個(gè)分區(qū),那所有的消費(fèi)者都訂閱的是這一個(gè)分區(qū)消息;如果有多個(gè)分區(qū)的話,那消費(fèi)者之間又是如何分配的呢?本文就來為大家詳細(xì)講解一下
    2022-04-04
  • java動(dòng)態(tài)代理詳解

    java動(dòng)態(tài)代理詳解

    本文章要用很土的語(yǔ)言描述Java動(dòng)態(tài)代理,力求更易被理解。Java是JDK5中新加的機(jī)制,大家都知道Spring是用Java的動(dòng)態(tài)代理實(shí)現(xiàn)的,那這個(gè)動(dòng)態(tài)代理是什么東東呢,首先他肯定是個(gè)代理,我們先講代理,把代理弄明白了,動(dòng)態(tài)代理就好說了
    2014-02-02
  • SpringBean依賴和三級(jí)緩存的案例講解

    SpringBean依賴和三級(jí)緩存的案例講解

    這篇文章主要介紹了SpringBean依賴和三級(jí)緩存的案例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Springboot接收文件報(bào)錯(cuò)Required request part‘file‘is not present問題分析及解決

    Springboot接收文件報(bào)錯(cuò)Required request part‘file‘is 

    文章總結(jié):在Flutter和Vue項(xiàng)目中遇到文件上傳問題,后端接口Controller定義無誤,但前端通過FormData封裝上傳文件時(shí)報(bào)錯(cuò),通過瀏覽器抓包和PostMan測(cè)試,發(fā)現(xiàn)后臺(tái)確實(shí)可以接收參數(shù),最終通過修改封裝的file為file.raw解決問題,解決了文件上傳不成功的問題
    2025-12-12

最新評(píng)論

金门县| 蓬溪县| 通城县| 南澳县| 铁力市| 绿春县| 太仓市| 沾益县| 醴陵市| 桑日县| 茌平县| 宽甸| 紫金县| 龙游县| 黄梅县| 雷波县| 托克托县| 邻水| 泸西县| 西华县| 永寿县| 阳城县| 铜陵市| 鹿泉市| 黔江区| 睢宁县| 灵台县| 通渭县| 昭平县| 禄丰县| 五原县| 丘北县| 杨浦区| 醴陵市| 祥云县| 兴城市| 鹤壁市| 永仁县| 竹北市| 宣城市| 山东省|