1、网络架构图如下

2、采用这种方案的原因

1、现网机器都在各个省机房内网,或者堡垒机内部。无法直接从公司总部ssh到各个现网机器
2、现网机器可以访问到公网。因此可以从公网下载制作的tar包
3、每次升级现网项目实际通过vpn远程或者堡垒机方式登录。然后手工把tar包传输到对应机器上,操作繁琐,浪费大量时间

  

3、方案特点描述

1、采用gitlab作为公司私有代码托管仓库,和开发约定好采用tag标签作为发布版本
2、jenkins机器有2台,一个master,一台slave。这里在jenkins上配置只使用slave机器干活。jenkins机器数量和本次实验并无直接关系。一台jenkins也行
3、各个地区安装有salt-minion。用于接收salt-master的指令从公网下载对应tar包,以及执行部署等。通过salt方式绕过vpn和堡垒机
4、公司总部是20MB的电信专线。各个地区现网机器处于移动机房、联通机房等。出于各个地区minion机器下载tar包网络稳定性的考虑。采用一台带公网IP阿里云ECS作为制品库机器
5、ECS配置为2C/4G内存/200GB硬盘/100MB按流量付费的类型,安装nginx并配置文件下载服务,用于minion机器下载tar包
6、jenkins上配置项目为参数化构建,有2个参数,一个参数是代码版本,另一个参数是是否重启Tomcat的布尔值(涉及到java项目)
7、采用pipeline方式执行整个代码拉取构建和发布
8、salve机器需要做免密钥登录salt-master机器执行命令或者脚本(出于安全考虑后期可以调整ssh执行命令权限)
9、slave机器做免密钥登录公网阿里云机器。把构建编译打包后的tar包传输到制品库机器
10、本方案可以发布对应tag版本代码也可以发布最新代码
11、针对每个tar包配置一个job。比如我一个机器上部署2个tomcat,每个tomcat下面有3个war包。那么我在jenkins中创建6个job。每个job对应一个war包
12、关于tag包这里约定含有打标记的时间。比如v1226.1表示12月26日打第一个tag。

  

单个job配置截图如下

下面没有要设置的地方,后期如果有需要可以设置自动触发构建等

下面在头部定义变量。类似shell脚本

def PKG_NAME="demores"  表示项目包的名字,也就是最终软链接到tomcat的webapps下面的名字
def PROJ_NAME="GZDX-DDZ-PROD"  是地区名--业务名--生产 的缩写,GZDX表示广州电信机房,DDZ是业务名,是斗地主的缩写。PROD表示现网def CODE_URL="git@10.0.2.61:game-group/demoddz.git"  是源码仓库地址
def DIFF_URL="git@10.0.2.61:game-group/demoddz-diff.git" 是源码仓库开发维护的配置(比如一些各个地区各个项目的差异配置文件)
def CONF_URL="git@10.0.2.61:game-group/demoddz-config.git" 是运维维护的配置文件,比如数据库连接方式配置文件等def CRED_ID="412f328e-8b79-44f6-b6d8-2cad518475c2" 是groovy语法生成器拉取git代码部分生成的信任IDdef PROD_SERVER="47.110.xxx.xxx"  就是阿里云的ECS机器IP ,作为制品库def MINION_ID="gzdx-ddz-web-01.hzdg.cn" 对应一个minion的id

  

关于上面的def CRED_ID="412f328e-8b79-44f6-b6d8-2cad518475c2"

如果设置了deploy-key拉取gitlab代码。下面这里就是固定不变的了。用到多次的话可以把它设置成变量提取到前面方便引用

整个pipeline内容如下

