持续集成交付CICD:HELM 自动化完成前端项目应用发布与回滚

目录

一、实验

1.环境

[2. GitLab 共享库新建HELM CI流水线](#2. GitLab 共享库新建HELM CI流水线)

[3.Jenkins新建HELM CI流水线](#3.Jenkins新建HELM CI流水线)

5.Jenkins构建前端项目

[6.GitLab 共享库新建HELM CD流水线](#6.GitLab 共享库新建HELM CD流水线)

[7.Jenkins新建HELM CD流水线](#7.Jenkins新建HELM CD流水线)

8.HELM完成前端项目应用发布与回滚

9.Jenkins再次构建前端项目

10.HELM再次完成前端项目应用发布与回滚

二、问题

[1. HELM CD流水线报错](#1. HELM CD流水线报错)


一、实验

1.环境

(1)主机

表1 主机

|---------|--------------|----------|---------------------|---------------------|
| 主机 | 架构 | 版本 | IP | 备注 |
| master1 | K8S master节点 | 1.20.6 | 192.168.204.180 | jenkins slave (从节点) |
| | helm | 3.6.0 | | |
| | git | 1.8.3.1 | | |
| node1 | K8S node节点 | 1.20.6 | 192.168.204.181 | |
| node2 | K8S node节点 | 1.20.6 | 192.168.204.182 | |
| jenkins | jenkins主节点 | 2.414.2 | 192.168.204.15:8080 | gitlab runner (从节点) |
| | harbor私有仓库 | 1.2.2 | 192.168.204.15 | |
| gitlab | gitlab 主节点 | 12.10.14 | 192.168.204.8:82 | jenkins slave (从节点) |
| | sonarqube | 9.6 | 192.168.204.8:9000 | |

2. GitLab 共享库新建HELM CI流水线

(1)共享库新建CI流水线

(2)修改k8scihelm.jenkinsfile

bash 复制代码
@Library("mylib@master") _
import org.devops.*


def checkout = new Checkout()
def build = new Build()
def unittest = new UnitTest()
def sonar = new Sonar()
def gitlabutil = new Gitlab()


pipeline {
    agent { label "build"}

    options {
        skipDefaultCheckout true
    }
    stages{
        stage("Checkout"){
            steps{
                script {
                    println("GetCode")
                    checkout.GetCode("${env.srcUrl}","${env.branchName}")
                }
            }
        }
        stage("build"){
            steps{
                script{
                    println("Build")
                    build.CodeBuild("${env.buildTool}")
                }
            }

        }

        stage("UnitTest"){
            steps{
                script{
                    println("Test")
                    unittest.CodeTest("${env.buildTool}")
                }
            }

        }
        stage("SonarScan"){
            steps {
                script {
                    groupName = "${JOB_NAME}".split("/")[0]
                    projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]
                    sonar.CodeSonar("${env.buildTool}",projectName,groupName)
                }

            }

        }
        stage("PushImage"){
            steps {
                script {
                    repoName = "${JOB_NAME}".split("/")[0]
                    projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]
                    env.registry = "192.168.204.15"
                    env.imageName = "${env.registry}/${repoName}/${projectName}:${env.branchName}"
                    withCredentials([usernamePassword(credentialsId: '8c662308-4991-4576-9826-74a5417de685', passwordVariable: 'DOCKER_PASSWD', usernameVariable: 'DOCKER_USER')]) {
                        sh """
                            #重写HTML首页
                            echo "${env.imageName}" > dist/index.html 
    
                            #构建镜像
                            docker build -t ${env.imageName} .
                           
                            #登录镜像仓库
                            docker login -u ${DOCKER_USER} -p ${DOCKER_PASSWD} ${env.registry}
                            
                            #上传镜像
                            docker push  ${env.imageName}
    
                            #删除镜像
                            sleep 2
                            docker rmi ${env.imageName}
                        """
                    }


                }

            }

        }

        stage("ReleaseFile"){
            steps{
                script{
                    env.namespace = "${JOB_NAME}".split("/")[0]
                    env.appName ="${JOB_NAME}".split("/")[-1].split("_")[0]
                    // 获取values.yaml文件
                    fileData = gitlabutil.GetRepoFile(23,"${env.appName}%2fvalues.yaml", "master")
                    yamlData = readYaml text: fileData

                    // 替换模板文件内容
                    yamlData.image.tag  = "${env.imageName}".split(":")[-1]
                    yamlData.image.repository = "${env.registry}/${env.namespace}/${env.appName}"


                    //保存yaml文件
                    sh "rm -fr values.yaml"
                    writeYaml  charset: 'UTF-8', file: 'values.yaml', data: yamlData

                    // 上传替换后的版本文件(新建文件或者更新文件)
                    newYaml = sh returnStdout: true, script: 'cat values.yaml'
                    println(newYaml)
                    
                    //更新gitlab文件内容
                    base64Content = newYaml.bytes.encodeBase64().toString()

                    // 会有并行问题,同时更新报错
                    try {
                        gitlabutil.UpdateRepoFile(23,"${env.appName}%2fvalues.yaml",base64Content, "master")
                    } catch(e){
                        gitlabutil.CreateRepoFile(23,"${env.appName}%2fvalues.yaml",base64Content, "master")
                    }
                }
            }
        }
    }

}

3.Jenkins新建HELM CI流水线

(1)新建CI流水线

(2)修改脚本路径

(3)新建视图

(4)列表添加

(5)查看视图

5.Jenkins构建前端项目

(1)Jenkins构建前端项目 CI流水线,指定版本为RELEASE-1.1.6

(2)完成

(3)GitLab HELM项目显示更新了文件values.yaml

更新前:

更新后:

6.GitLab 共享库新建HELM CD流水线

(1)共享库新建CD流水线

(2)修改k8scdhelm.jenkinsfile

bash 复制代码
@Library("mylib@master") _
import org.devops.*


def checkout = new Checkout()
def gitlabbutil = new Gitlab()
env.groupName = "${JOB_NAME}".split("/")[0]
env.projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]


pipeline {
    agent { label "k8s"}

    options {
        skipDefaultCheckout true
    }
    stages{
        stage("GetChartRepo"){
            steps{
                script {
                    println("GetCode")
                    checkout.GetCode("${env.srcUrl}","${env.branchName}")
                }
            }
        }

        stage("DeployAPP"){
            steps{
                script{
                    env.namespace = "${env.groupName}"
                    env.appName = "${env.projectName}"

                    // HELM 发布
                    sh """
                        helm package "${env.appName}/"
                        helm upgrade --install --create-namespace  "${env.appName}" ./"${env.appName}"-*.tgz -n ${env.namespace}
                        helm history "${env.appName}"  -n ${env.namespace}
                    """

                    //获取release的历史版本
                    env.revision = sh returnStdout: true, script: """helm history ${env.appName} -n ${env.namespace} | grep -v 'REVISION' | awk '{print \$1}' """
                    println("${env.revision}")
                    println("${env.revision.split('\n').toString()}")
                    env.REVISION = "${env.revision.split('\n').toString()}"
                    println("${env.REVISION}")

                    // 获取应用状态
                    5.times{
                        sh "sleep 2; kubectl -n ${env.namespace} get pod | grep ${env.appName}"
                    }


                }
            }
        }

        stage("RollOut"){
            steps{
                script{
                    //获取release的历史版本
                    env.revision = sh returnStdout: true, script: """helm history ${env.appName} -n ${env.namespace} | grep -v 'REVISION' | awk '{print \$1}' """
                    //println("${env.revision}")
                    //println("${env.revision.split('\n').toString()}")
                    env.REVISION = "${env.revision.split('\n').toString()}"
                    println("${env.REVISION}")
                    def result = input message: 'RollBack?',
                                       ok: 'submit',
                                       parameters: [choice(choices: "${env.REVISION}", description: '', name: 'revision')]
                    env.result = result - "\n"

                    echo "Actions is  ${env.result}, doing......."
                    if ( "${env.result}" != ""){
                        sh """ helm rollback ${env.appName} ${env.result} -n ${env.namespace}  """
                    } else {
                        println("Skip rollback .....")
                    }

                }
            }
        }
    }
}

(3)查看共享库目录

7.Jenkins新建HELM CD流水线

(1)新建CD流水线

(2)修改脚本路径

(3)复制Clone项目地址

(4)添加字符参数

(5)新建并查看视图

8.HELM完成前端项目应用发布与回滚

(1)K8S master节点另开一个终端用watch命令观察pod变化

# watch -n 1 "kubectl get pod -n devops03"

(2)外部测试访问(当前版本为1.1.6)

# curl http://devops03-devops-ui.devops.com:31291

(3)Jenkins构建前端项目CD 流水线,指定分支为master

(4)选择回滚 1 版本

相当于选择1 版本

bash 复制代码
# helm rollback devops03-devops-ui 1 -n devops03

(5)完成

(6)观察pod变化

9.Jenkins再次构建前端项目

(1)Jenkins构建前端项目 CI流水线,指定版本为RELEASE-1.1.7

(2)完成

(3)GitLab HELM项目显示更新了文件values.yaml

更新前:

更新后:

10.HELM再次完成前端项目应用发布与回滚

(1)Jenkins构建前端项目CD 流水线,指定分支为master

(2)观察pod变化

(3)外部测试访问(当前版本为1.1.7)

# curl http://devops03-devops-ui.devops.com:31291

(4)选择回滚 6 版本

相当于选择6 版本

bash 复制代码
# helm rollback devops03-devops-ui 1 -n devops03

(5)完成

(6)观察pod变化

(7)外部测试访问(当前版本为1.1.6)

# curl http://devops03-devops-ui.devops.com:31291

(8)查看历史版本

bash 复制代码
# helm history devops03-devops-ui -n devops03

二、问题

1. HELM CD流水线报错

(1) 报错

(2)原因分析

GitLab HELM项目只有master分支

(3)解决方法

分支名输入master.

修改:

成功:

相关推荐
NiNg_1_23437 分钟前
使用Docker Compose一键部署
运维·docker·容器
萠哥啥都行42 分钟前
Linux安装Docker以及Docker入门操作
运维·docker·容器
小江湖19941 小时前
元数据保护者,Caesium压缩不丢重要信息
运维·学习·软件需求·改行学it
gopher95111 小时前
linux驱动开发-中断子系统
linux·运维·驱动开发
吃面不喝汤662 小时前
如何配置和使用自己的私有 Docker Registry
运维·docker·容器
Rookie_explorers2 小时前
Linux下go环境安装、环境配置并执行第一个go程序
linux·运维·golang
学习向前冲2 小时前
AD域控服务器
运维·服务器
hgdlip2 小时前
查看ip地址的方法有几种?探索多样方法
运维·服务器·ip地址
丶21362 小时前
【Nginx】在 Docker 上安装 Nginx 的详细指南
运维·nginx·docker
神即道 道法自然 如来3 小时前
Jenkins怎么设置每日自动执行构建任务?
运维·jenkins