9

Jenkins实战应用–回滚方案的最佳实践之传统自由风格以及与ansible集成的配置 |坐而言...

 3 years ago
source link: http://www.eryajf.net/3508.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Jenkins实战应用–回滚方案的最佳实践之传统自由风格以及与ansible集成的配置 |坐而言不如起而行! 二丫讲梵
> 术业专攻 > 自动化运维 > Jenkins > <三十七>Jenkins实战应用–回滚方案的最佳实践之传统自由风格以及与ansible集成的配置
本文预计阅读时间 18 分钟

上周在Jenkins中文社区做了一次关于回滚那些事儿的分享,因为要准备这样一次分享,所以很多以前放下的事情,又都捡拾起来了,瞬间又有了不少奇思妙想出来,这种收获,是不进行这次经历无法获取的,分享常常使我更加成长,尽管分享的东西,已经是自己所熟悉的,熟悉的东西多加巩固,就会有意外收获。

曾经我一直以为,Jenkins对比所谓Gitlab的cicd,以及drone等的发布工具,可能在对发布的历史版本回滚的操作上,有天生不足(前边提到的两者都是直接基于git自身的版本控制进行发布,回滚的时候也直接基于历史版本重新发布即可),我一度以为这是Jenkins无尽美好中的唯一缺憾。

后来工作中接触到walle的部署,当我了解了walle的发布思路之后,就像忽然打开了一扇大门一样,忽然觉得Jenkins同样可以借鉴这样一个思路来进行发布的工作,于是,在工作之余,我做了五大实验:

  • 基于freestyle的定制化单机版本发布回滚配置管理
  • 基于pipeline的定制化单机版本发布回滚配置管理
  • 基于freestyle结合ansible的多主机批量发布回滚配置管理
  • 基于pipeline结合ansible的多主机批量发布回滚配置管理
  • 基于pipeline结合优化版ansible的多主机批量发布回滚配置管理

今天将针对这些方案一一解析与分享,本文将分享 基于freestyle的定制化单机版本发布回滚配置管理基于freestyle结合ansible的多主机批量发布回滚配置管理 这两种。

现在,进入正题。

1,思路整理

如果是发布PHP项目:

  1. 同步到远端的版本目录,目录使用时间 + build id命名
  2. 将新的应用版本软链到项目root目录
  3. 确保远程目录只保留五次(可自定义次数)历史

如果是回滚:

  1. 构建参数当中添加一个回滚ID,默认情况下,将回滚到上次构建
  2. 如果输入自定义ID,则回滚到对应构建
  3. 支持灵活在五次构建内回滚

这一思路的流程图大概如下:

Snipaste_2019-12-14_21-24-50.png

现在通过实际例子来实现一下上边这个思路,大概将进行四个实验,或者更多,首先是类前端项目发布,静态部署,PHP项目等都可采用这种方案。

2,自由风格单机部署回滚示例

创建一个自由风格的测试项目,核心当然是在参数化的配置,以及脚本的灵活定义,因此这里就展示这两个部分,先看参数化部分配置:

image-20191208092245866.png

定义三个参数,分别对应上边流程图中的三个节点,首先通过分支branch进行下发,接着通过mode进行部署或者回滚,如果是回滚,则再针对版本ID进行一下判断即可。