node{def PKG_NAME="dawnres"def PROJ_NAME="GZDX-TTMQ-PROD"def CODE_URL="git@10.0.2.61:game-group/DawnEDUEPGGame.git"def DIFF_URL="git@10.0.2.61:game-group/DawnEDUEPGGame-diff.git"def CONF_URL="git@10.0.2.61:game-group/DawnEDUEPGGame-config.git"def CRED_ID="412f328e-8b79-44f6-b6d8-2cad518475c2"def PROD_SERVER="47.110.xxx.xxx"def MINION_ID="gzdx-ddz-web-01.hzdg.cn"stage("拉取源码"){echo "git pull src code ${PKG_NAME}"       git credentialsId: "${CRED_ID}", url: "${CODE_URL}"sh '[ -n "${CODE_TAG}" ] &&  git checkout "${CODE_TAG}" ||  { echo -e "切换至指定的tag的版本,tag:"${CODE_TAG}" 不存在或为空,请检查输入的tag!" && exit 111; }'}stage("代码编译"){echo "ant build ${PKG_NAME}"sh "/data/app/ant/bin/ant"}stage("确定时间戳和其它变量") {script {def now = new Date()CTIME=now.format("yyyy_MMdd_HHmmss", TimeZone.getTimeZone('GMT+8'))println "${CTIME}"CODE_TAG="${CODE_TAG}".replaceAll("/", "_")TAR_NAME="${PKG_NAME}-${CTIME}-${CODE_TAG}"}}stage("拷贝编译后的产物"){sh "mkdir -p /deploy/${PROJ_NAME}/tmp/${TAR_NAME}/"sh "/bin/cp -a WebRoot/* /deploy/${PROJ_NAME}/tmp/${TAR_NAME}/"}    stage("拉取差异文件"){echo "git pull src code ${PKG_NAME}-diff"git credentialsId: "${CRED_ID}", url: "${DIFF_URL}"sh "/bin/cp -a WebRoot/* /deploy/${PROJ_NAME}/tmp/${TAR_NAME}/"}stage("拉取配置文件"){echo "git pull src code ${PKG_NAME}-conf"git credentialsId: "${CRED_ID}", url: "${CONF_URL}"sh "/bin/cp -a WebRoot/* /deploy/${PROJ_NAME}/tmp/${TAR_NAME}/"}    stage("打包目录"){echo "tar pgk"sh "cd /deploy/${PROJ_NAME}/tmp/ && tar cfz ${TAR_NAME}.tgz ${TAR_NAME}"}stage("传输包到制品库"){sh "ssh root@${PROD_SERVER}" + '  "' +"mkdir -p" +" /deploy/${PROJ_NAME}/"+'"'sh "scp /deploy/${PROJ_NAME}/tmp/${TAR_NAME}.tgz" + " root@${PROD_SERVER}:/deploy/${PROJ_NAME}/"}stage("minion下载tar包"){sh "/data/scripts/salt-download-pkg.sh"+ "  ${MINION_ID}"+"  ${PROJ_NAME}"+"  ${TAR_NAME}"sh "echo hehe"}stage('现网环境部署确认'){input("执行现网环境部署")sh "/data/scripts/salt-deploy-pkg.sh"+"  ${MINION_ID}"+"  ${TAR_NAME}"+"   ${RestartTomcat}"}
}

  

如果发布选择的是origin/master需要做一个处理

打包后的文件名需要把斜线去掉或者替换掉,因为linux斜线就分割为目录了
这里是替换为下划线了最终的TAG_NAME就是下面这种

demores-2018_1226_142912-origin_master

  

如果选择的是tag,比如是v1226.2版本 那么TAG_NAME就是下面这种

demoweb-2018_1226_134619-v1226.2

  

主要业务是javaweb。开发这边jar包都是单独下载的。每次发布都是仅仅是编译class文件。因此采用ant

下面2个脚本都在jenkins的slave机器上

让对应的minion下载对应的tar包脚本

pipeline中可以直接写命令 由于括号太多的问题。这里就用了脚本方式调用salt远程执行命令

[root@jenkins-slave-1 /data/scripts]# cat salt-download-pkg.sh
#!/bin/bash
SALT_MASTER="10.0.1.61"
MINION_ID="$1"
PROJ_NAME="$2"
TAR_NAME="$3"
PROD_SERVER_PORT="47.110.xxx.xxxx:18181"
ssh root@${SALT_MASTER} " salt \"${MINION_ID}\"  cmd.run \"wget -O /data/pkgroot/${TAR_NAME}.tgz http://${PROD_SERVER_PORT}/deploy/${PROJ_NAME}/${TAR_NAME}.tgz\" "
[root@jenkins-slave-1 /data/scripts]#

  

下载的包tar包统一存放在/data/pkgroot/目录下

让对应minion机器执行部署操作脚本

下面是让对应的minion执行自己机器上/data/scripts/deploy.sh脚本

