持续集成交付CICD:K8S 通过模板文件自动化完成前端项目应用发布

目录

一、实验

1.环境

2.GitLab 更新deployment文件

3.GitLab更新共享库前端项目CI与CD流水线

4.K8S查看前端项目版本

5.Jenkins 构建前端项目

6.Jenkins 再次构建前端项目

二、问题

1. Jenkins 构建CI 流水线报错

2. Jenkins 构建CI 流水线弹出脚本报错

3. Jenkins 构建CD 流水线报错

4.URL中特殊字符实现哪些功能

5.sed如何实现替换特殊字符


 

 

一、实验

1.环境

(1)主机

表1 主机

主机架构版本IP备注
master1K8S master节点1.20.6192.168.204.180

jenkins slave

(从节点)

node1K8S node节点1.20.6192.168.204.181 
node2K8S node节点1.20.6192.168.204.182 
jenkins

 jenkins主节点      

2.414.2192.168.204.15:8080

 gitlab runner

(从节点)

 harbor私有仓库1.2.2192.168.204.15 
gitlab

gitlab 主节点       

12.10.14192.168.204.8:82

jenkins slave

(从节点)

 sonarqube9.6192.168.204.8:9000 

 

2.GitLab 更新deployment文件

(1)项目新建目录,用于存放上传的deployment 替换文件

61c1cbe42f2d49a39e69240126b465b4.png0302eeaaa9314db0b00609479c98cf34.png

(2)准备更新模板文件deployment.yaml

 __APPNAME__(应用名称)对应Jenkins作业名称

 __NAMESPACE__ (名称空间)  对应业务名称

 __INAGENAME__(镜像名称) 

(3)更新完成

601bde8c1f414594be88b29fad1cd1b1.png

(4)项目目录如下:

6a39dfb70567465d913ec49e65801f4f.png

 

3.GitLab更新共享库前端项目CI与CD流水线

(1)查看项目架构

623fb835973a495c830c9ec5b72a42f8.png

(2)更新K8S CI流水线 (k8sci.jenkinsfile)

@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{

                    // 获取模板文件
                    fileData = gitlabutil.GetRepoFile(22,"deployment.yaml", "master")
                    sh "rm -fr deployment.yaml"
                    writeFile file: 'deployment.yaml', text: fileData

                    // 替换模板文件内容
                    namespace = "${JOB_NAME}".split("/")[0]
                    appName ="${JOB_NAME}".split("/")[-1].split("_")[0]
                    sh """
                          sed -i 's#__PORT__#${env.port}#g' deployment.yaml
                          sed -i 's#__APPNAME__#${appName}#g' deployment.yaml
                          sed -i 's#__NAMESPACE__#${namespace}#g' deployment.yaml
                          sed -i 's#__IMAGENAME__#${env.imageName}#g' deployment.yaml
                    """

                    // 上传替换后的版本文件(新建文件或者更新文件)
                    newYaml = sh returnStdout: true, script: 'cat deployment.yaml'
                    println(newYaml)

                    //更新gitlab文件内容
                    base64Content = newYaml.bytes.encodeBase64().toString()

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

}

(3)更新K8S CD流水线 (k8scd.jenkinsfile)

@Library("mylib@master") _
import org.devops.*



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("GetDeployFile"){
            steps{
                script {

                    env.appName = "${env.projectName}"
                    env.deployFile = "${env.appName}/${env.branchName}.yaml"
                    //println("GetCode")
                    fileData = gitlabbutil.GetRepoFile(22,"${env.appName}%2f${env.branchName}.yaml", "master")
                    //println(fileData)
                    sh "rm -fr ${env.deployFile}"
                    writeFile file: "${env.deployFile}", text: fileData
                    //sh "ls -l; cat deployment.yaml"
                    sh "ls -l "

                }
            }
        }

        stage("DeployAPP"){
            steps{
                script{
                    env.namespace = "${env.groupName}"
                    sh """
                        ## 发布应用
                        kubectl apply -f ${env.deployFile} -n ${env.namespace}
                    """

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

        stage("RollOut"){
            input {
                message "是否进行回滚"
                ok "提交"
                submitter "david,aa"
                parameters {
                    choice(choices: ['yes','no'], name: 'opts')
                    
                }

            }

            steps{
                script{
                    switch ("${opts}"){
                        case "yes":
                            sh " kubectl rollout undo deployment/${env.appName} -n ${env.namespace}"
                            break

                        case "no":
                            break

                    }
                }
            }
        }

    }
}

4.K8S查看前端项目版本

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

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

32d8f31c58604548bdd6cc611ab8295d.png

(2)  另开一个终端用watch命令观察pod变化

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

d96aae45ce34497591dc6de5697a69c5.png

47a29171ffd848509def7e5d120697d6.png

 

5.Jenkins 构建前端项目

(1)Jenkins给前端项目CI流水线添加参数添加字符参数port

196fbfedc0c74af294f3ddba9543342e.png

(2)Jenkins给前端项目CD流水线添加参数添加字符参数branchNameab052818e67444dfaf556bb479cd11b4.png

 

(3) 构建前端项目CI流水线

4e61d5320ba74b25a254f2b0788afe8d.png

(4)成功

657b576137aa4d3d8a6331d25eada137.png

5203e2aeeb5f4120bad2a3deb55945a2.png

 

(5)GitLab查看deployment部署文件已自动上传(RELEASE-1.1.5.yaml)

434f94317f334b50a9796c0feabb9a4e.png

(6) 构建前端项目CD流水线d1c81cb7941f44e5854bffaf7f6b2f64.png

(7) 观察pod变化

8fdf0d54fe094e7fb1fb2982237a138d.pngca0e8e4c9e01415aae78c449fde74bd3.png45782720009a44cd85d92180f2f26bd6.png7e827018b4be476fb283aea9b6c353b1.png

(8)外部测试访问(当前版本为1.1.5)

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

26984850e4ae42cb85ff70b1384dea00.png

(9)不进行回滚

300eb1721dff471b8e6c1b6173b81891.png

(10)完成

4df8695a8cf14ac5be378553274eb472.png

 

6.Jenkins 再次构建前端项目

(1) 构建前端项目CI流水线

9fee5006590e468ca6e533cda043c8c6.png

(2)成功

7b527348e58943108ab98d44150c0e10.png4f64c6b568344c90adc1139a8714ba19.png

(3)GitLab查看deployment部署文件已自动上传(RELEASE-1.1.6.yaml)

580bf6ea655c4bf3a44640955f355896.png

(4) 构建前端项目CD流水线bce3be17b9234b3ab77ca4bd400d4919.png

(5) 观察pod变化

1688804adfca4414ad42046457ddd287.png8fd04a1ced684c0a8a53da51b3a90468.pngd51cfaf94d5d4ee8aab483ce4555ed36.png

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

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

d3f58ce4df0740eca5618712df063206.png

(7)不进行回滚

e9b689b356944152a69688dbd0f8dbd8.png

(8)完成

654e375590794adf80c7af252b620e2b.png

 

二、问题

1. Jenkins 构建CI 流水线报错

(1)报错

acdbe0abbb2448f69f539cf8f8bfc43f.png

(2)原因分析

函数名错误

(3)解决方法

修改函数名。

修改前:

c992530857914cc4b17c0812f0a39723.png

修改后:

b6b8a6fd3a634c7bbdbd28d7022b1b2e.png

 

 

2. Jenkins 构建CI 流水线弹出脚本报错

(1)报错

dac675a89db84b22ba0cf1a0429db99a.png

(2)原因分析

script不允许使用静态方法

(3)解决方法

运行script使用静态方法

根据弹出提示页面,点击进入。

fc79c8d85a7f496ca4afdf809f215b5b.png

点击Approve

8b9cd0905d99413db07ea1c0a35fe636.png

完成

91619c37d02244ee825946f230503240.png

重写构建项目成功

39907b913566440889afda475addf7a6.png

3. Jenkins 构建CD 流水线报错

(1) 报错

f0191d23859141a59087d93bd2538cb7.png

(2)原因分析

yaml文件格式错误

(3)解决方法

修改deploymeny模板文件

修改前:

02616c8eeb1c4e1eada1e0e6423e5fa9.png

修改后:

841077c010824c1589c62e1ec3fa5d7c.png

成功:

be3873f0b9da4f7386c365cc8c36caf2.png

 

4.URL中特殊字符实现哪些功能

(1)URL特殊字符

​
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了。
编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(16进制)码值。例如 空格的编码值是"%20"。
如果不使用转义字符,这些编码就会当URL中定义的特殊字符处理。

​

(2)URL特殊符号及编码 十六进制值

1) + URL 中+号表示空格 %2B
2) 空格 URL中的空格可以用+号或者编码 %20
3) / 分隔目录和子目录 %2F
4) ? 分隔实际的 URL 和参数 %3F
5) % 指定特殊字符 %25
6) # 表示书签 %23
7) & URL 中指定的参数间的分隔符 %26
8) = URL 中指定参数的值 %3D

5.sed如何实现替换特殊字符

(1)普通操作可以使用冒号(:)井号(#)正斜杠(/)来作为分隔符

sed -i 's#abc#def#g'  geng.file  ---将文件geng中的abc替换成def

cat geng.file | sed  's/abc/def/g'   ---打印文件geng,并将其中的abc替换成def

(2)对于变量做替换

sed 若是单引号括起来的,变量上得再额外加个单引号才能引用生效;

       若是双引号括起来的,可直接引用生效。

1)举例
pa='127.0.0.1/32'; field='ip_allow=123'; \
echo $field | sed 's#^ip_allow=.*#ip_allow=${pa}#g' 