脚本内容:

  1. #!/bin/bash
  2. ##set color##
  3. echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
  4. echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
  5. echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
  6. ##set color##
  7. source /etc/profile
  8. project="admin"
  9. remote_port="22"
  10. remote_user="root"
  11. remote_ip="10.3.0.42"
  12. Date=`date "+%Y%m%d%H%M%S"`
  13. project_dir="/data/www/${project}"
  14. version_dir="/release/$project/${Date}_${BUILD_ID}"
  15. cat > keepfive.sh << 'EOF'
  16. file_path="/release/admin"
  17. while true;do
  18. A=`ls ${file_path} | wc -l`
  19. B=`ls -lrX ${file_path} | tail -n 1 | awk '{print $9}'`
  20. if [ $A -gt 5 ];then rm -rf ${file_path}/$B;else break;fi;done
  21. EOF
  22. if [ $mode == "deploy" ];then
  23. echoYellow "创建远程主机上的版本目录 :${version_dir}"
  24. ssh -p $remote_port $remote_user@$remote_ip "mkdir -p ${version_dir}"
  25. [ $? != 0 ] && echoRed "请注意,在创建远程主机上的版本目录时出错,故而退出构建,可联系运维同学处理!" && exit 1
  26. echoYellow "将代码同步到远程主机版本目录"
  27. rsync -az -e "ssh -p $remote_port" --exclude='Jenkinsfile' --exclude='keepfive.sh' --delete ${WORKSPACE}/ $remote_user@$remote_ip:$version_dir/
  28. [ $? != 0 ] && echoRed "请注意,在执行同步代码到版本目录时出错,故而退出构建,可联系运维同学处理!" && exit 1
  29. echoGreen "将代码同步到远程主机版本目录成功!"
  30. echoYellow "将项目部署到生产目录"
  31. ssh -p $remote_port $remote_user@$remote_ip "ln -snf $version_dir $project_dir"
  32. [ $? != 0 ] && echoRed "请注意,在将项目部署到生产目录时出错,故而退出构建,可联系运维同学处理!" && exit 1
  33. echoGreen "将项目部署到生产目录成功!"
  34. echoYellow "使版本目录保持五个版本历史"
  35. ssh -p $remote_port $remote_user@$remote_ip sh < keepfive.sh
  36. [ $? != 0 ] && echoRed "请注意,在执行版本清理时出错,将会影响回滚,故而退出构建,可联系运维同学处理!" && exit 1
  37. echoGreen "执行版本清理成功!"
  38. echoYellow "同步版本号到本地"
  39. [ ! -d /root/.jenkins/version/$project ] && mkdir -p /root/.jenkins/version/$project
  40. ssh -p $remote_port $remote_user@$remote_ip "ls /release/$project" > /root/.jenkins/version/$project/version.log
  41. echoGreen "============"
  42. echoGreen "上线部署完成!"
  43. echoGreen "============"
  44. else
  45. if [ ${version_id} == "0" ];then
  46. echoYellow "选择回滚的版本是默认,将回滚到上次制品,回滚即将进行..."
  47. Version="/release/$project/`tail -n2 /root/.jenkins/version/$project/version.log | head -n1`"
  48. ssh -p $remote_port $remote_user@$remote_ip "ln -snf $Version $project_dir"
  49. [ $? != 0 ] && echoRed "请注意,在执行回滚时出错,故而退出构建,可立即联系运维同学处理!" && exit 1
  50. echoGreen "=============="
  51. echoGreen "项目已回滚完成!"
  52. echoGreen "=============="
  53. else
  54. echoYellow "选择回滚的版本是:${version_id},将回滚到 ${version_id} 的制品,回滚即将进行..."
  55. Version="/release/$project/`grep "_$version_id" /root/.jenkins/version/$project/version.log`"
  56. ssh -p $remote_port $remote_user@$remote_ip "ln -snf $Version $project_dir"
  57. [ $? != 0 ] && echoRed "请注意,在执行回滚时出错,故而退出构建,可立即联系运维同学处理!" && exit 1
  58. echoGreen "项目回滚到 ${version_id} 完成!"
  59. fi
  60. fi

核心部分也就是脚本内容了,以上即是脚本内容,采用的逻辑也都比较容易理解,只要读一下就能理解,可用于生产,可能只需要调整一下几个变量,或者路径就可以直接投入使用。

3,自由风格结合ansible多机批量部署回滚示例

自由风格之下,同样首先创建对应的参数用于传递,然后这里又新增了一个参数用于传递远程主机,以实现单机或者批量发布都可的功能。

依旧是先定于参数如下:

Snipaste_2019-12-14_21-49-48.png

