salt+jenkins+gitlab+ecs构建公司部署平台
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构建公司部署平台相关推荐
- 解放双手 | Jenkins + gitlab + maven 自动打包部署项目
前言 记录 Jenkins + gitlab + maven 自动打包部署后端项目详细过程! 需求背景 不会偷懒的程序员不是好码农,传统的项目部署,有时候采用本地手动打包,再通过ssh传到服务器部署运 ...
- gitlab 自动推送代码到gitee_Gitlab 利用 Webhook+jenkins 实现自动构建与部署
之前部署了Gitlab的代码托管平台和Jenkins的代码发布平台.通常是开发后的代码先推到Gitlab上管理,然后在Jenkins里通过脚本构建代码发布. 这种方式每次在发版的时候,需要人工去执行j ...
- 怎么把项目推到gitlab上_Gitlab利用Webhook+jenkins实现自动构建与部署
之前部署了Gitlab的代码托管平台和Jenkins的代码发布平台.通常是开发后的代码先推到Gitlab上管理,然后在Jenkins里通过脚本构建代码发布. 这种方式每次在发版的时候,需要人工去执行j ...
- Jenkins + gitlab webhook实现自动化部署
1.先在Jenkins安装插件Gitlab Hook Plugin 和Build Authorization Token Root Plugin: 2.插件安装完成后在任务里添加token 3.在gi ...
- Gitlab+Docker构建流水线部署
[架构] 整体的设计思路是通过gitlab的runner将版本发布到各个环境,通过Apollo配置中心来区分环境配置,做到一次构建到处运行.生产环境镜像库根据实际情况来定,有些用的AWS ECR,有些 ...
- 【Gitlab+Jenkins+Ansible】构建自动化部署
说明: Gitlab.Jenkins.生产服务器.测试服务器上都需要安装Git. 一.安装Gitlab 1.主机配置 IP: 10.10.10.105OS: CentOs7.5Gitlab版本:git ...
- Jenkins + Gitlab 实现代码流水线部署
DevOps DevOps 概述 DevOps(Development和Operations的组合词)是一种重视 " 软件开发人员(Dev)" 和 " IT运维技术人员( ...
- jenkins + gitlab 自动化构建全流程记录。
文章目录 1.jenkins (windows 版本 Jenkins 2.346.3) 2.gitLab (linux 版本:GitLab Community Edition 15.3.5 3.可能出 ...
- Jenkins + GitLab + CocoaPod 的自动打包平台配置(从build到export success)
目录 1. 安装JAVA环境 2. 安装Jenkins 3. 管理插件 4. 项目新建和设置 5. Keychains and Provisioning Profiles Management配置(重 ...
- 阿里云 jenkins svn maven 构建自动化部署
第一步:下载 jdk .tomcat.jenkins.maven jdk:http://www.oracle.com/technetwork/java/javase/downloads/index.h ...
最新文章
- UIbutton 圆角和边线
- 《游戏设计师修炼之道:数据驱动的游戏设计》一1.4小结
- 工作流实战_19_flowable 任务委派
- 带着问题了解Openstack Neutron安全组
- 新Azure 服务仪表盘!
- 用户的大量数据保存在计算机的,大量计算机用户遭到恶意木马程序威胁
- Apache Tomcat部署多个项目
- 大数据技术主要应用在哪些行业
- 树莓派4B Ubuntu20.04 ROS2 DSO realsense d455
- java的int和Integer的区别
- SpringBoot配置多数据源(动态切换)
- Storm 的一个案例
- 《linux内核分析》第三次课 实验作业
- 微信小程序实现替换logo功能
- 【Camera】手机相机自动对焦的3种方式及原理
- 从数据结构及汇编角度深入学习go语言
- 中国鼠标行业销售动态及营销形势分析报告(新版)2022-2027年
- 相干解调与非相干解调
- 解决普通笔记本无法连接iPhone热点的问题
- 安信可ESP8266模块实现对接天猫精灵IOT平台控制单路插座的教程
热门文章
- 安卓软件开发面试题!五年Android开发者小米、阿里面经,小白也能看明白
- sqlmap注入之tamper绕过WAF防火墙过滤
- c语言注释中文,Comments(注释符)
- 教你快速记住公司工作邮箱格式,再也不用百度“邮箱格式怎么写”啦!
- 第二章 SPSS 的数据管理
- 十二进制转二进制--2018
- 基于spring cloud + nacos + gateway + ssm+的学生管理系统
- App在appStore上搜索不到的解决方案
- java的create vm_JNI_CreateJavaVM(Runtime::Create())
- [深度学习概念]·深度学习的人脸识别技术发展综述