[root@jenkins-slave-1 /data/scripts]# cat salt-deploy-pkg.sh
#!/bin/bash
SALT_MASTER="10.0.1.61"
MINION_ID="$1"
TAR_NAME="$2"
RESTART_FLAG="$3"
ssh root@${SALT_MASTER} " salt \"${MINION_ID}\"  cmd.run \"/data/scripts/deploy.sh ${TAR_NAME} ${RESTART_FLAG} \" "[root@jenkins-slave-1 /data/scripts]#

  

其中/data/scripts/deploy.sh是在minion机器上的脚本

因为各个地区现网项目标准化程度不够。
有的机器上有一个1个tomcat
有的机器有2个tomcat。
这个脚本要具备通过包名判断这个包属于哪个tomcat的功能

  

比如下面2个tomcat。

4、一次代码发布到现网机器的过程

1、jenkins页面点击参数化构建。选择一个版本。根据是否有配置文件或者class文件变更选择是否重启Tomcat
2、slave机器根据版本号从gitlab拉取代码。执行编译操作。然后拉取配置文件
3、使用groovy代码生成一个时间戳变量 比如2018_1226_134619 表示2018年12月26日13点36分19秒
4、根据pipeline框中定义好的包名,以及上面的时间戳变量,和参数构建的版本号变量构成本次打包的文件包名,比如demores-2018_1226_134619-v1226.2
5、把目录打成tgz的包demores-2018_1226_134619-v1226.2.tgz
6、salve机器把这个包scp方式传输到阿里云机器(制品库)
7、salve机器ssh到salt-master机器执行命令让对应minion下载这个tar包
8、设置一个交互式input选项是否执行最终部署。也可以登录机器手动执行deploy.sh脚本进行部署

  

minion机器上,也就是web机器上有4个脚本

通过文件名可以知道大概意思

[root@router /data/scripts]# ll
total 20
-rwxr-xr-x 1 root root  671 Dec 28 15:32 clean_old_pkg.sh
-rwxr-xr-x 1 root root 6667 Jan 10 01:56 deploy.sh
-rwxr-xr-x 1 root root  796 Dec 25 20:24 restart_tomcat8_18080.sh
-rwxr-xr-x 1 root root  800 Dec 25 20:23 restart_tomcat8_28080.sh
[root@router /data/scripts]#

  

清除历史版本脚本

对于pkgroot目录。如果频繁升级。会积累很多目录
这里通过写了一个脚本,针对每一种项目包保留最近的10个版本
deploy在部署成功新版本之后会调用执行它删除老版本

[root@router /data/pkgroot]# cat /data/scripts/clean_old_pkg.sh
#!/bin/bash
PKG_ROOT="/data/pkgroot"PKGS=`ls $PKG_ROOT  |awk  '{print $NF}' |awk -F '[-]' '{print $1}' |sort -u`
for item in ${PKGS[@]}
do
#保留文件数
ReservedNum=10
date=$(date "+%Y%m%d-%H%M%S")FileNum=$(ls -l $PKG_ROOT/ |grep $item | wc -l)while(( $FileNum > $ReservedNum))
doOldFile=$(ls -rt $PKG_ROOT/ |grep $item | head -1)echo  $date "Delete File:" ${PKG_ROOT}/$OldFilerm -rf ${PKG_ROOT}/$OldFilelet "FileNum--"
done
done[root@router /data/pkgroot]#

  

重启tomcat的脚本

[root@router /data/scripts]# cat restart_tomcat8_18080.sh
#!/bin/sh
TOMCAT_SERVICE=tomcat8_18080
TOMCAT_PATH=/data/app/tomcat8_18080/binecho "TOMCAT_PATH is $TOMCAT_PATH"PID=`ps aux | grep "${TOMCAT_PATH}" | grep java | awk '{print $2}'`if [ -n "$PID" ]; thenecho "Will kill tomcat: $PID"systemctl stop ${TOMCAT_SERVICE}sleep 6
else echo "No Tomcat Process $PID"
fiPID2=`ps aux | grep "${TOMCAT_PATH}" | grep java | awk '{print $2}'`if [ -n "$PID2" ]; thenkill -9 $PID2echo "Try to kill $PID2"
else echo "No Tomcat Process $PID2"
fi#startup tomcat servicesystemctl start ${TOMCAT_SERVICE}sleep 3PID=`ps aux | grep "${TOMCAT_PATH}" | grep java | awk '{print $2}'`
if [ -n "$PID" ]; thenecho "Restart tomcat successfully!"
elseecho "Fail to startup tomcat"exit 1
fi
[root@router /data/scripts]#

  

deploy.sh脚本
写的不够优雅。有待优化

[root@router /data/scripts]# cat deploy.sh
#!/bin/bash
TAR_NAME=$1
RESTART_FLAG=$2
PKG_ROOT="/data/pkgroot"
WEB_ROOT_1=/data/app/tomcat8_18080/webapps
WEB_ROOT_2=/data/app/tomcat8_28080/webapps#定义包的数组,用于判断传过来的包名是否在这个机器上
pkg_arr=("dawnweb" "dawnvideo" "dawnres")#用于判断包在哪个tomcat中,注意2个tomcat的包不能有重名的。否则无法判断属于哪个tomcat
pkg_arr_1=("dawnweb")
pkg_arr_2=("dawnvideo" "dawnres")#如果tomcat2不存在,数组2写为空即可,如下所示
#pkg_arr_2=()#重启对应的tomcat的脚本
restart_tomcat_1=/data/scripts/restart_tomcat8_18080.sh
restart_tomcat_2=/data/scripts/restart_tomcat8_28080.sh#清除过期历史版本脚本clean_old_pkg="/data/scripts/clean_old_pkg.sh"#定义是否重启数组,用于判断是否重启
restart_arr=("true" "false")#Shell Env
SHELL_NAME="deploy.sh"
SHELL_DIR="/data/scripts/"#如果第一个参数传递的是list,那么列出这个目录所有文件
#pre check
if [ "${TAR_NAME}" == "list" ];thenecho "hehe"echo "${TAR_NAME}"ls -alh ${PKG_ROOT}/exit
fi#获取包名,比如dawnweb-2018-1226-v3.tgz经过下面处理得到dawnweb
PKG_NAME=`echo ${TAR_NAME} | awk -F '[-]'  '{print $1 }'`#定义锁,shell lock,一种项目包一个锁,方便多个不同项目包并行执行
LOCK_FILE="/tmp/deploy_${PKG_NAME}.lock"
#定义日志,shell log,一种项目包一个执行日志
SHELL_LOG="/var/log/deploy_${PKG_NAME}.log"   #调用清除脚本,清除老版本项目包
clean_old_pkg_version(){/bin/bash "${clean_old_pkg}"
}#脚本使用方式,这里没用到,预留着
usage(){echo  $"Usage: $0 { tar_version  restart_flag }"
}#写日志
writelog(){LOGINFO=$1echo  `date "+%Y-%m-%d"` `date "+%H-%M-%S"`  " : ${SHELL_NAME} : ${LOGINFO}" >> ${SHELL_LOG}
}#加锁,这里用不到
shell_lock(){touch ${LOCK_FILE}
}#解锁,这里用不到
shell_unlock(){rm -f ${LOCK_FILE}
}#定义重启对应tomcat的方法
restart_script_1(){echo "running restart_tomcat_script_1"writelog "running restart_tomcat_script_1"/bin/bash ${restart_tomcat_1}echo "restart_tomcat_script_1 done ok"writelog  "restart_tomcat_script_1 done ok"
}restart_script_2(){echo "running restart_tomcat_script_2"writelog   "running restart_tomcat_script_2"/bin/bash ${restart_tomcat_2}echo "restart_tomcat_script_2 done ok"writelog  "restart_tomcat_script_2 done ok"
}#判断重启标志位是否为空以及是否在数组中,如果不在就退出
restart_flag_check(){
#判断变量是否为空,如果为空就退出if [ -z "${RESTART_FLAG}" -o -z "${TAR_NAME}"  ]; then echo "restart_flag is empty"writelog  "restart_flag is empty"exit 110 fiexist_flag=truefor i in ${restart_arr[@]}do[ "$i" == "${RESTART_FLAG}" ] && exist_flag=falsedoneif  ${exist_flag} ;thenecho "restart_flag not right"writelog "restart_flag not right"exit 111fi
}#判断项目包的变量是否在数组中,如果不在就退出
pkg_flag_check(){exist_flag=truefor i in ${pkg_arr[@]}do[ "$i" == "${PKG_NAME}" ] && exist_flag=falsedoneif  ${exist_flag} ;thenecho "pkg not in array"writelog "pkg not in array"exit 112fi
}#判断TAR包文件是否存在,如果不存在就退出
tar_check(){echo "running tar check"if [ ! -f "${PKG_ROOT}"/${TAR_NAME}.tgz -a ! -d "${PKG_ROOT}"/${TAR_NAME} ];thenecho "${PKG_ROOT}/${TAR_NAME}.tgz   and ${PKG_ROOT}/${TAR_NAME} not exist!"writelog  "${PKG_ROOT}/${TAR_NAME}.tgz   and ${PKG_ROOT}/${TAR_NAME}  not exist!"exit 113
fi
}#判断项目包是在哪个webroot下面方法
#如果数组2长度大于等于1,说明数组2存在,也就是第二个tomcat存在,需要判断项目包是否在数组2中,这里就不考虑是否有数组3了pkg_owner_check(){pkg_arr_2_length=${#pkg_arr_2[@]}pkg_owner="tomcat_1"  if [ "${pkg_arr_2_length}" -ge 1 ];then       #获取数组长度#判断是否在组2里for i in ${pkg_arr_2[@]}do[ "$i" == "${PKG_NAME}" ] && pkg_owner="tomcat_2"donefiecho "pkg owner is:"$pkg_owner writelog  "pkg owner is:"$pkg_owner
}#执行部署tar包,先解压,然后删除对应路径下软链接,创建新的软链接以及授权
deploy_tar(){WEB_ROOT=$1echo "running deploy_tar"writelog "running deploy_tar"cd ${PKG_ROOT}/ echo "cd success"pwdif [ ! -d "${TAR_NAME}" ]; thencd ${PKG_ROOT}/ && tar xfz ${TAR_NAME}.tgz && chown -R www.www * && rm -f ${TAR_NAME}.tgzcd ${WEB_ROOT}/ && rm -rf ${PKG_NAME} && ln -s ${PKG_ROOT}/${TAR_NAME} ${WEB_ROOT}/${PKG_NAME} && chown -R www.www *writelog "finished deploy_tar"elsecd ${WEB_ROOT}/ && rm -rf ${PKG_NAME} && ln -s ${PKG_ROOT}/${TAR_NAME} ${WEB_ROOT}/${PKG_NAME} && chown -R www.www *writelog "finished deploy_tar"fi
}#部署完毕测试,这里没用到
url_test(){URL=$1curl -s --head $URL | grep "200 OK"if [ $? -ne 0 ];thenshell_unlock;echo "test error" && exit;fi
}#定义main函数开始---------------------#main(){#运行监测clean_old_pkg_versionrestart_flag_checkpkg_flag_checktar_checkpkg_owner_check#判断包在哪个tomcat,以及重启的flag是否是true,执行对应的动作
if [ "${pkg_owner}" = "tomcat_1" -a "${RESTART_FLAG}" = true ];thenshell_lock;writelog "deploy tomcat_1 and restart tomcat_1"echo "deploy tomcat_1 and restart tomcat_1"deploy_tar ${WEB_ROOT_1}restart_script_1 shell_unlock;
elif [ "${pkg_owner}" = "tomcat_1" -a "${RESTART_FLAG}" = false ];thenshell_lock;echo "deploy tomcat_1 and not restart tomcat_1"writelog  "deploy tomcat_1 and not restart tomcat_1"deploy_tar ${WEB_ROOT_1}shell_unlock;
elif [ "${pkg_owner}" = "tomcat_2" -a "${RESTART_FLAG}" = true ];thenshell_lock;echo "deploy tomcat_2 and restart tomcat_2"writelog "deploy tomcat_2 and restart tomcat_2"deploy_tar ${WEB_ROOT_2}restart_script_2shell_unlock;
elif [ "${pkg_owner}" = "tomcat_2" -a "${RESTART_FLAG}" = false ];thenshell_lock;echo "deploy tomcat_2 and not restart tomcat_2"writelog  "deploy tomcat_2 and not restart tomcat_2"deploy_tar ${WEB_ROOT_2}shell_unlock;
elseusageecho "unknown error"writelog "unknown error"exit 1000
fi}#定义main函数结束---------------------##执行main函数
main[root@router /data/scripts]#

  

