Jenkins 微服务打包再优化


共计 6977 个字符,预计需要花费 18 分钟才能阅读完成。

之前也写过 jenkins 微服务打包的教程,可以打包单个模块,但是如果需要一次性打包全部就实现不了了,这次优化了一下脚本。

如果有不了解的,可以先看看这两篇文章 Jenkins 打包微服务教程-一个配置文件即可打包所有模块Jenkins 打包微服务流程优化

不过这次需要用到 Extended Choice Parameter 插件,因为需要在构建时传参,但是 jenkins 默认不支持传多选,需要通过这个插件。

插件的使用也比较简单,在添加参数时选择 Extended Choice Parameter。

Jenkins 微服务打包再优化

/>

然后按如下图填写即可。

Jenkins 微服务打包再优化

/>

接下来就可以按住 ctrl 键配合鼠标进行多选了,也可以按住 shift 选择一个区间。

接下来就是配置源码地址,maven 的打包可以不需要,如果实在需要可以设置命令为 mvn dependency:tree,因为接下来会在脚本进行打包。

脚本如下,注意这里需要配置三个参数,分别是 all_module-候选打包模块,all_host-候选打包主机,branch-git分支,这个分支变量需要配置为 git 变量,其他两个使用上面的插件配置。

#!/bin/bash

# 0. 准备 1. 指定打包mvn路径 2. 获取打包的所有模块 3. 获取打包的所有主机
maven_command="/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/maven3.6/apache-maven-3.6.1/bin/mvn"
IFS=',' read -ra modules <<< "$all_module"
IFS=',' read -ra hosts <<< "$all_host"

echo "===============本次选择打包的模块 "$all_module"==============="
# 1. 打包
skip_tests="-Dmaven.test.skip=true"
for module in "${modules[@]}"
do
     echo "===============模块 "$module" 执行 mvn install==============="
     $maven_command clean install -pl ${module} -am $skip_tests
done

# 2. 构建镜像并保存
for module in "${modules[@]}"
do
    ## 构建镜像
    cd "${WORKSPACE}/${module}"
    serviceName="${module#*/}"
    current=$(date -d "8 hours" +"%Y%m%d-%H%M")
    branch_name=$(echo "${branch}" | sed 's/\//-/g')
    #imageName="${serviceName}-${branch_name}:${current}"
    imageName="${serviceName}:${branch_name}-${current}"
    tarName="${serviceName}-${current}.tar"
    jarFile=$(ls target/ | grep \.jar$)
    mv "target/${jarFile}" .
    docker build --build-arg JAR_FILE="${jarFile}" -t "${imageName}" .

    ## 保存镜像-保存在 jenkins 主目录下的 images 文件夹
    imagesDir="${JENKINS_HOME}/images/$JOB_NAME/${serviceName}"
    mkdir -p "${imagesDir}"
    docker save -o "${imagesDir}/${tarName}" "${imageName}"
    cp "${imagesDir}/${tarName}" target/

    ## 清理镜像
    docker rmi -f $(docker images | grep "${serviceName}" | awk 'NR>0 {print $3}')
    ## tar包保留指定数量
    cd "${imagesDir}"
    retainNumber=3
    rm -f $(ls -t | awk "NR>${retainNumber}")
done

# 3. 部署
# 准备工作 -> 1. 定义主机 2.获取工作目录 3. 连接新主机不询问是否添加到known_hosts
cd ${WORKSPACE}
cat > hosts.txt <<EOF
172.26.1.21 root xxx dev_test "-e ACTIVE=pro -e NACOS_URL=172.26.1.21"
EOF
grep -q 'StrictHostKeyChecking no' /etc/ssh/ssh_config || echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config

#==========定义远程执行脚本文件开始==========
cd ${WORKSPACE}
cat << 'EOF' > script.sh
#!/bin/bash
cd /tmp/robot-patrol-platform
tarName=$(ls *.tar -1t | head -n 1)
imageName=$(docker load -i ${tarName} |  cut -d' ' -f3)
containerName=$(echo ${imageName} | cut -d: -f1)
# 删除原来的容器,并新建一个容器
if docker ps -a| grep "${containerName}" >/dev/null 2>&1; then docker rm -f ${containerName} ; fi
docker run -d --net host $1 --restart=unless-stopped --name ${containerName} ${imageName}
# 删除无用的镜像,只保留最新的镜像
serviceName=${containerName}
if docker images | grep "${serviceName}" >/dev/null 2>&1; then docker rmi -f $(docker images | grep ${serviceName} |awk 'NR>1 {print $3}'); fi
# 删除临时文件夹
rm -rf /tmp/robot-patrol-platform/${tarName}
rm -rf /tmp/robot-patrol-platform/script.sh
echo "The script has been executed successfully."
EOF
#==========定义远程执行脚本文件结束==========