然后定义脚本如下:

  1. #!/bin/bash
  2. ##set color##
  3. echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
  4. echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
  5. echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
  6. ##set color##
  7. source /etc/profile
  8. project="tale"
  9. remote_port="22"
  10. remote_user="root"
  11. project_dir="/data/www/${project}"
  12. version_dir="/release/$project/${Date}_${BUILD_ID}"
  13. cat > keepfive.sh << 'EOF'
  14. file_path="/release/tale"
  15. while true;do
  16. A=`ls ${file_path} | wc -l`
  17. B=`ls -lrX ${file_path} | tail -n 1 | awk '{print $9}'`
  18. if [ $A -gt 5 ];then rm -rf ${file_path}/$B;else break;fi;done
  19. EOF
  20. cat > excludefile << EOF
  21. hosts.ini
  22. deploy.yml
  23. Jenkinsfile
  24. keepfive.sh
  25. excludefile
  26. EOF
  27. Rs(){
  28. if [ $remote_ip == "all" ];then
  29. cat > hosts.ini << EOF
  30. [remote]
  31. 10.3.9.32 ansible_port=34222
  32. 10.3.20.4 ansible_port=34222
  33. EOF
  34. else
  35. cat > hosts.ini << EOF
  36. [remote]
  37. $remote_ip ansible_port=34222
  38. EOF
  39. fi
  40. }
  41. Rb(){
  42. cat > rollback.yml << EOF
  43. ---
  44. - hosts: "remote"
  45. remote_user: root
  46. tasks:
  47. - name: "将项目回滚到对应期望的构建"
  48. file: path=/data/www/${project} state=link src=${Version}
  49. EOF
  50. }
  51. Rd(){
  52. cat > deploy.yml << EOF
  53. ---
  54. - hosts: "remote"
  55. remote_user: root
  56. tasks:
  57. - name: "创建远程主机上的版本目录"
  58. file: path=/release/${project}/${project}_${BUILD_ID} state=directory
  59. - name: "将代码同步到远程主机版本目录"
  60. synchronize:
  61. src: ${WORKSPACE}/
  62. dest: /release/${project}/${project}_${BUILD_ID}/
  63. rsync_opts: --exclude-from=excludefile
  64. - name: "将项目部署到生产目录"
  65. file: path=/data/www/${project} state=link src=/release/${project}/${project}_${BUILD_ID}
  66. - name: "使版本目录保持五个版本历史"
  67. script: keepfive.sh
  68. - name: "生成远程版本号"
  69. shell: "ls /release/${project} > /release/version.log"
  70. - name: "同步版本号到本地"
  71. synchronize: "src=/release/version.log dest=/root/.jenkins/version/${project}/version.log mode=pull"
  72. EOF
  73. }
  74. if [ $mode == "deploy" ];then
  75. Rs && Rd
  76. ansible-playbook -i hosts.ini deploy.yml
  77. else
  78. if [ ${version_id} == "0" ];then
  79. Rs
  80. echo "选择回滚的版本是默认,将回滚到上次制品,回滚即将进行..."
  81. Version="/release/$project/`tail -n2 /root/.jenkins/version/$project/version.log | head -n1`"
  82. Rb
  83. ansible-playbook -i hosts.ini rollback.yml
  84. echo "=============="
  85. echo "项目已回滚完成!"
  86. echo "=============="
  87. else
  88. Rs
  89. echo "选择回滚的版本是:${version_id},将回滚到 ${version_id} 的制品,回滚即将进行..."
  90. Version="/release/$project/`grep "_$version_id" /root/.jenkins/version/$project/version.log`"
  91. Rb
  92. ansible-playbook -i hosts.ini rollback.yml
  93. echo "项目回滚到 ${version_id} 完成!"
  94. fi
  95. fi

这里把所有内容都集成到一个脚本,便于维护管理。这是我现在比较推崇的一种配置习惯,日常使用过程中,可能我们经常需要调试一些东西,如果一个构建调用的脚本要放好几个地方,那么维护起来是非常痛苦的,莫不如直接全部都集成在Jenkins当中,任何时候需要排查某个项目,直接到Jenkins中打开配置查看即可,而不需要再找几个地方。

如上两种方式都是紧贴合文章开头的流程图所为,也就几个大佬口中简单的if/else而已,但是就已经足够满足并实现我们的需求了。


weinxin


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK