持续集成交付CICD:Jenkins使用基于SaltStack的CD流水线部署前后端应用

目录

一、实验

1.Jenkins使用基于SaltStack的CD流水线部署后端应用

2.Jenkins使用基于SaltStack的CD流水线部署前端应用


一、实验

1.Jenkins使用基于SaltStack的CD流水线部署后端应用

(1)GitLab添加Token

(2)Jenkins添加凭据

(3)devops03-env 添加脚本

# sh service.sh devops03-devops-service 1.1.1 9099 start
APPNAME=$1
VERSION=$2
PORT=$3

start(){
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`

    if [[ $port_result == "false" ]];then
        nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    else
       stop
       sleep 5
       nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    fi
}


stop(){
    pid=`netstat -anlpt | grep "${PORT}" | awk '{print $NF}' | awk -F '/' '{print $1}'`
    kill -15 $pid
}


check(){
    proc_result=`ps aux | grep java | grep "${APPNAME}" | grep -v grep || echo false`
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`
    url_result=`curl -s http://localhost:${PORT} || echo false `

    if [[ $proc_result == "false" || $port_result == "false" || $url_result == "false" ]];then
        echo "error"
    else
        echo "ok"
    fi
}

case $4 in
    start)
        start
        sleep 5
        check
        ;;

    stop)
        stop
        sleep 5
        check
        ;;
    restart)
        stop
        sleep 5
        start
        sleep 5
        check
        ;;
    check)
        check
        ;;
    *)
        echo "sh service.sh {start|stop|restart|check}"
        ;;
esac

(4)Jenkins给后端项目CD流水线添加参数

(5)Jenkins安装插件HTTP Request

(5) 修改流水线代码

pipeline {
    agent { label "build" }
    stages{
        stage("PullArtifacts"){
            steps{
                script{
                    repoName = "${JOB_NAME}".split("/")[0]
                    env.projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]

                    if ("${env.projectType}" == "maven"){
                        type="jar"
                    }
                    if ("${env.projectType}" == "npm"){
                        type="tar.gz"
                    }
                    PullArtifacts("${env.releaseVersion}","${env.projectName}",repoName,type)

                    env.pkgName="${env.projectName}-${env.releaseVersion}.${type}"
                }
            }
        }
        stage("DeployHost"){
            steps{
                script{
                    print("DeployHost")
                    // 文件内容写到本地
                    response = GetRepoFile(21, "service.sh", "master")
                    writeFile file: 'service.sh', text: "${response}"
                    sh "ls -a "


                    if ("${env.deployTool}" == "saltstack"){

                        targetHosts = "${env.saltHosts}"
                        println(targetHosts)
                        localDeployDir = "/srv/salt/${env.projectName}"
                        sh """
                            [ -d ${localDeployDir} ] || mkdir -p ${localDeployDir}
                            mv service.sh ${env.pkgName} ${localDeployDir}
        
                            # 清理发布目录
                            salt -L "${targetHosts}" cmd.run  "rm -fr ${targetDir}/${env.projectName}/* &&  mkdir -p ${targetDir}/${env.projectName} || echo file is exists"
            
                            # 发布应用
                            salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/${env.pkgName} ${targetDir}/${env.projectName}

                            # 发布启动脚本
                            salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/service.sh ${targetDir}/${env.projectName}

                            # 启动服务
                            salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} start"

                            # 检查服务
                            sleep 5
                            salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} check"
                                                        
                           """
                    }
                }
            }
        }
        stage("ServiceCtrl"){
            steps{
                script{
                    print("ServiceCtrl")
                }
            }
        }
        stage("HealthCheck"){
            steps{
                script{
                    print("HealthCheck")
                }
            }
        }
    }
}


//下载制品
def PullArtifacts(version,projectName,repoName,type){
    repoUrl = "http://192.168.204.13:8081/repository"
    pkgPath = "${repoUrl}/${repoName}/${projectName}/${version}/${projectName}-${version}.${type}"
    sh "wget --http-user=admin --http-passwd=Admin123 ${pkgPath} -q"
}

// 封装HTTP
def HttpReq(reqType, reqUrl,reqBody ){
    def gitServer = "http://192.168.204.8:82/api/v4"
    withCredentials([string(credentialsId: '02dce3ff-4e46-4de2-b079-5dd6093d4f64', variable: 'GITLABTOKEN')]) {
        response = httpRequest acceptType: 'APPLICATION_JSON_UTF8',
                consoleLogResponseBody: true,
                contentType: 'APPLICATION_JSON_UTF8',
                customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]],
                httpMode: "${reqType}",
                url: "${gitServer}/${reqUrl}",
                wrapAsMultipart: false,
                requestBody: "${reqBody}"

    }
    return response
}

//获取文件内容
def GetRepoFile(projectId,filePath, branchName ){
    //GET /projects/:id/repository/files/:file_path/raw
    apiUrl = "/projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"
    response = HttpReq('GET', apiUrl, "")
    return response.content
}

(6)手动构建流水线

(7)watch命令观察

# watch -n 1 "ps aux | grep 9099"

(8) 成功

(9) GitLab后端项目新建分支

(10)Jenkins后端项目CI流水线手动构建

(11) 成功

(12)Nexus查看

(13)Jenkins手动构建后端项目CD流水线

(14)成功

(15)查看本地目录

# cd /optdevops03-devops-service/
# ls

2.Jenkins使用基于SaltStack的CD流水线部署前端应用

(1)主机安装nginx

1)添加 nginx 到 yum 源中
sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

2)安装 nginx (在把nginx添加到 yum 源之后,就可以使用 yum 安装了)
sudo yum install -y nginx

3)稍等一会,即可安装完成

4)启动 nginx
sudo systemctl start nginx.service

5)设置 nginx 开机自启动
sudo systemctl enable nginx.service

(2)nginx 配置信息


1)网站文件存放默认位置(Welcome to nginx 页面)
/usr/share/nginx/html

2)网站默认站点配置
/etc/nginx/conf.d/default.conf

3)自定义 nginx 站点配置文件存放目录
/etc/nginx/conf.d/

4)nginx 全局配置文件
/etc/nginx/nginx.conf

5)启动 nginx
service nginx start

6)关闭 nginx
service nginx stop

7)重启 nginx
service nginx restart
service nginx reload

8) 加成nginx
nginx -t

(3)Jenkins新建前端项目CD流水线

(4)添加参数

(5)修改nginx配置文件

# /etc/nginx/nginx.conf
  1 
  2 user  nginx;
  3 worker_processes  auto;
  4 
  5 error_log  /var/log/nginx/error.log notice;
  6 pid        /var/run/nginx.pid;
  7 
  8 
  9 events {
 10     worker_connections  1024;
 11 }
 12 
 13 
 14 http {
 15     include       /etc/nginx/mime.types;
 16     default_type  application/octet-stream;
 17 
 18     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
 19                       '$status $body_bytes_sent "$http_referer" '
 20                       '"$http_user_agent" "$http_x_forwarded_for"';
 21 
 22     access_log  /var/log/nginx/access.log  main;
 23 
 24     sendfile        on;
 25     tcp_nopush      on;
 26     tcp_nodelay     on;
 27     types_hash_max_size 2048;
 28 
 29 
 30     keepalive_timeout  65;
 31 
 32     #gzip  on;
 33 
 34     include /etc/nginx/conf.d/*.conf;
 35 
 36 
 37 server {
 38     listen 8099;
 39     server_name _;
 40     root /usr/share/nginx/html/devops03-devops-ui;
 41 
 42     # Load configuration files for the default server block.
 43     include /etc/nginx/default.d/*.conf;
 44 
 45     location / {
 46     }
 47 
 48     error_page 404 /404.html;
 49         location = /40x.html {
 50     }
 51 
 52     error_page 500 502 503 504 /50x.html;
 53         location = /50x.html {
 54     }
 55  }

# nginx -t

# curl 127.0.0.1:8099

验证:

(6)修改前端项目CD流水线代码

pipeline {
    agent { label "build" }
    stages{
        stage("PullArtifacts"){
            steps{
                script{
                    repoName = "${JOB_NAME}".split("/")[0]
                    env.projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]

                    if ("${env.projectType}" == "maven"){
                        type="jar"
                    }
                    if ("${env.projectType}" == "npm"){
                        type="tar.gz"
                    }
                    PullArtifacts("${env.releaseVersion}","${env.projectName}",repoName,type)

                    env.pkgName="${env.projectName}-${env.releaseVersion}.${type}"
                }
            }
        }
        stage("DeployHost"){
            steps{
                script{
                    print("DeployHost")


                    if ("${env.deployTool}" == "saltstack"){

                        targetHosts = "${env.saltHosts}"
                        println(targetHosts)
                        localDeployDir = "/srv/salt/${env.projectName}"
                        sh """
                            [ -d ${localDeployDir} ] || mkdir -p ${localDeployDir}
                            mv ${env.pkgName} ${localDeployDir}
        
                            # 清理发布目录
                            salt -L "${targetHosts}" cmd.run  "rm -fr ${targetDir}/${env.projectName}/* &&  mkdir -p ${targetDir}/${env.projectName} || echo file is exists"
            
                            # 发布应用
                            salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/${env.pkgName} ${targetDir}/${env.projectName}
                   
                           """
                    }
                }
            }
        }
        stage("ServiceCtrl"){
            steps{
                script{
                    print("ServiceCtrl")
                    localDeployDir = "/srv/salt/${env.projectName}"

                    if ("${env.projectType}" == "maven") {
                        // 文件内容写到本地
                        response = GetRepoFile(21, "service.sh", "master")
                        writeFile file: 'service.sh', text: "${response}"
                        sh "ls -a "

                        sh """
                             mv service.sh  ${localDeployDir}
                             # 发布启动脚本
                             salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/service.sh ${targetDir}/${env.projectName}
                             
                             # 启动服务
                             salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} start"
    
                             # 检查服务
                             sleep 5
                             salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} check"
                            
                            
                        """
                    }

                    if ("${env.projectType}" == "npm") {
                        sh """
                             # 启动服务
                             salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;tar zxf ${env.pkgName}"

                            """


                    }

                }
            }
        }
        stage("HealthCheck"){
            steps{
                script{
                    print("HealthCheck")
                }
            }
        }
    }
}


//下载制品
def PullArtifacts(version,projectName,repoName,type){
    repoUrl = "http://192.168.204.13:8081/repository"
    pkgPath = "${repoUrl}/${repoName}/${projectName}/${version}/${projectName}-${version}.${type}"
    sh "wget --http-user=admin --http-passwd=Admin123 ${pkgPath} -q"
}

// 封装HTTP
def HttpReq(reqType, reqUrl,reqBody ){
    def gitServer = "http://192.168.204.8:82/api/v4"
    withCredentials([string(credentialsId: '02dce3ff-4e46-4de2-b079-5dd6093d4f64', variable: 'GITLABTOKEN')]) {
        response = httpRequest acceptType: 'APPLICATION_JSON_UTF8',
                consoleLogResponseBody: true,
                contentType: 'APPLICATION_JSON_UTF8',
                customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]],
                httpMode: "${reqType}",
                url: "${gitServer}/${reqUrl}",
                wrapAsMultipart: false,
                requestBody: "${reqBody}"

    }
    return response
}

//获取文件内容
def GetRepoFile(projectId,filePath, branchName ){
    //GET /projects/:id/repository/files/:file_path/raw
    apiUrl = "/projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"
    response = HttpReq('GET', apiUrl, "")
    return response.content
}

(7)Jenkins手动构建前端项目CD流水线

(8)成功

(9)GitLab前端项目新建分支

(10)Jenkins手动构建前端项目CI流水线

(11)成功

(12)Nexus查看

(13)Jenkins手动构建前端项目CD流水线

(14)命令观察

# watch -n 1 "ls devops03-devops-ui"

# for i in `seq 1000`; do sleep 1 ; curl http://127.0.0.1:8099; echo -e "\n\n\n";done

(15) 查看本地目录

# cd /usr/share/nginx/html/
# ls

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

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

相关文章

Modbus转Profinet网关配置步骤

Modbus转Profinet网关(XD-MDPN100/200)是用于将Modbus协议和Profinet协议进行转换并进行通迅的设备。Modbus转Profinet网关(XD-MDPN100/200)无论是新项目还是改造项目都可轻松配置完成通迅互联。 正确的安装和配置对于确保设备的正…

重新思考U-Net在医学超声图像分割中的应用(NU-net)

Rethinking the Unpretentious U-net for Medical Ultrasound Image Segmentation 摘要: 乳腺肿瘤分割是帮助我们描述和定位肿瘤区域的关键步骤之一。然而,乳腺肿瘤形态多变、边界模糊、强度分布相似,给乳腺肿瘤的准确分割带来了挑战。近年…

matter模组有无源测试事例

测试一款matter模组的硬件性能 1.1 天线阻抗、电压驻波比测试 主要测试:PCB板载天线设计效率及板材PCB铜面的平整度等 1.2 模组有源数据测试 主要测试:模组的阻抗匹配、频偏等情况 1.3 模组传输能量精度 主要测试:矢量误差等数据 1.4 模…

多家高校设立“鸿蒙班”;ChatGPT 成为 Nature 年度十大人物丨 RTE 开发者日报 Vol.107

开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE (Real Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

C# WPF上位机开发(利用tcp/ip网络访问plc)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 c# wpf如果是用来开发非标上位机的,那么和plc的通信肯定是少不了的。而且,大部分plc都支持modbus协议,所以这个…

焊盘:十字连接VS全覆盖 铺铜

在铺铜规则中,焊盘连接方式有两种: 十字连接 优点:较好焊接:因铺铜面积减少,温度下降速度降低,较好焊接,不易虚焊。 缺点:载流能力较弱:铺铜面积↓ → 载流能力↓全连接…

IDEA:TomEE 主目录/基目录出错

错误示例: 错误分析:创建Tomcat项目时,错误地创建了TomcatEE项目,重新创建即可。

【Java 集合】ConcurrentLinkedQueue

在日常中, 我们用到的数据结构有很多: 数组, 链表, 树等, 而在这些结构中, 还有一个叫做队列的存在。 和其他的集合相同, Java 原生提供了不同的实现。 而如果我们需要一个线程安全的队列的话, 可以基于实际的场景进行选择, 比如基于数组实现同时操作上会阻塞的 ArrayBlockingQ…

BRAS应用场景及测试方法

什么是BRAS? 宽带接入服务器(Broadband Remote Access Server,简称BRAS)是面向宽带网络应用的新型接入网关,它位于骨干网的边缘层,可以完成用户带宽的IP/ATM网的数据接入。 宽带接入服务器(BRAS&#xff0…

STL中sort的底层实现

文章目录 1、源码分析2、算法优化3、总结 在讲解STL中sort的底层原理之前,先引申出这样几个问题? ①STL中sort的底层是采用哪种或者哪几种排序? ②STL中sort会导致栈溢出吗? ③快速排序的时间复杂度是不稳定的 l o g 2 n log_2n l…

基于Java (spring-boot)的二手物品交易平台

​ 一、项目介绍 1、管理员功能 (1)登录:管理员能够根据账号访问系统。 (2)用户管理:管理员可以添加、删除、修改用户信息,查看用户列表,对用户进行管理和控制。例如&#xff0c…

死锁的预防、避免、检测和消除

一、预防死锁 1. 破坏互斥条件 2. 破坏不剥夺条件 3.破坏请求和保持条件 4.破坏循环等待条件 二、避免死锁 避免死锁的一种方法是使用银行家算法,它涉及到安全序列的概念。银行家算法是一种资源分配和死锁避免的算法,它确保系统能够分配资源而不会导致死…

十五、YARN辅助架构

1、学习内容 (1)了解什么是代理服务器 (2)了解什么是历史服务器 2、辅助架构 (1)辅助架构的由来 对于YARN架构来讲,除了ResourceManager集群资源总管家、NodeManager单机资源管家两个核心角…

『番外篇三』Swift “乱弹”之带索引遍历异步序列(AsyncSequence)

概览 在 Swift 开发中,我们往往在遍历集合元素的同时希望获得元素对应的索引。在本课中,我们将向小伙伴们展示除 enumerated() 方法之外的几种实现思路。在玩转普通集合之后,我们将用“魔法棒”进一步搞定异步序列带索引遍历的实现。 在本篇博主中,您将学到以下内容: 概…

Makefile基础使用与原理

一、基本概念 通常我们编写好代码后,都需要编译,只是这些操作是由IDE来完成,我们只需要点击一个编译按钮。当项目工程越来越庞大,存在几十个甚至更多的文件的时候,你使用的不是IDE工具,而是命令行&#xf…

基于JavaWeb+SSM+Vue微信小程序的移动学习平台系统的设计和实现

基于JavaWebSSMVue微信小程序的移动学习平台系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 第1章 绪论 1 1.1 课题背景 1 1.2 课题意义 1 1.3 研究内容 2 第2章 开发环…

采用nodejs + socket.io实现简易聊天室功能(群聊 + 私聊)

项目演示 支持群聊以及私聊 项目代码 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport…

Android12-RK3588_s-开机动画

目录 一、实现自定义开机动画 步骤一&#xff1a;准备 bootanimation.zip 步骤二&#xff1a;将 bootanimation.zip 放到 /system/media/bootanimation.zip下 步骤三&#xff1a;重启即可 二、注意事项 2.1 bootanimation.zip 压缩 2.2 bootanimation.zip 存放 2.3 boo…

RabbitMQ插件详解:rabbitmq_web_stomp【RabbitMQ 六】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 《RabbitMQ Web STOMP&#xff1a;打破界限的消息传递之舞》 前言STOMP协议简介STOMP&#xff08;Simple Text Oriented Messaging Protocol&#xff09;协议简介STOMP与WebSocket的关系 WebSocket和R…

Certbot实现 HTTPS 免费证书(Let‘s Encrypt)自动续期

Certbot实现 HTTPS 自动续期 以前阿里云支持申请一年的免费https证书&#xff0c;那每年我们手动更新证书并没什么大问题&#xff0c;但现在阿里云的免费证书仅支持3个月&#xff0c;这意味着每三个月都要要申请一下证书显得非常麻烦。 下面我们使用Certbot实现ssl证书的自动…