生产项目容器化改造(二)使用Jenkins任务部署Maven项目

构建jre1.8 tomcat8 基础镜像:

  • 登陆harbor主机,构建tomcat基础镜像,并上传到harbor
cd /tmp
wget --no-check-certificate https://wget.XXXXXXX.com:10194/jre/server-jre-8u241-linux-x64.tar.gz
wget --no-check-certificate https://wget.XXXXXXX.com:10194/tomcat/apache-tomcat-8.5.51.tar.gz
vi Dockerfile
FROM centos:6
LABEL description="jdk1.8 and tomcat8"
# 时区调整
RUN /bin/cp -av /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 适应中文
ENV LC_ALL en_US.UTF-8
# 安装unzip包和git包
RUN sed -i 's/gpgcheck=1/gpgcheck=0/g' /etc/yum.repos.d/*.repo && \
  yum -y install unzip git
# 部署jdk1.8
ENV JDK_TAR   server-jre-8u241-linux-x64.tar.gz
ENV JDK_FILE  jdk1.8.0_241
ENV JAVA_HOME /usr/local/java/java_1.8
ENV CLASSPATH ${JAVA_HOME}/lib:${JAVA_HOME}/jre/lib
ENV PATH      ${JAVA_HOME}/bin:${JAVA_HOME}/jre/bin:${PATH}
WORKDIR /usr/local/java
ADD ${JDK_TAR} .
RUN ln -s ${JDK_FILE} java_1.8 && \
    chown root: -R .
# 部署tomcat8
ENV TOM_TAR apache-tomcat-8.5.51.tar.gz
ENV TOM_FILE apache-tomcat-8.5.51
WORKDIR /usr/local/tomcat
ADD ${TOM_TAR} .
RUN ln -s ${TOM_FILE} tomcat8 && \
    chown root: -R .
# tomcat8 简单优化调整
ENV OPTS "-Djava.security.egd=file:/dev/./urandom -Xms1256m -Xmx1512m"
ENV OPTS=${OPTS}" -XX:PermSize=50m -XX:MaxPermSize=70m"
ENV OPTS=${OPTS}" -XX:-UseGCOverheadLimit"
ENV OPTS2=${OPTS}" -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp"
RUN sed -i "s|cygwin=false|JAVA_OPTS=\"${OPTS}\"\n&|g" tomcat8/bin/catalina.sh && \
    sed -i "s|cygwin=false|# JAVA_OPTS=\"${OPTS2}\"\n&|g" tomcat8/bin/catalina.sh && \
    sed -i 's/Connector port="8080" protocol="HTTP\/1.1"/&\n \
               maxThreads="800" acceptCount="1000"\n \
               compression="on"\n \
               compressionMinSize="2048"\n \
               noCompressionUserAgents="gozilla,traviata"\n \
               compressableMimeType="text\/html,text\/xml,text\/javascript,text\/css,text\/plain"/g' tomcat8/conf/server.xml && \
    sed -i 's|${catalina.base}/logs|/web/logs|g' tomcat8/conf/logging.properties && \
    sed -i 's|appBase="webapps"|appBase="/web/project"|g' tomcat8/conf/server.xml && \
    sed -i 's|directory="logs"|directory="/web/logs/access"|g' tomcat8/conf/server.xml && \
    mkdir -pv /web/{profile,project/ROOT} && \
    echo "$(hostname) $(date +%F_%T)">/web/project/ROOT/index.html
EXPOSE 8080
CMD tomcat8/bin/catalina.sh run &> /web/logs/catalina.out

docker build -t harbor.vincent.com/library/tomcat8-j8 .
docker push harbor.vincent.com/library/tomcat8-j8

部署Jenkins模版任务,复制模版部署测试:

  • 网页登陆jenkins,创建一个模版任务deploy-templete,类型为pipeline, 丢弃旧构建选择保留2个,添加groovy脚本如下:
#!groovy
pipeline{
  agent any
  environment{
    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
    GitLab="gitlab"
    GitLabCredentialsId="gitlabcredentialsid"
    GitNS="gitns"
    GitName="gitname"
    GitSubPro="gitsubpro"
    GitSubProPort="gitsubproport"
    IPs="ips"
    Nginx="nginx"
    Harbor="harbor"
    LbNginx="lbnginx"
    LbNginxConf='lbnginxconf'
  }
  parameters{
    choice(
      name: 'Option',
      choices: 'Update\nRepublish\nRollback',
      description: '功能选择,升级发布、项目再发布,回滚发布'
    )
    choice(
      name: 'Range',
      choices: 'Canary\nExcept\nALL\nips',
      description: '发布范围:单机发布,剩余主机发布,全量发布,单机发布'
    )
    choice(
      name: 'Interval',
      choices: '15\n30\n60\n120',
      description: '多机发布时的发布间隔,单位秒'
    )
    /* 参数使用情形举例:
    // ------- 金丝雀升级发布,测试后,再发布到剩余主机
    // Option=Update,Range=Canary,金丝雀升级发布,默认发布到第一个IP
    // Option=Republish,Range=Except,项目再发布到第一个IP之外的其他主机
    // ------- 全量升级发布,不进行测试,直接发布到全局主机
    // Option=Update,Range=ALL
    // ------- 指定IP升级发布,测试,再发布到剩余主机
    // Option=Update,Range=IP2,当指定的IP是第一个时,既是金丝雀发布
    // Option=Republish,Range=IP3/IP4...,指定IP的再发布
    // ------- 指定IP再发布,当某个主机的项目包损坏时或者新添加了主机时
    // Option=Republish,Range=IP5
    // ------- 全量回滚
    // Option=Rollback,Range=ALL
    // ------- 金丝雀回滚发布,测试后,剩余主机回滚
    // Option=Rollback,Range=Canary
    // Option=Rollback,Range=Except
    // ------- 指定IP回滚
    // Option=Rollback,Range=IP2...
    // ------- 当Range=Except/ALL时,Interval 参数生效
    */
  }
  stages{
    stage("GitClone"){
      when { environment name: "Option", value: "Update"}
      steps{
        // 代码下载
        sh 'git config --global http.sslVerify false'
        dir("${env.WORKSPACE}"){
          git branch: 'develop',
          // git branch: 'master',
          credentialsId: "${GitLabCredentialsId}",
          url:"${GitLab}/${GitNS}/${GitName}.git"
        }
      }
    }
    stage("ProjectBuild"){
      when { environment name: "Option", value: "Update"}
      steps{
        // 项目构建
        dir("${env.WORKSPACE}"){
          sh "source /etc/profile && mvn -Dmaven.test.skip=true clean package"
        }
      }
    }
    stage("ImageBuild"){
      when { environment name: "Option", value: "Update"}
      steps{
        // 项目包上传包共享服务器,构建镜像并存入harbor镜像共享服务器
        sh "bash ${JENKINS_HOME}/script/warMoveAndClear.sh ${WORKSPACE} ${GitSubPro} ${Nginx} ${Harbor}"
      }
    }
    stage("PublishProject"){
      steps{
        sh "bash ${JENKINS_HOME}/script/mutiPublish.sh ${Option} ${env.Range} '${IPs}' ${Interval} ${GitSubPro} ${GitSubProPort} ${Harbor} ${LbNginx} ${LbNginxConf}"
        
      }
    }
  }
}

  • 在jenkins主机上部署任务所调用的脚本