脚本单独执行测试

传递list参数列出所有包
传递2个参数执行部署,第一个参数是包的名,第二个参数是是否重启的true或者false

[root@router /data/scripts]# /data/scripts/deploy.sh list
hehe
list
total 4.0K
drwxr-xr-x 15 root root 4.0K Jan 10 02:02 .
drwxr-xr-x  8 root root   86 Jan 10 02:01 ..
drwxr-xr-x  7 www  www   212 Dec 26 14:23 dawnres-2018_1226_142344-v1226.2
drwxr-xr-x  7 www  www   212 Dec 26 14:25 dawnres-2018_1226_142516-origin_master
drwxr-xr-x  7 www  www   212 Dec 26 14:26 dawnres-2018_1226_142629-v1226.2
drwxr-xr-x  7 www  www   212 Dec 26 14:28 dawnres-2018_1226_142827-v1226.2
drwxr-xr-x  7 www  www   212 Dec 26 14:29 dawnres-2018_1226_142912-origin_master
drwxr-xr-x  7 www  www   212 Dec 28 15:33 dawnres-2018_1228_153309-origin_master
drwxr-xr-x  7 www  www   212 Dec 28 15:35 dawnres-2018_1228_153517-origin_master
drwxr-xr-x  7 www  www   212 Dec 26 13:46 dawnweb-2018_1226_134619-v1226.2
drwxr-xr-x  7 www  www   212 Dec 26 13:50 dawnweb-2018_1226_134953-v1226.2
drwxr-xr-x  7 www  www   212 Dec 26 13:51 dawnweb-2018_1226_135114-origin_master
drwxr-xr-x  7 www  www   212 Dec 26 13:59 dawnweb-2018_1226_135939-origin_master
drwxr-xr-x  7 www  www   212 Dec 26 14:15 dawnweb-2018_1226_141510-v1226.2
drwxr-xr-x  8 www  www   227 Dec 26 14:15 dawnweb-2018_1226_141549-origin_master
[root@router /data/scripts]# ll /data/app/tomcat8_18080/webapps/
total 0
lrwxrwxrwx 1 www www 52 Jan 10 01:57 dawnweb -> /data/pkgroot/dawnweb-2018_1226_141549-origin_master
drwxr-xr-x 2 www www 42 Dec 24 16:24 ROOT执行部署,不重启tomcat
[root@router /data/scripts]# /data/scripts/deploy.sh dawnweb-2018_1226_141510-v1226.2 false
running tar check
pkg owner is:tomcat_1
deploy tomcat_1 and not restart tomcat_1
running deploy_tar
cd success
/data/pkgroot
[root@router /data/scripts]# ll /data/app/tomcat8_18080/webapps/
total 0
lrwxrwxrwx 1 www www 46 Jan 10 02:16 dawnweb -> /data/pkgroot/dawnweb-2018_1226_141510-v1226.2
drwxr-xr-x 2 www www 42 Dec 24 16:24 ROOT
[root@router /data/scripts]#

  

