Jenkins结合gitlab实现静态项目发布

文章目录

  • 一、 Jenkins基本概述
    • 1.1 什么是Jenkins
    • 1.2 为什么需要Jenkins
    • 1.3 Jenkins安装
      • 1.3.1 调整系统语言环境
      • 1.3.2 安装JDK
      • 1.3.3 安装Jenkins
      • 1.3.4 Jenkins结构分析
      • 1.3.5 配置Jenkins
      • 1.3.6 启动Jenkins
      • 1.3.7 访问前先解锁jenkins
    • 1.4 优化Jenkins
  • 二、Jenkins插件管理
    • 2.1 联网安装插件
    • 2.2 手动上传插件
    • 2.3 离线安装插件
  • 三、Jenkins创建项目
  • 四 Jenkins集成Gitlab
    • 5.2 Jenkins集成Shell
    • 5.3 Jenkins集成Ansibl
  • 六、Jenkins实现CI
    • 6.1 CI架构图
    • 6.2 Jenkins实现CI整体思路
    • 6.3 手动实现CI流程
  • 七、jenkins shell(前端传参)
  • 八、Jenkins调用Ansible
    • 8.1 Jenkins调用Ansible传参
  • 九、Jenkins全自动CI
    • 9.1 定时构建
    • 9.2 SCM轮询
    • 9.3 Webhook
      • 9.3.1 配置Jenkins
      • 9.3.2 配置Gitlab触发器
  • 十、Jenkins基于CommitID实现CI
    • 10.1 Jenkins配置
    • 10.2 CI剧本
    • 10.3 基于CommitID回滚
      • 10.3.1 回滚思路
    • 10.4 基于脚本的回滚
    • 10.5 Jenkins结合Ansilbe 基于CommitID 实现回滚

一、 Jenkins基本概述

1.1 什么是Jenkins

Jenkins是一个开源提供友好操作界面的持续集成的工具,是由 JAVA 开发而成。
Jenkins 是一个调度平台,本身不处理任何事情,调用第三方插件来完成所有的工作。
Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。

1.2 为什么需要Jenkins

jenkins 能将各种开源的软件集成为一体,从而实现不同功能的调度工作。

1.3 Jenkins安装

官方下载
可以按照官网的方式配置仓库安装,也可以直接从清华大学源中下载rpm包安装。

1.3.1 调整系统语言环境

[root@jenkins ~]# setenforce 0
[root@jenkins ~]# systemctl stop firewalld
[root@jenkins ~]# systemctl disable firewalld

# 设置语言,避免后期Jenkins汉化不完整(设置后需要重启服务器)
[root@jenkins ~]# localectl set-locale
LANG=en_US.UTF-8
[root@jenkins ~]# localectl status

1.3.2 安装JDK

[root@jenkins ~]# yum install java-11-openjdk-devel -y
[root@jenkins ~]# java --version
openjdk 11.0.12 2021-07-20 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.12+7-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.12+7-LTS, mixed mode, sharing)

1.3.3 安装Jenkins

[root@jenkins ~]# yum localinstall -y https://mirror.tuna.tsinghua.edu.cn/jenkins/redhat/jenkins-2.303-1.1.noarch.rpm

1.3.4 Jenkins结构分析

[root@jenkins ~]# rpm -ql jenkins
/etc/init.d/jenkins  #启停文件
/etc/logrotate.d/jenkins # 日志切分文件
/etc/sysconfig/jenkins  # 配置文件
/usr/lib/jenkins  # JENKINS_HOME
/usr/lib/jenkins/jenkins.war
/usr/sbin/rcjenkins # 软链接,链接到启停文件
/var/cache/jenkins
/var/lib/jenkins
/var/log/jenkins # 日志目录

1.3.5 配置Jenkins

[root@jenkins ~]# vim /etc/sysconfig/jenkins
JENKINS_USER="root" # 运行Jenkins的用户身份,避免后期权限不足的情况
JENKINS_PORT="80" # 如果jenkins监听在80端口,运行身份必须为root

1.3.6 启动Jenkins

[root@jenkins ~]# systemctl start jenkins
[root@jenkins ~]# systemctl enable jenkins

1.3.7 访问前先解锁jenkins

1.当您第一次通过浏览器访问 Jenkins 时,系统会要求您使用自动生成的密码对其进行解锁。
2.解锁 Jenkins 之后,可以安装任何数量的插件作为您初始步骤的一部分。
1)如果不确定需要哪些插件,请选择 “安装建议的插件”(这个过程可能需要几分钟或几十分钟的时间)
2)也可以跳过插件安装,后期可以通过 Jenkins 的Manage Plugins 页面进行插件安装或删除。
3.创建一个 Jenkins 的管理员用户。然后单击保存完成。
在这里插入图片描述

[root@jenkins jenkins]# cat /var/lib/jenkins/secrets/initialAdminPassword
60d158c95780437ca8a65dc3c16c4150

解锁后使用admin用户继续操作,然后后台点击admin configure修改admin用户密码,然后用admin+新密码重新登录jenkins即可。
在这里插入图片描述

1.4 优化Jenkins

jenkins 系统管理中的插件管理非常重要,因为jenkins 的工作全部是由插件来完成。
但jenkins插件默认从国外下载,速度会很慢,所以需要在安装插件前将下载地址改为国内的下载地址:
1.修改jenkins “下载插件” 地址为国内镜像源;

sed -i 's#http://www.google.com/#https://www.baidu.com/#g' /var/lib/jenkins/updates/default.json

sed -i 's#updates.jenkins.io/download#mirror.tuna.tsinghua.edu.cn/jenkins#g' /var/lib/jenkins/updates/default.json

2.修改jenkins ”插件升级站点“ Url地址;选择 系统管理 -->插件管理–>高级–>升级站点
Manage Jenkins----> Manage Plugins------->Advanced
在这里插入图片描述

二、Jenkins插件管理

在插件管理中有 {可更新 | 可选插件 | 已安装} 日常的插件安装都是在这个界面上完成的。
插件的安装方式有联网安装、手动上传、离线安装三种方式

2.1 联网安装插件

在这里插入图片描述

2.2 手动上传插件

通过页面上传一个.hpi文件的方式来安装插件。
1.在 jenkins 官网 https://plugins.jenkins.io/下载插件。( 插件是以 .hpi 结尾的 ),或者去清华大学源下载插件。
2.将下载好的插件通过上传的方式进行安装 系统设置—>插件管理–>高级–>上传插件

2.3 离线安装插件

将之前jenkins服务器的插件保存下来,然后导入到服务器中,(离线安装),最后重启 Jenkins
未装任何插件之前新建任务界面如下:
在这里插入图片描述

[root@jenkins ~]# ls
anaconda-ks.cfg  jenkins_plugins_2021-10-19.tar.gz
[root@jenkins ~]# tar xf jenkins_plugins_2021-10-19.tar.gz -C /var/lib/jenkins/plugins/

[root@jenkins ~]# systemctl restart jenkins.service 

离线装完插件之后,新建任务界面如下:
在这里插入图片描述

三、Jenkins创建项目

1.新建一个项目

新建任务
1、输入任务名称:freestyle-demo
2、选择自由风格的软件项目
3、描述:描述该任务的作用

在这里插入图片描述
在这里插入图片描述

2.设置丢弃旧的构建

丢弃旧的构建:构建后的产物,保留多久
条件1:保持构建的天数:当前项目构建的产物最多保留多少天;
条件2:保持构建的最大个数:当前项目最多保留多少构建产物,多出的自动删除;

3.参数化构建过程
参数化构建:在执行任务时,可以传递参数,和Shell中的脚本位置参数一致

四 Jenkins集成Gitlab

之所以需要jenkins集成gitlab,是因为我们要抓取Gitlab上的代码,为后续发布网站做好准备;
由于 jenkins 只是一个调度平台,所有需要安装与gitlab 相关的插件才可完成对应的集成。
1、模拟开发组通过gitlab创建一个项目,然后进行代码提交;代码下载
2、创建一个新的 freestyle 项目,名称为monitor-deploy
3、在 jenkins 中填写 gitlab 项目地址(域名需要解析),由于是ssh协议,所以需要添加认证凭据;

  • 3.1 jenkins需要访问 gitlab 项目,则需要与gitlab建立信任;首先登陆Jenkins 生成一对秘钥;
  • 3.2 将 Jenkins 服务器生成的公钥添加上 gitlab对应的用户;
  • 3.3 然后继续操作 Jenkins,将 root 用户的私钥添加至 Jenkins 服务器上;至此就完成了“公钥加密私钥解密”;此时 jenkins 就能正常访问gitlab 项目。

4、选择对应的凭据,再次检查是否存在报错提示。如果没有点击保存即可。
5、最后点击构建,然后查看构建的输出信息是否有错误提示。
6、构建成功后,代码会被下载至 Jenkins 服务器本地 /var/log/jenkins/workspace目录下。
在这里插入图片描述

5.2 Jenkins集成Shell

构建–>增加构建步骤–>选择执行 shell 命令
jenkins向web集群推送代码,首先jenkins服务器要与web集群免密。
在这里插入图片描述
在这里插入图片描述

WORKSPACE为系统参数,为当前项目所在目录,代码从gitlab拉取过来恰巧就放入此目录中。

构建并执行:
在这里插入图片描述
#构建后所产生的文件会存储在/var/lib/jenkins/workspace/jenkins_project_name目录下.

5.3 Jenkins集成Ansibl

1.jenkins服务器上安装ansible

[root@jenkins ~]# yum install ansible -y

2.配置ssh免密(ansibl要操作哪台主机,就对哪台主机免密)

[root@jenkins ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.5
[root@jenkins ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.6
[root@jenkins ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.7
[root@jenkins ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.8
[root@jenkins ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.9
[root@jenkins ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.99

3.配置inventory主机清单文件

[root@jenkins ~]# cat /etc/ansible/hosts 
[webservers]
172.16.1.7
172.16.1.8
172.16.1.9

[lbservers]
172.16.1.5
172.16.1.6

[test]
172.16.1.99

在这里插入图片描述

root@jenkins roles]# cat test.yml 
- hosts: "{{ host }}"
  tasks:
    - name: Test Shell Command
      shell:
        cmd: ls
      register: system_cmd

    - name: Debug System Command
      debug:
        msg: "{{ system_cmd }}"


在这里插入图片描述
这时候选择参数化构建,选择选项参数:
在这里插入图片描述
然后前端就可以这样传参:
在这里插入图片描述

六、Jenkins实现CI

6.1 CI架构图

在这里插入图片描述

6.2 Jenkins实现CI整体思路

1.搭建 web 集群架构环境;
2.模拟开发提交代码至 gitlab、
3.模拟运维拉取代码,并推送至 web 服务器组;
4.将手动发布的操作编写为 Shell或Ansible 脚本,由 Jenkins 调用;

6.3 手动实现CI流程

1.lb上haproxy上的安装,这些操作其实是在搭建web集群时已经由ansible自动部署了。
2.webservers上的nginx安装与配置

# haproxy 安装
[root@proxy01 ~]# yum install socat -y
[root@proxy01 ~]# wget https://cdn.xuliangwei.com/haproxy22.rpm.tar.gz
[root@proxy01 ~]# tar xf
haproxy22.rpm.tar.gz
[root@proxy01 ~]# yum localinstall haproxy/*.rpm -y

3.从仓库拉取代码,进入仓库

[root@jenkins ~]# git clone git@gitlab.bertwu.com:dev/monitor.git
[root@jenkins ~]# cd monitor/

4.使用 tar 命令打包代码,带上时间戳;

[root@jenkins monitor]# tar czf /opt/monitor_$(date +%F).tar.gz ./*

5.将打包代码使用 scp 推送代码至目标集群;

[root@jenkins monitor]# scp /opt/monitor_2021-10-21.tar.gz 172.16.1.7:/opt

6.操作负载均衡摘掉节点,多个负载均衡需要做循环操作;

[root@jenkins ~]# ssh root@172.16.1.5 "echo 'disable server web_cluster/172.16.1.7' | socat stdio /var/lib/haproxy/stats"

7.远程创建对应目录用于存放代码

[root@jenkins opt]# ssh root@172.16.1.7 "mkdir /opt/monitor_$(date +%F)" 
[root@jenkins opt]# ssh root@172.16.1.8 "mkdir /opt/monitor_$(date +%F)" 

8.解压代码到对应目录,解压出来直接就是一堆散代码

[root@jenkins opt]# ssh root@172.16.1.7 "tar xf /opt/monitor_2021-10-21.tar.gz -C /opt/monitor_$(date +%F)" 
[root@jenkins opt]# ssh root@172.16.1.8 "tar xf /opt/monitor_2021-10-21.tar.gz -C /opt/monitor_$(date +%F)" 

9.删除旧软连接,创建新软连接

[root@jenkins opt]# ssh root@172.16.1.7 "rm -rf /opt/web" 
[root@jenkins opt]# ssh root@172.16.1.7 "ln -s /opt/monitor_$(date +%F) /opt/web"  

10.将节点加入负载均衡,对外提供

ssh root@172.16.1.5 "echo 'enable server web_cluster/172.16.1.7' | socat stdio /var/lib/haproxy/stats"

11.对其他webservers中的其他主机,重复5-10的操作

可以看到,手动部署非常麻烦,需用借助jenkins shell 自动化构建

七、jenkins shell(前端传参)

为 jenkins 的项目增加构建步骤,选择执行 Shell;
1.在jinlins上创建新项目 Monitor_Shell_CI,
自动发布脚本思路如下

# 1.进入代码目录,对代码进行打包;
# 2.将代码推送至目标集群节点;
# 3.将节点从负载均衡中摘掉节点;
# 4.解压代码,创建软连接,测试站点可用性;
# 5.加入节点至负载均衡,对外提供服务;
# 6.需要通过函数的方式来编写,使得脚本更加的专

脚本

[root@jenkins scripts]# cat deploy_html.sh 
#!/usr/bin/bash
Date=$(date +%F_%H_%M)
web_dir=/opt
#webservers="172.16.1.7 172.16.1.8"
#lbservers="172.16.1.5"
web_name=web

#上锁
if [ -f /tmp/lock ];then
	echo "脚本正在执行,请不要重复执行"
	exit
fi

# 枷锁

touch /tmp/lock 



test="172.16.1.9"
testlbserbers="172.16.1.6"
#1.进入项目中打包

cd ${WORKSPACE} && \
tar czf $web_dir/monitor_$Date.tar.gz ./*


#2.将打包代码推送到目标集群

for host in $webservers
do
    scp $web_dir/monitor_$Date.tar.gz $host:$web_dir
done

# 下线节点
lbservers_disable (){
	for lb_host in $lbservers
	do
		ssh root@$lb_host "echo 'disable server web_cluster/$1' | socat stdio /var/lib/haproxy/stats"
	done
}

# 上线节点
lbservers_enable (){
	for lb_host in $lbservers
	do
		ssh root@$lbservers "echo 'enable server web_cluster/$1' | socat stdio /var/lib/haproxy/stats"
	done
}


for host in $webservers
do
  #下线节点
	lbservers_disable $host

  # 创建目录
	ssh root@$host "mkdir $web_dir/monitor_$Date"
  # 解压代码到对应目录
	ssh root@$host "tar xf $web_dir/monitor_$Date.tar.gz -C $web_dir/monitor_$Date"

  # 删除旧软连接,创建新软连接
	ssh root@$host "rm -rf $web_dir/$web_name && ln -s $web_dir/monitor_$Date $web_dir/$web_name"
	
  # 上线节点		
	lbservers_enable $host
	
	sleep 5

done

#解锁
rm -rf /tmp/lock

参数设置:
在这里插入图片描述
前端传参展示
在这里插入图片描述

八、Jenkins调用Ansible

创建一个项目,名称为:monitor-Ansible-CI,在执行构建阶段选择 Invoke Ansible Playbook
Playbook path:/scripts/deploy_html.yml,文件绝对路径Inventory:File or host list
(/etc/ansible/hosts),主机清单文件路径
通过Ansible实现自动化部署整体思路;
1.设定时间变量,设定WorkSpace变量,委派给Jenkins节点执行;
2.代码进行打包,委派给Jenkins节点执行;
3.当 web 节点代码需要更新时,先下线节点,将任务委派给Haproxy
4.关闭web端的nginx
5.为web节点创建站点目录,并将代码推送至对应的目录中;
6.删除软连接,重新创建软连接;
7.重启nginx
8.加入负载均衡
在这里插入图片描述

[root@jenkins ~]# cat /scripts/deploy_html.yml 
- hosts: "{{ deploy_webcluster }}"
  serial: 1
  vars:
    - web_dir: /opt
    - web_name: monitor
    - backend_name: web_cluster
    - service_port: 80

  tasks:
    - name: set system time variable
      shell:
        cmd: "date +%F:%H:%M"
      register: system_date
      delegate_to: "127.0.0.1"
    
    # 设定jenkins workspace 变量
    - name: set jenkins workspace 
      shell:
        cmd: echo ${WORKSPACE}
      register: workspace
      delegate_to: "127.0.0.1"

    # 打包代码
    - name: archive web code
      archive:
        path: "{{ workspace.stdout }}/*"
        dest: "{{ web_dir }}/{{ web_name }}.tar.gz"
      delegate_to: "127.0.0.1"


    # 下线节点
    - name: stop haproxy webcluster pool node
      haproxy:
        socket: /var/lib/haproxy/stats
        backend: "backend_name"
        state: disabled
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}"
      loop: "{{ groups['lbservers']}}"
   
   # 创建站点目录
    - name: create web sit directory
      file:
        path: "{{ web_dir}}/{{ web_name }}_{{ system_date.stdout }}"
        state: directory 
  
   # 关闭nginx服务
    - name: stop nginx server
      systemd:
        name: nginx
        state: stopped

   # 检测nginx是否已经关闭,端口是否存活
    - name: check port state
      wait_for:
        port: "{{ service_port }}"
        state: stopped

   # 解压代码到远程
    - name: unarchive code to remote
      unarchive:
        src: "{{ web_dir }}/{{ web_name }}.tar.gz"
        dest: "{{ web_dir}}/{{ web_name }}_{{ system_date.stdout }}"

   # 删除软连接
    - name: delete old webserver link
      file:
        path: "{{ web_dir}}/web"
        state: absent

   # 创建新的软连接
    - name: create new webserver link
      file: 
        src: "{{ web_dir}}/{{ web_name }}_{{ system_date.stdout }}"
        dest: "{{ web_dir }}/web"
        state: link
 
  # 启动nginx服务
    - name: start nginx server
      systemd:
        name: nginx
        state: started

   # 检测nginx是否已经启动,端口是否存活
    - name: check port state
      wait_for:
        port: "{{ service_port }}"
        state: started



   # 上线节点
    - name: start haproxy webcluster pool node
      haproxy:
        socket: /var/lib/haproxy/stats
        backend: "backend_name"
        state: enabled
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}" # 委派给负载均衡节点
      loop: "{{ groups['lbservers']}}"

8.1 Jenkins调用Ansible传参

1.Playbook中定义的hosts主机是写死的,这样不够灵活,希望通过传参让其变得更加灵活

[root@jenkins scripts]# vim
/scripts/deploy_html.yml
- hosts: "{{ deploy_webcluster }}" # 修改为变量

2.在Jenkins中配置Ansible的外置传参,value为一个变量,需要通过执行Jenkins时进行传递;
在这里插入图片描述

3.配置Jenkins的参数化构建,这些参数会当作环境变量暴露给构建任务
在这里插入图片描述
l

九、Jenkins全自动CI

9.1 定时构建

定时构建,每间隔多久执行一次;无论代码是否更新,时间到了则会执行;类似于定时任务的功能
在这里插入图片描述
每隔5分钟执行,缺点,不管代码修改没修改,都会在指定的时间重新拉取代码部署

9.2 SCM轮询

SCM轮询:每分钟检查代码是否更新,当检查到代码发生变更后,会触发构建,否则不执行;
在这里插入图片描述
每隔一分钟轮询一次。
在这里插入图片描述

9.3 Webhook

webhook 就是当开发一提交代码,则立刻将代码部署至目标集群服务节点;
需要配置Jenkins和Gitlab触发器

9.3.1 配置Jenkins

  1. 点击jenkins中对应的项目,找到构建触发器;
  2. 配置jenkins通知的项目地址;
  3. 找到高级,然后找到Secret token,点击Generate生成token;

这样就可以通过外部程序调用Jenkins,进而触发动作构建项目

在这里插入图片描述

在这里插入图片描述

9.3.2 配置Gitlab触发器

1.配置 gitlab,管理中心–>设置–>网络设置–>外发请求–>允许钩子和服务访问本地网络(勾选)
2.找到对应要实现自动化发布的项目,点击设置–>集成–>链接–>通知jenkins的哪个项目地址
令牌–>jenkins针对项目生成的token令牌
在这里插入图片描述

十、Jenkins基于CommitID实现CI

默认情况下都是基于最新版本获取代码,但仅有时间戳无法区分出代码对应的版本,例如发布代码颗粒密度很小的时候,每分钟更新多次代码,就无法做到精确的获取每个版本,所以我们可以基于git commitID 来实现代码的发布策略,保证每次代码提交与发布都是唯一的。

10.1 Jenkins配置

1.创建一个新的项目,monitor-Ansible-Commit-CI,然后再Jenkins前端增加git传参方式
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

10.2 CI剧本

[root@jenkins scripts]# cat deploy_html_commitid.yml 
- hosts: "{{ deploy_webcluster }}"
  serial: 1
  vars:
    - web_dir: /opt
    - web_name: monitor
    - backend_name: web_cluster
    - service_port: 80

  tasks:
    - name: set system time variable
      shell:
        cmd: "date +%F:%H:%M"
      register: system_date
      delegate_to: "127.0.0.1"
    
    # 设定jenkins workspace 变量
    - name: set jenkins workspace 
      shell:
        cmd: echo ${WORKSPACE}
      register: workspace
      delegate_to: "127.0.0.1"
  
    # 获取commitid ,用shell可以获取到前端的任何环境变量
    - name: get commit id
      shell:
        cmd: "echo ${git_commit_id} | cut -c 1-8" # 获取前8register: commit_id
      delegate_to: "127.0.0.1"




    # 打包代码
    - name: archive web code
      archive:
        path: "{{ workspace.stdout }}/*"
        dest: "{{ web_dir }}/{{ web_name }}_{{ commit_id.stdout}}.tar.gz"
      delegate_to: "127.0.0.1"


    # 下线节点
    - name: stop haproxy webcluster pool node
      haproxy:
        socket: /var/lib/haproxy/stats
        backend: "backend_name"
        state: disabled
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}"
      loop: "{{ groups['lbservers']}}"
   
   # 创建站点目录
    - name: create web sit directory
      file:
        path: "{{ web_dir}}/{{ web_name }}_{{ system_date.stdout }}_{{ commit_id.stdout }}"
        state: directory 
  
   # 关闭nginx服务
    - name: stop nginx server
      systemd:
        name: nginx
        state: stopped

   # 检测nginx是否已经关闭,端口是否存活
    - name: check port state
      wait_for:
        port: "{{ service_port }}"
        state: stopped

   # 解压代码到远程
    - name: unarchive code to remote
      unarchive:
        src: "{{ web_dir }}/{{ web_name }}_{{ commit_id.stdout }}.tar.gz"
        dest: "{{ web_dir}}/{{ web_name }}_{{ system_date.stdout }}_{{ commit_id.stdout }}"

   # 删除软连接
    - name: delete old webserver link
      file:
        path: "{{ web_dir}}/web"
        state: absent

   # 创建新的软连接
    - name: create new webserver link
      file: 
        src: "{{ web_dir}}/{{ web_name }}_{{ system_date.stdout }}_{{ commit_id.stdout }}"
        dest: "{{ web_dir }}/web"
        state: link
 
  # 启动nginx服务
    - name: start nginx server
      systemd:
        name: nginx
        state: started

   # 检测nginx是否已经启动,端口是否存活
    - name: check port state
      wait_for:
        port: "{{ service_port }}"
        state: started



   # 上线节点
    - name: start haproxy webcluster pool node
      haproxy:
        socket: /var/lib/haproxy/stats
        backend: "backend_name"
        state: enabled
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}" # 委派给负载均衡节点
      loop: "{{ groups['lbservers']}}"

10.3 基于CommitID回滚

在更新新版本可能会存在一些未知的Bug,为了不影响用户的正常使用,需要先将代码回退至上一个可用的版本;所以需要我们代码的快速回退功能;

10.3.1 回滚思路

1.从负载均衡中摘掉节点;
2.登陆目标集群服务节点;
3.删除软链接,重建软连接(依照前端传递的commitid可以快速定位到之前推送到web主机上的软件包);
4.重载服务,加入集群服务;

10.4 基于脚本的回滚

伪代码:

commitid=$(echo ${git_commit_id} | cut -c 1-8)

for host in webservers
do

  ssh root@$host "old_name=$(find /opt -type d -name "*${commitid}") && \
                  rm -rf /opt/web && \
                  ln -s ${old_name} /opt/web"                                                                           
done

10.5 Jenkins结合Ansilbe 基于CommitID 实现回滚

[root@jenkins scripts]# cat rollback_html_commitid.yml 
- hosts: "{{ deploy_webcluster }}"
  serial: 1
  vars:
    - web_dir: /opt
    - web_name: monitor
    - backend_name: web_cluster
    - service_port: 80

  tasks: 
    # 获取commitid
    - name: get commit id
      shell:
        cmd: "echo ${git_commit_id} | cut -c 1-8" # 获取前8register: commit_id
      delegate_to: 127.0.0.1



    # 下线节点
    - name: stop haproxy webcluster pool node
      haproxy:
        socket: /var/lib/haproxy/stats
        backend: "backend_name"
        state: disabled
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}"
      loop: "{{ groups['lbservers']}}"
   
  
   # 关闭nginx服务
    - name: stop nginx server
      systemd:
        name: nginx
        state: stopped

   # 检测nginx是否已经关闭,端口是否存活
    - name: check port state
      wait_for:
        port: "{{ service_port }}"
        state: stopped


   # 删除软连接
    - name: delete old webserver link
      file:
        path: "{{ web_dir}}/web"
        state: absent
  
   # 获取之前版本的commitid 对应的 文件路径
    - name: find old version
      find:
        paths: "{{ web_dir }}"
        patterns: "*{{ commit_id.stdout }}*"
        file_type: directory
      register: old_version_dir

   # 获取 旧版本 对应的绝对路径)
    - name: get absolute path about old_version_dir
      debug:
        msg: "{{ old_version_dir.files[0].path  }}"
      register: web_absolute_path_commitid
  

   # 创建新的软连接
    - name: create new webserver link
      file: 
        src: "{{ web_absolute_path_commitid.msg }}"
        dest: "{{ web_dir }}/web"
        state: link

 
  # 启动nginx服务
    - name: start nginx server
      systemd:
        name: nginx
        state: started

   # 检测nginx是否已经启动,端口是否存活
    - name: check port state
      wait_for:
        port: "{{ service_port }}"
        state: started



   # 上线节点
    - name: start haproxy webcluster pool node
      haproxy:
        socket: /var/lib/haproxy/stats
        backend: "backend_name"
        state: enabled
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}" # 委派给负载均衡节点
      loop: "{{ groups['lbservers']}}"

在这里插入图片描述
在这里插入图片描述

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法,在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较,从而确定目标数是在中间数的左边还是右边,将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令: 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体,就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛,这门课会介绍许多方法去利用离散点最大化地逼近这个函数,甚至它的导数、积分,甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下,坐标杭州,14届本科毕业,算上年前在阿里巴巴的面试,一共有面试了有6家公司(因为不想请假,因此只是每个晚上去其他公司面试,所以面试的公司比较少) ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目: 解题思路: 第一步: 第二步: 第三步: 总代码: 题目: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验,睡觉过程中突然意识清醒,身体却动弹不了。这时候感觉非常恐怖,希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况,一年有一百多次,那时候很害怕晚上到来,睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别(move-only type,只移型别还有std::mutex等)。 结合一下工厂模式,看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在,但代码中需要用到它,通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能,通常需要完成两步操作:一.是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度(?) 不管两个高积木之间的的积木是怎样乱七八糟的高度,最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的,用的是MFC VS2019. 详见:http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936,然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一:区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N,表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家,在他的着作中曾经提到:「若有一只免子每个月生一只小免子,一个月后小免子也开始生产。起初只有一只免子,一个月后就有两只免子,二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源,一般分为两类: 系统内置资源:Android SDK中所提供的已经定义好的资源,用户可以直接拿来使用。 用户自定义资源:用户自己定义或引入的,只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 如果一个算法有缺陷,或不适合于某个问题,执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python,NLP,知识图谱,机器学习,深度学习人工智能:知识图谱实战前言一、实体建模工具Protegepython,NLP,知识图谱,机器学习,深度学习 人工智能:知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…