su - deploy
mkdir -pv /var/lib/jenkins/script && cd /var/lib/jenkins/script
vi warMoveAndClear.sh
#!/bin/bash
source ~/.bash_profile
warPath=${1}
warProName=${2}
imageName=$(echo ${warProName}| tr '[A-Z]' '[a-z]')
Release=$(date +%Y%m%d.%H%M%S)
WarFile=${warProName}-${Release}.war
nginxRootPath=/usr/share/nginx/html
Nginx=${3}
Harbor=${4}
# 创建nginx相应目录并存储当前构建的war包
mkdir -p ${nginxRootPath}/${warProName}
cd ${warPath}/${warProName}/target/
find . -name "*.war" -type f -exec cp -a {} ${nginxRootPath}/${warProName}/${WarFile} \;
# 对历史war包进行清理,保留3个war包
WarFileNumber=$(ls ${nginxRootPath}/${warProName}/*.war|wc -l)
if [ "${WarFileNumber}" -ge 3 ]
then
  StandFile=$(ls -t ${nginxRootPath}/${warProName}/*.war|head -3|tail -1)
  find ${nginxRootPath}/${warProName}/ -type f -name "*.war" -not -newer ${StandFile} -exec rm -f {} \;
fi
echo "[+] ############## $(date +%F_%T) 项目包${WarFile}存储到nginx完成"
# 操纵harbor,构建镜像并上传
ssh root@${Harbor} "rm -rf /opt/${warProName} && mkdir -p /opt/${warProName}"
cat >/tmp/Dockerfile-${warProName}-${Release}<<EOF
FROM harbor.vincent.com/library/tomcat8-j8
WORKDIR /web/profile
ADD ${warProName}.tar.gz .
# git clone ...
WORKDIR /web/project
RUN rm -rf *
COPY ${WarFile} ROOT.war
EXPOSE 8080
CMD /usr/local/tomcat/tomcat8/bin/catalina.sh run &> /web/logs/catalina.out
EOF
echo "[+] ############## $(date +%F_%T) 同步Dockerfile到harbor"
scp /tmp/Dockerfile-${warProName}-${Release} root@${Harbor}:/opt/${warProName}/Dockerfile
rm -rf /tmp/Dockerfile-${warProName}-${Release}
echo "[+] ############## $(date +%F_%T) 下载profile"
ssh root@${Harbor} "cd /opt/${warProName} && wget ${Nginx}/profile/${warProName}.tar.gz -o /dev/null"
echo "[+] ############## $(date +%F_%T) 下载war包"
ssh root@${Harbor} "cd /opt/${warProName} && wget ${Nginx}/${warProName}/${WarFile} -o /dev/null"
echo "[+] ############## $(date +%F_%T) 构建镜像"
ssh root@${Harbor} "cd /opt/${warProName} && docker build -t harbor.vincent.com/library/${imageName}:${Release} ."
echo "[+] ############## $(date +%F_%T) 镜像上传到harbor"
ssh root@${Harbor} "docker push harbor.vincent.com/library/${imageName}:${Release}"
echo "[+] ############## $(date +%F_%T) 本地镜像清除"
ssh root@${Harbor} "docker rmi harbor.vincent.com/library/${imageName}:${Release}"
echo "[+] ############## $(date +%F_%T) 镜像 harbor.vincent.com/library/${imageName}:${Release}存储到harbor完成"
vi mutiPublish.sh
#!/bin/bash
source ~/.bash_profile
Option=${1}
Range=${2}
IPs=${3}
Interval=${4}
GitSubPro=${5}
imageName=$(echo ${GitSubPro}| tr '[A-Z]' '[a-z]')
GitSubProPort=${6}
Harbor=${7}
LbNginx=${8}
LbNginxConf=${9}
ImagePath="harbor.vincent.com/library"
# 获取项目的镜像tag列表
TagInfo=$(curl -s -k -X GET "https://${Harbor}/api/repositories/library%2F${imageName}/tags" \
  -H "accept: application/json" -H "X-Xsrftoken: GUXirgNTqmudkEPhJtOtl520yTRJz6RW" \
   | jq '.[].name'|sed 's/"//g')
Tag0=$(echo ${TagInfo}|awk '{print $(NF-0)}')
Tag1=$(echo ${TagInfo}|awk '{print $(NF-1)}')
Tag2=$(echo ${TagInfo}|awk '{print $(NF-2)}')
# 发布类型判断
case ${Option} in
  "Update")
    Image=${imageName}:${Tag0}
    ;;
  "Republish")
    Image=${imageName}:${Tag0}
    ;;
  "Rollback")
    Image=${imageName}:${Tag1}
    ;;
esac
# 发布范围判断
case ${Range} in
  "Canary")
    ip=$(echo ${IPs}|awk '{print $1}')
    ;;
  "Except")
    ip=$(echo ${IPs}|awk '{for(i=2;i<=NF;i++) printf("%s ",$i)}')
    ;;
  "ALL")
    ip=${IPs}
    ;;
  *)
    ip=${Range}
    ;;
esac
# 最终发布
echo "[+] ############## $(date +%F_%T) ${Option}发布,使用镜像:${ImagePath}/${Image},发布IP为:${ip}"
for i in ${ip}
do
  ssh root@${i} "echo -ne \"[+] ############## $(date +%F_%T) ${i} 发布开始 \n\""
  # 需要配置deploy到LbNginx的root用户的免密登陆
  # ssh root@${LbNginx} "sed -i 's/${i}:${GitSubProPort}/# ${i}:${GitSubProPort}/g' ${LbNginxConf}"
  # ssh root@${LbNginx} "systemctl reload nginx"
  # echo "[+] ############## $(date +%F_%T) ${GitSubPro}-${i}-${GitSubProPort} 负载下线,${Interval}秒后部署开始"
  # curl -s 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxx' \
  #   -H "Content-Type: application/json" -d "{\"msgtype\": \"text\", \
  #        \"text\": {\"content\": \"${GitSubPro}-${i}-${GitSubProPort}:\n$(date +%F_%T) 负载下线,${Interval}秒后部署开始\"}}"
  # sleep ${Interval}
  ssh root@${i} "echo -ne \"[+] ############## $(date +%F_%T) 容器关闭 \" && docker stop ${imageName}-${i}-${GitSubProPort}"
  ssh root@${i} "echo -ne \"[+] ############## $(date +%F_%T) 容器删除 \" && docker rm ${imageName}-${i}-${GitSubProPort}"
  ssh root@${i} "echo -ne \"[+] ############## $(date +%F_%T) 镜像删除 \n\" && for i in \$(docker image ls|grep ${imageName}|awk '{print \$3}');do docker rmi \$i &>/dev/null;done"
  ssh root@${i} "echo -ne \"[+] ############## $(date +%F_%T) 镜像拉取 \n\" && docker pull ${ImagePath}/${Image} &>/dev/null"
  ssh root@${i} "echo -ne \"[+] ############## $(date +%F_%T) 容器启动 \" && docker run -d --name=${imageName}-${i}-${GitSubProPort} -p ${GitSubProPort}:8080 -v /opt/logs/${imageName}-${i}-${GitSubProPort}:/web/logs -m 1512M -it ${ImagePath}/${Image}"
  echo "[+] ############## $(date +%F_%T) ${imageName}-${i}-${GitSubProPort} ${Option}发布成功" #,${Interval}秒后负载上线"
  curl -s 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxx' \
    -H "Content-Type: application/json" -d "{\"msgtype\": \"text\", \
         \"text\": {\"content\": \"${GitSubPro}-${i}-${GitSubProPort}:\n$(date +%F_%T) ${Option}发布成功\"}}" #,${Interval}秒后负载上线\"}}"
  sleep ${Interval}
  # ssh root@${LbNginx} "sed -i 's/# ${i}:${GitSubProPort}/${i}:${GitSubProPort}/g' ${LbNginxConf}"
  # ssh root@${LbNginx} "systemctl reload nginx"
  # echo "[+] ############## $(date +%F_%T) ${GitSubPro}-${i} 负载上线"
  # curl -s 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxx' \
  #   -H "Content-Type: application/json" -d "{\"msgtype\": \"text\", \
  #        \"text\": {\"content\": \"${GitSubPro}-${i}-${GitSubProPort}:\n$(date +%F_%T) 负载上线\"}}"
done
  • 模版复制创建任务,构建发布测试
su - deploy
gitns='vincent'
gitname='test'
gitsubpro='test-soaport'
gitsubproport='8081'
ips='192.168.1.171 192.168.1.172 192.168.1.173 192.168.1.174 192.168.1.175'
ipS='192.168.1.171\\n192.168.1.172\\n192.168.1.173\\n192.168.1.174\\n192.168.1.175'
gitlab='https://gitlab.vincent.com'
gitlabcredentialsid='https.gitlab.root.pass'
nginx='http://dockerjenkins:8080'
harbor='harbor.vincent.com'
lbnginx='lbnginx'
lbnginxconf='lbnginxconf'
cd /var/lib/jenkins/jobs/
cp -av deploy-templete ${gitsubpro}
sed -i "s|GitLab=\&quot;gitlab\&quot;|GitLab=\&quot;${gitlab}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|GitLabCredentialsId=\&quot;gitlabcredentialsid\&quot;|GitLabCredentialsId=\&quot;${gitlabcredentialsid}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|GitNS=\&quot;gitns\&quot;|GitNS=\&quot;${gitns}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|GitName=\&quot;gitname\&quot;|GitName=\&quot;${gitname}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|GitSubPro=\&quot;gitsubpro\&quot;|GitSubPro=\&quot;${gitsubpro}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|GitSubProPort=\&quot;gitsubproport\&quot;|GitSubProPort=\&quot;${gitsubproport}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|IPs=\&quot;ips\&quot;|IPs=\&quot;${ips}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|Nginx=\&quot;nginx\&quot;|Nginx=\&quot;${nginx}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|Harbor=\&quot;harbor\&quot;|Harbor=\&quot;${harbor}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|LbNginx=\&quot;lbnginx\&quot;|LbNginx=\&quot;${lbnginx}\&quot;|g" ${gitsubpro}/config.xml
sed -i "s|LbNginxConf=\&apos;lbnginxconf\&apos;|LbNginxConf=\&apos;${lbnginxconf}\&apos;|g" ${gitsubpro}/config.xml
sed -i "s|ips\&apos|${ipS}\&apos|g" ${gitsubpro}/config.xml
su - root /etc/init.d/jenkins restart
  • 项目做过配置分离,需要将相应的配置目录profile打包上传到nginx对应目录:
cd /tmp
tar -czf test-soaport.tar.gz profile
mkdir -pv /usr/share/nginx/html/profile
mv -v test-soaport.tar.gz /usr/share/nginx/html/profile
  • 网页登陆Jenkins,使用任务进行构建部署测试

[TOC]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值