jenkins页面执行

一些执行日志输出

补充部分

创建好job有时候会遇到配置完毕项目。但是看不到tag
没关系。点击开始构建之后它会默认拉取最新的origin/master代码并执行
可以在最后的是否执行最终部署点击放弃。后期再执行参数化构建就可以看到tag了

下面的红色箭头标错位置了。应该指向上面

转载于:https://www.cnblogs.com/nmap/p/10466884.html

salt+jenkins+gitlab+ecs构建公司部署平台相关推荐

  1. 解放双手 | Jenkins + gitlab + maven 自动打包部署项目

    前言 记录 Jenkins + gitlab + maven 自动打包部署后端项目详细过程! 需求背景 不会偷懒的程序员不是好码农,传统的项目部署,有时候采用本地手动打包,再通过ssh传到服务器部署运 ...

  2. gitlab 自动推送代码到gitee_Gitlab 利用 Webhook+jenkins 实现自动构建与部署

    之前部署了Gitlab的代码托管平台和Jenkins的代码发布平台.通常是开发后的代码先推到Gitlab上管理,然后在Jenkins里通过脚本构建代码发布. 这种方式每次在发版的时候,需要人工去执行j ...

  3. 怎么把项目推到gitlab上_Gitlab利用Webhook+jenkins实现自动构建与部署

    之前部署了Gitlab的代码托管平台和Jenkins的代码发布平台.通常是开发后的代码先推到Gitlab上管理,然后在Jenkins里通过脚本构建代码发布. 这种方式每次在发版的时候,需要人工去执行j ...

  4. Jenkins + gitlab webhook实现自动化部署

    1.先在Jenkins安装插件Gitlab Hook Plugin 和Build Authorization Token Root Plugin: 2.插件安装完成后在任务里添加token 3.在gi ...

  5. Gitlab+Docker构建流水线部署

    [架构] 整体的设计思路是通过gitlab的runner将版本发布到各个环境,通过Apollo配置中心来区分环境配置,做到一次构建到处运行.生产环境镜像库根据实际情况来定,有些用的AWS ECR,有些 ...

  6. 【Gitlab+Jenkins+Ansible】构建自动化部署

    说明: Gitlab.Jenkins.生产服务器.测试服务器上都需要安装Git. 一.安装Gitlab 1.主机配置 IP: 10.10.10.105OS: CentOs7.5Gitlab版本:git ...

  7. Jenkins + Gitlab 实现代码流水线部署

    DevOps DevOps 概述 DevOps(Development和Operations的组合词)是一种重视 " 软件开发人员(Dev)" 和 " IT运维技术人员( ...

  8. jenkins + gitlab 自动化构建全流程记录。

    文章目录 1.jenkins (windows 版本 Jenkins 2.346.3) 2.gitLab (linux 版本:GitLab Community Edition 15.3.5 3.可能出 ...

  9. Jenkins + GitLab + CocoaPod 的自动打包平台配置(从build到export success)

    目录 1. 安装JAVA环境 2. 安装Jenkins 3. 管理插件 4. 项目新建和设置 5. Keychains and Provisioning Profiles Management配置(重 ...

  10. 阿里云 jenkins svn maven 构建自动化部署

    第一步:下载 jdk .tomcat.jenkins.maven jdk:http://www.oracle.com/technetwork/java/javase/downloads/index.h ...

最新文章

  1. UIbutton 圆角和边线
  2. 《游戏设计师修炼之道:数据驱动的游戏设计》一1.4小结
  3. 工作流实战_19_flowable 任务委派
  4. 带着问题了解Openstack Neutron安全组
  5. 新Azure 服务仪表盘!
  6. 用户的大量数据保存在计算机的,大量计算机用户遭到恶意木马程序威胁
  7. Apache Tomcat部署多个项目
  8. 大数据技术主要应用在哪些行业
  9. 树莓派4B Ubuntu20.04 ROS2 DSO realsense d455
  10. java的int和Integer的区别
  11. SpringBoot配置多数据源(动态切换)
  12. Storm 的一个案例
  13. 《linux内核分析》第三次课 实验作业
  14. 微信小程序实现替换logo功能
  15. 【Camera】手机相机自动对焦的3种方式及原理
  16. 从数据结构及汇编角度深入学习go语言
  17. 中国鼠标行业销售动态及营销形势分析报告(新版)2022-2027年
  18. 相干解调与非相干解调
  19. 解决普通笔记本无法连接iPhone热点的问题
  20. 安信可ESP8266模块实现对接天猫精灵IOT平台控制单路插座的教程

热门文章

  1. 安卓软件开发面试题!五年Android开发者小米、阿里面经,小白也能看明白
  2. sqlmap注入之tamper绕过WAF防火墙过滤
  3. c语言注释中文,Comments(注释符)
  4. 教你快速记住公司工作邮箱格式,再也不用百度“邮箱格式怎么写”啦!
  5. 第二章 SPSS 的数据管理
  6. 十二进制转二进制--2018
  7. 基于spring cloud + nacos + gateway + ssm+的学生管理系统
  8. App在appStore上搜索不到的解决方案
  9. java的create vm_JNI_CreateJavaVM(Runtime::Create())
  10. [深度学习概念]·深度学习的人脸识别技术发展综述