结果:ip_allow=${pa}  --变量替换未生效

2)更改
echo $field | sed 's#^ip_allow=.*#ip_allow='${pa}'#g'

结果:ip_allow=127.0.0.1/32

3)更改
echo $field | sed "s#^ip_allow=.*#ip_allow=${pa}#g"

结果:ip_allow=127.0.0.1/32

(3) 特殊字符替换,反斜杠、正斜杠、双引号、$符

单个转义:多加个反斜杠做转义即可:反斜杠(\\)、正斜杠(\/)、双引号(\")

单转多个:参考如下列表

表2 特殊字符转换

实现目标方法能否用单引号还是双引号括起来
单引号双引号为什么
反斜杠(\)替换成两个反斜杠(\\)

sed -i 's#\\#\\\\#g' file

或sed -i 's:\\:\\\\:g' file

×反斜杠用双引号括起来会报错
反斜杠(\)替换成正斜杠(/)sed -i 's#\\#\/#g' file×反斜杠用双引号括起来会报错
双引号(")替换成两个双引号("")

sed -i 's#\"#\"\"#g' file

sed -i "s#\"#\"\"#g" file

 
单引号(')替换成两个单引号('')sed -i "s#'#''#g" file×不能用单引号括起来,分不清了
($)替换成\$sed -i 's:\$:\\\$:g' file×不能用双引号,否则会认为是$(正则匹配结尾位置)行的结果追加字符呢

(4)curl时用的变量,sed转化

curl -H 'Content-Type: application/json' -X POST -d 参数

(参数中涉及到特殊字符都得转义,而且要多转一层,即$得转成\\$,才能原封不动的供后续使用)
#值替换单引号、反斜杠、双引号 curl的时候用,多一层转义,所以\要用\\

sed -i "s#'#''#g" ${file}      ---单引号要转成两个单引号

sed -i 's#\\#\\\\\\\\#g' ${file}    ---反斜杠

sed -i "s:\":\\\\\":g" ${file}      ---双引号

sed -i 's:\$:\\\\\$:g' ${file}    ---$符

curl引用参数的这种形式有两种写法:

1)直接引用单个参数变量
curl -H 'Content-Type: application/json' -X POST -d '{"type":"0","name":" ' ${pa_name} ' "}'
这种需要对变量额外加上一个单引号,才能引用生效。

2)整个参数变量作为一个整体(推荐)
param="{\"type\":\"0\", \"name\":\"${pa_name}\"}"
curl -H 'Content-Type: application/json' -X POST -d "${param}"

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/257761.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微软官宣放出一个「小模型」,仅2.7B参数,击败Llama2和Gemini Nano 2

就在前一阵谷歌深夜炸弹直接对标 GPT-4 放出 Gemini 之后,微软这两天也紧锣密鼓进行了一系列动作。尽管时间日趋圣诞假期,但是两家巨头硬碰硬的军备竞赛丝毫没有停止的意思。 就在昨日,微软官宣放出一个“小模型” Phi-2,这个 Ph…

构建智慧储能物联网,4G工业路由器远程监测在线管理

物联网技术的发展为智慧储能管理带来了革命性的变化。其中,4G工业路由器IR5000通过丰富的连接能力如串口RS485/232或网口的方式,实现了与储能现场各设备的连接,包括电表、电能检测器、防孤岛装置、BMS电池管理系统、监控服务器、储能控制器、…

K8s攻击案例:RBAC配置不当导致集群接管

01、概述 Service Account本质是服务账号,是Pod连接K8s集群的凭证。在默认情况下,系统会为创建的Pod提供一个默认的Service Account,用户也可以自定义Service Account,与Service Account关联的凭证会自动挂载到Pod的文件系统中。 …

JNDI注入Log4jFastJson白盒审计不回显处理

目录 0x00 前言 0x01 Maven 仓库及配置 0x02 JNDI 注入简介 0x03 Java-第三方组件-Log4J&JNDI 0x04 Java-第三方组件-FastJson&反射 0x05 白盒审计 - FastJson 0x06 白盒审计 - Log4j 0x07 不回显的处理方法 0x00 前言 希望和各位大佬一起学习,如果…

ubuntu推送本地仓库到coding

本教程提供在ubuntu系统下推送本地仓库到coding的指令,用于查阅 一、主要步骤有: 0.初始化仓库 git init 1.添加远程仓库 git remote add origin https://coding.git #修改自己仓库链接 (命名仓库别名为origin) 2.提交代码…

金融CRM有用吗?金融行业CRM有哪些功能

市场形式波诡云谲,金融行业也面临着资源体系分散、竞争力后继不足、未知风险无法规避等问题。金融企业该如何解决这些问题,或许可以了解一下CRM管理系统,和其提供的金融行业CRM解决方案。 金融行业是银行业、保险业、信托业、证券业和租赁业…

lv12 linux 内核移植 10

目录 1 内核概述 1.1 内核与操作系统 1.2 Linux层次结构 1.3 Linux内核特点 2 Linux内核源码结构 2.1 Linux内核源码获取 2.2 源码结构 3 Linux内核移植 3.1 在 Linux 官网下载 Linux 内核源码(这里我们下载 linux-3.14.tar.xz) 3.2 拷贝内核源…

centos开机自启动实战小案例

1.编写一个我们需要做事的脚本 #!/bin/bash # 打印 "Hello" echo "Hello,Mr.Phor" # 为了更好的能看到效果 我们把这段文本放置到一个文件中 如果重启能够看到 /a.txt文件 我们实验成功 echo "hahahahahahahaha" > /a.txt #每次开机 执行…

Windows/Linux双系统安装(双系统独立分盘)

一、固态硬盘、机械硬盘及U盘概述 (一)机械硬盘[1][3] 硬盘驱动器(Hard Disk Drive,HDD),又称“机械硬盘”或“传统硬盘”,是电脑上使用刚性的旋转磁性盘片为基础的非依电性存储器,…

Eclipse_03_如何加快index速度

1. ini配置文件 -Xms:是最小堆内存大小,也是初始堆内存大小,因为堆内存大小可以根据使用情况进行扩容,所以初始值最小,随着扩容慢慢变大。 -Xmx:是最大堆内存大小,随着堆内存的使用率越来越高&a…

CentOS 8离线安装telnet

下载telnet rpm安装包,可从https://www.rpmfind.net/linux/rpm2html/search.php?querytelnet&submitSearch…&systemcentos&arch 根据自己的操作系统下载对应的包,这里以CentOS8为例,分别下载如下的rtp包 xinetd-2.3.15-24.el8.x86_64.rpm…

IDEA shorten command line介绍和JAR manifest 导致mybatis找不到接口类处理

如果类路径太长,或者有许多VM参数,程序就无法启动。原因是大多数操作系统都有命令行长度限制。在这种情况下,IntelliJIDEA将试图缩短类路径。最好选中 classpath file模式。 shorten command line 选项提供三种选项缩短类路径。 none&#x…

JMUer-网络新技术课程期末考试复习整理

✏️write in front✏️ 📝个人主页:陈丹宇jmu 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝​ 🙉联系作者🙈by QQ:813942269🐧 🌈致亲爱的读者:很高兴你…

智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黑寡妇算法4.实验参数设定5.算法结果6.参考文…

单片机应用实例:LED显示电脑电子钟

本例介绍一种用LED制作的电脑电子钟(电脑万年历)。其制作完成装潢后的照片如下图: 上图中,年、月、日及时间选用的是1.2寸共阳数码管,星期选用的是2.3寸数码管,温度选用的是0.5寸数码管,也可根据…

Vue+ElementUI前端添加展开收起搜索框按钮

1、搜索框添加判断 v-if"advanced" <el-form-item label"创建日期" v-if"advanced"><el-date-pickerv-model"daterangeLedat"size"small"style"width: 240px"value-format"yyyy-MM-dd"type&q…

基于grpc从零开始搭建一个准生产分布式应用(7) - 01 - 附:GRPC拦截器源码

开始前必读&#xff1a;​​基于grpc从零开始搭建一个准生产分布式应用(0) - quickStart​​ 一、源码目录结构 二、GRPC拦截器源码 2.1、com.zd.baseframework.core.core.common.interceptor package com.zd.baseframework.core.core.common.interceptor;import com.zd.ba…

element plus 表格el-table行多选单选

1 行多选-点击checkbox 添加一个 el-table-column&#xff0c;设 type 属性为 selection 即可 <template><div class"box"><el-table :data"tableData" selection-change"handleSelectionChange"><el-table-column type&…

docker小白第六天

docker小白第六天 容器数据卷是什么 首先&#xff0c;容器卷有个坑&#xff1a;容器卷需要加入privilegedtrue&#xff0c;如下图所示&#xff0c;是为了解决permission denied的问题。其中“挂载”的意思是相当于一个硬盘插到主机上。使用该命令。是扩大容器的权限解决挂载目…

路由器设置代理IP教程,http代理怎么固定IP地址?

路由器设置代理IP教程 一、确定代理IP地址 首先&#xff0c;你需要确定你要使用的代理IP地址。你可以从代理服务提供商处获取代理IP地址和端口号。 二、登录路由器管理界面 在浏览器中输入路由器的IP地址&#xff0c;输入账号和密码&#xff0c;进入路由器的管理界面。 三、设置…