#==========定义任务函数开始==========
dotask () {
    echo "===============远程主机 "$ip" 开始执行任务==============="
    for module in "${modules[@]}"
    do 
      echo "===============远程主机 "$ip" 正在部署 "$module" ==============="
      ip=$1; username=$2; password=$3; environment=$4; param=$5
      sshpass -p $password ssh $username@$ip "mkdir -p /tmp/robot-patrol-platform"
      sshpass -p $password scp ${WORKSPACE}/${module}/target/*.tar $username@$ip:/tmp/robot-patrol-platform
      sshpass -p $password scp ${WORKSPACE}/script.sh $username@$ip:/tmp/robot-patrol-platform
      sshpass -p $password ssh $username@$ip "chmod +x /tmp/robot-patrol-platform/script.sh && /tmp/robot-patrol-platform/script.sh $param"
   done
   echo "===============远程主机 "$ip" 脚本执行完成==============="
}
#==========定义任务函数结束==========

while read -r ip username password environment param; do
  for host in "${hosts[@]}"; do
    if [ "$host" = "$environment" ] || [ "$host" = "$ip" ]; then
      dotask "$ip" "$username" "$password" "$environment" "$param"
    fi
  done
done < hosts.txt
echo "===============所有任务已完成==============="

当然,这样的方式有个弊端,就是 idea 插件并不支持多选参数,

还有一种方式,需要配置 single_module、host 都为单选,并且提供 all 这个选项,意思是打包全部模块或发送到全部主机。然后配置一个 all_module 字符变量,这个变量是模块以逗号分隔,另外一个就是分支变量了。

脚本如下:

#!/bin/bash
modules=${single_module}
# 如果选择该项目,则全部进行打包
maven_command="/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/maven3.6/apache-maven-3.6.1/bin/mvn"
skip_tests="-Dmaven.test.skip=true"
if [ ${single_module} == "all" ]; then
     IFS=',' read -ra modules <<< "$all_module"
     echo "===============全部模块执行 mvn install==============="
     $maven_command clean install $skip_tests
else
     echo "===============${single_module}模块执行 mvn install==============="
     $maven_command clean install -pl ${single_module} -am $skip_tests
fi
for module in "${modules[@]}"
do
    echo $module
    ## 构建镜像
    cd "${WORKSPACE}/${module}"
    serviceName="${module#*/}"
    current=$(date -d "8 hours" +"%Y%m%d-%H%M")
    branch_name=$(echo "${branch}" | sed 's/\//-/g')
    #imageName="${serviceName}-${branch_name}:${current}"
    imageName="${serviceName}:${branch_name}-${current}"
    tarName="${serviceName}-${current}.tar"
    jarFile=$(ls target/ | grep \.jar$)
    mv "target/${jarFile}" .
    docker build --build-arg JAR_FILE="${jarFile}" -t "${imageName}" .

    ## 保存镜像-保存在 jenkins 主目录下的 images 文件夹
    imagesDir="${JENKINS_HOME}/images/$JOB_NAME/${serviceName}"
    mkdir -p "${imagesDir}"
    docker save -o "${imagesDir}/${tarName}" "${imageName}"
    cp "${imagesDir}/${tarName}" target/

    ## 清理镜像
    docker rmi -f $(docker images | grep "${serviceName}" | awk 'NR>0 {print $3}')
    ## tar包保留指定数量
    cd "${imagesDir}"
    retainNumber=3
    rm -f $(ls -t | awk "NR>${retainNumber}")
done

# 准备工作 -> 1. 定义主机 2.获取工作目录 3. 连接新主机不询问是否添加到known_hosts
cd ${WORKSPACE}
cat > hosts.txt <<EOF
172.26.1.21 root xxx dev_test "-e ACTIVE=pro -e NACOS_URL=172.26.1.21"
EOF
grep -q 'StrictHostKeyChecking no' /etc/ssh/ssh_config || echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config

#==========定义远程执行脚本文件开始==========
cd ${WORKSPACE}
cat << 'EOF' > script.sh
#!/bin/bash
cd /tmp/robot-patrol-platform
tarName=$(ls *.tar -1t | head -n 1)
imageName=$(docker load -i ${tarName} |  cut -d' ' -f3)
containerName=$(echo ${imageName} | cut -d: -f1)
# 删除原来的容器,并新建一个容器
if docker ps -a| grep "${containerName}" >/dev/null 2>&1; then docker rm -f ${containerName} ; fi
docker run -d --net host $1 --restart=unless-stopped --name ${containerName} ${imageName}
# 删除无用的镜像,只保留最新的镜像
serviceName=${containerName}
if docker images | grep "${serviceName}" >/dev/null 2>&1; then docker rmi -f $(docker images | grep ${serviceName} |awk 'NR>1 {print $3}'); fi
# 删除临时文件夹
rm -rf /tmp/robot-patrol-platform/${tarName}
rm -rf /tmp/robot-patrol-platform/script.sh
echo "The script has been executed successfully."
EOF
#==========定义远程执行脚本文件结束==========

#==========定义任务函数开始==========
dotask () {
      echo "===============远程主机 "$ip" 开始执行任务==============="
    for module in "${modules[@]}"
    do 
      echo "===============远程主机 "$ip" 正在部署 "$module" ==============="
      ip=$1; username=$2; password=$3; environment=$4; param=$5
      sshpass -p $password ssh $username@$ip "mkdir -p /tmp/robot-patrol-platform"
      sshpass -p $password scp ${WORKSPACE}/${module}/target/*.tar $username@$ip:/tmp/robot-patrol-platform
      sshpass -p $password scp ${WORKSPACE}/script.sh $username@$ip:/tmp/robot-patrol-platform
      sshpass -p $password ssh $username@$ip "chmod +x /tmp/robot-patrol-platform/script.sh && /tmp/robot-patrol-platform/script.sh $param"
   done
   echo "===============远程主机 "$ip" 脚本执行完成==============="
}
#==========定义任务函数结束==========

while read -r ip username password environment param; do
  if [ "$host" = "all" ]; then
    dotask $ip $username $password $environment "$param"
  elif [ "$host" = "$environment" ]; then
    dotask $ip $username $password $environment "$param"
  fi
done < hosts.txt
echo "===============所有任务已完成==============="

提醒:本文发布于399天前,文中所关联的信息可能已发生改变,请知悉!

Tips:清朝云网络工作室

阅读剩余
THE END