Jenkins简介安装

持续集成是 DevOps 最重要的部分,用于集成各个 ***DevOps 阶段***。Jenkins 是最著名的持续集成工具

什么是持续集成

持续集成是一种开发实践,在这种实践中,要求开发人员每天多次或更频繁地对共享存储库中的源代码提交更改。然后构建存储库中进行的每个提交。这使团队可以及早发现问题。除此之外,根据持续集成工具的不同,还有其他一些功能,例如在测试服务器上部署构建应用程序,为相关团队提供构建和测试结果等。

Jenkins 经常和gitlab结合实现 CI/CD ,是基于 Java的独立程序,jenkins结合脚本和插件可以把代码自动部署到公司服务器上去,是常用的CD组件 官网位置

代码能不能部署到生产环境?

​ 测试人员通过以后需要通过发送邮件发送测试报告

如何部署?部署什么服务是由开发定义

手动、脚本、Jenkins、自动化平台等

部署那些机器都是提前写好一个表格里面,部署时间我们公司基本都是周四晚上 12:00左右,周五还有时间观察

如果是 kubernetes 容器可以随时部署·

1
2
3
4
jenkis是用来以非交互的方式连接到gitlab,把代码克隆下来,把项目打成jar包, 结合脚本或者插件实现把我们的代码以非交互的方式部署到web服务器上,类似一条流水线。
至于怎么部署,可以手动部署,也可以结合脚本部署
#优势
能够实现持续集成和持续部署,可扩展的自动化服务器。

安装方式介绍

  • jenkins安装官网 如果嫌慢可以去清华源下载`

  • jenkins有三种安装方式 ,下面会介绍

1 java -jar 启动 生产中不会这样启动,只要有java环境安装就可以,在公司一般都是 8G 内存 8C 100G磁盘起步,下 载LTS稳定版

1
2
3
4
5
6
7
8
9
10
$ apt install openjdk-8-jdk
$ mkdir /apps && cd /apps
$ wget https://mirror.tuna.tsinghua.edu.cn/jenkins/war-stable/2.289.3/jenkins.war #下载war包
$ java \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname="172.31.5.104" \
-jar jenkins.war &

2 在tomcat里面启动用的也不多,不太安全

1
2
3
4
5
6
7
$ mv /opt/apache-tomcat-8.5.69.tar.gz
$ tar xvf apache-tomcat-8.5.69.tar.gz
$ mv jenkins.war apache-tomcat-8.5.69/webapps/
$ cd /apps/apache-tomcat-8.5.69/
$ ./bin/catalina.sh run
访问就会显示登录界面
10.0.0.12:8080/jenkins

3 rpm包安装 最常用 这里使用清华源下载rpm安装包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#$先安装一台作为jenkins的MASTER
1 wget https://mirror.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.289.3_all.deb
2 需要下载依赖
apt install daemon
3 dpkg 安装
dpkg -i jenkins_2.289.3_all.deb

4、修改配置文件,修改以下配置,root是方便操作
vim /etc/default/jenkins
JENKINS_USER=root
JENKINS_GROUP=root
MAXOPENFILES=65535


5、配置文件介绍
/var/lib/jenkins #数据路径
/var/lib/jenkins/plugins/ # 插件路径
/etc/default/jenkins #配置文件路径
/var/lib/jenkins/jobs # job配置路径,config.xml 记录所有操作
  • 安装好以后访问本机的 8080默认 端口就可以访问,然后会推荐安装自定义插件,默认安装即可,插件安装好以后需要重启服务

4、Docker安装部署

安装Jenkins我这里直接使用Docker安装,安装docker可以直接参考阿里源

1
2
3
4
5
6
7
8
9
ubuntu配置docker
Ubuntu需要把soct映射到容器内部,并安装docker。
# 启动范例
docker run -d --name jenkins-paas-build-ubuntu20.04 --privileged=true \
-p 8080:8080 -p 5000:50000 \
-v /data/jenkins:/var/jenkins_home \
-v /etc/localtime:/etc/localtime \
-e JAVA_OPTS=-Duser.timezone=Asia/Shanghai \
jenkins/jenkins:2.346.2
  • –privileged=true含义

privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。

甚至允许你在docker容器中启动docker容器。

Jenkins设置为中文界面

1、下载Locale插件

点击Manage Jenkins –> 可选插件 –> 搜索local点击安装最后重启即可

重启好以后在点击系统配置 –> 找到local选项增加:zh_CN应用即可

插件使用和邮箱配置

jenkins 官方插件下载路径,需要下载下来,如果服务器无法上网就找到一台可以上网的服务把 /var/lib/jenkins/plugins/ 插件打包拷贝下来拷贝到服务器,然后重启jenkins就可以

  • 常用插件

  • Blue Ocean (是一个用户界面,创建流水线使用)

  • Role-based #基于角 色的认证策略

邮件通知

jenkins可以实现如果代码构建成功就可以发送邮件通知,这个是可选的因为构建我们都是在看着构建的

web界面点击-Dashboard –> 配置 找到系统管理员地址 输入qq就可以,说明由于企业邮箱大部分都使用的是企业邮件服务器:密码输入企业邮件即可

然后在最下面找到 邮件通知 SMTP服务器 填写(smtp.qq.com) 用户默认邮件后缀 (@qq.com)

在点击高级设置输入SMTP的授权码即可测试 ,端口是465

企业微信邮箱配置

小案例-隐藏插件告警信息

担心别人会不小心点到升级 导致插件版本不兼容 或者jenkins服务重启 因此打算把它隐藏掉

1656478325374

点击系统管理 –> 找到全局安全配置 –> 然后把隐藏的安全警告取消勾选安保存即可

创建job说明

先介绍基础创建自由风格 job 的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1、输入一个任务名称点击创建
2、源码管理使用Git 如果使用SVN就安装SVN的插件
触发器如果一个一个点闲慢可以远程构建,写shell脚本或者python脚本实现远程调用构建,下面是简单的触发python脚本,这样一次可以构建多个job
- 首先在jenkins服务器上面生成一个Token ,在web上选择一个job勾选触发器上选择构建远程触发
http://10.0.0.17:8080//job/yanghongtao-web1-job/build?token=0266a27f9322b16d9afc5f90
$ openssl rand -hex 12 #服务器生成token
- 这个时候可以使用curl 或者python脚本触发
cat jenkins_buildjob.sh
#!/bin/bash
curl http://10.0.0.17:8080/job/yanghongtao-web1-job/build?token=0266a27f9322b16d9afc5f90
curl http://10.0.0.17:8080/job/yanghongtao-web2-job/build?token=0266a27f9322b16d9afc5f90
curl http://10.0.0.17:8080/job/yanghongtao-web3-job/build?token=0266a27f9322b16d9afc5f90


- 编写python脚本
cat jenkins_build.py
#!/usr/bin/env python
#coding:utf-8
// pip3 install jenkinsapi
form jenkinsapi.jenkins import jenkins
conn = jenkins('http://10.0.0.17:8080'.username='jenkinsadmin',password='12345678',useCrumb='4cs5c4c1c1c54c5csad4')
conn.build_job('yang-nginx-web1')
conn.build_job('yang-nginx-web2')

3、构建后操作可以邮件通知 (可选)
4、构建成功以后会在/var/lib/jenkins/workspace/ 生成job名称

jenkins 脚本调用

jenkins调用shell脚本

  • jenkins后台脚本调用,在jenkins 服务器后端写脚本,这样保证脚本不会被别人篡改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ mkdir /data/script/jenkins -p && cd /data/script/jenkins
    - 给脚本添加可执行权限
    $ cat yht-app1-develop.sh
    #!/bin/bash
    echo "This is yht app1 job"
    $ ll /data/script/jenkins/yht-app1-develop.sh

    # 随后在jenkins-web界面 选择构建shell 然后填写以下内容执行即可
    bash /data/script/jenkins/yht-app1-develop.sh

    jenkins调用python脚本

    1
    2
    3
    4
    5
    6
    $ cd /data/script/jenkins && cat yht-app1-develop.py
    #!/usr/bin/python3.6
    print('yht app1 deploy')

    # 随后在jenkins-web界面 选择构建shell 然后填写以下内容执行即可
    /usr/bin/python3.6 /data/script/jenkins/yht-app1-develop.py

jenkins 权限管理

配置 jenkins 权限管理:
基于角色的权限管理,先创建角色和用户,给角色授权,然后把用户管理到角色。需要安装插件 Role-based #基于角色认证策略

一个jenkins是给多个项目去用,每个项目的人对应不同的 job ,防止别人误操作只允许 每个人的项目对应不同的job。

每个项目都有自己的job,比如magedu-m44等,还有45、46等等。然后会把不同的项目给不同的角色去管理

  • 首先创建账号测试,在系统管理的管理用户里面,点击新建用户 (默认jenkins登录用户是所有权限

  • 需要使用admin账号登录,并且下载插件Role-based,在可选插件当中

1、 点击系统配置 ==> 全局安全配置 (默认情况下是登录用户可以做任何事情)

在授权策略里面点击 Role-Based Strategy 这个时候普通用户访问 会提示没有权限

2、创建Role角色(Manage Roles): 重新点击 系统管理 选择Manage and Assign Roles点击Manage Roles创建只读菜单

Global roles:代表全局 使用 Role to add 添加全局角色勾选 Read(勾选只读就行)

Item roles : 代表构建job ,(权限可以全给,毕竟是某个人负责的指定项目)支持政策表达式 可以以点* 结尾

3、 用户继承权限 (Assign Roles) : Global roles 以及 item roles角色添加好登录普通用户即可看到对应的权限

jenkins 代码克隆

jenkins以非交互式进行克隆

1
2
3
4
5
6
7
8
代码克隆分为两种方式
` jenkins以非交互式进行克隆,自己克隆需要信任 ,他会把克隆的代码放在指定位置`
- 首先把jenkins服务器秘钥放在gitlab上
cat /root/.ssh/id_rsa.pub
- gitlab 用户设置里面选择 SSH秘钥,把jenkins的公钥放进去
- 然后在项目里面选择ssh协议克隆即可
- jenkins 配置job 在源码管理选择 Git ,私钥需要放在jenkins里面 需要添加凭据选择ssh才可以使用 ,分支选择main

通过shell脚本克隆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 通过shell脚本,把克隆命令放在脚本里面,这种使用比较多,我们可以自己指定路径,秘钥还是按照之前的方式添加到构建的job里面
-

1、编写脚本,测试是否能克隆成功,如果成功就放在jenkins服务器上面直接bash执行防止篡改,生产环境建议多加一些判断
cat /data/script/jenkins/yht-app1-develop.sh
#!/bin/bash
#bash /data/script/jenkins/yht-app1-develop.sh
cd /var/lib/jenkins/workspace/yanghongtao-web1-job
tar -zcvf app1.tar.gz ./index.html
scp app1.tar.gz 10.0.0.12:/data/tomcat/tomcat_appdir/
ssh 10.0.0.12 "systemctl stop tomcat.service"
ssh 10.0.0.12 "rm -rf /data/tomcat/tomcat_webapps/myapp/* && cd /data/tomcat/tomcat_appdir && tar -xvf app1.tar.gz -C /data/tomcat/tomcat_webapps/myapp"
ssh 10.0.0.12 "systemctl start tomcat.service"


2、 在jenkins网页端 shell命令执行
bash /data/script/jenkins/yht-app1-develop.sh

代码部署流程

jenkins的分布式

在公司我们部署的项目很多,这个时候就有了jenkins分布式,一个jenkins的master,用来创建和配置任务,但是不执行,他会让jenkins Agent去执行代码克隆部署,大幅度降低负载,MASTER去创建分配任务就可以了,agent连接gitlab去克隆,就算对几百个服务器更新也没问题,只有jenkins MASTER有web界面,agent是没有界面的。

安装 jenkins slave

如果有些执行脚本 node节点可能执行失败,所以各个服服务器需要每个节点都有这个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1、- 安装  slave 和master数据目录保持一致  ,还必须有java环境 
$ mkdir /var/lib/jenkins -p
2、jenkins 服务器web界面选择系统管理 -- 节点管理 --新建节点 -- 名称(jenkins-slave1)固定节点
- 描述:jenkins-slave1 和名字一样
- 执行数量:8
- 标签:非常重要用于job的节点匹配 一般和节点一样 (jenkins-slave1)
- 远程工作目录:/var/lib/jenkins
- 用法:只允许绑定这个机器上的job,如果选择尽可能任务是随机分配的
- 启动方式:Launch agents via SSH
- 主机: slave的ip地址,然后添加凭据,写上描述
- 添加好以后,可以查看日志是否添加成功
- slave 节点查看一定会有一个jenkins进程
$ ps -ef|grep jenkins

pipline 使用

官方文档 jenkins从2.x 版本以后,他能实现非常强大的流水线,就好像富士康。这个代码类似于shell脚本 ,但是我们既不需要放在jenkins也不需要放在服务器上。因为之前脚本放在jenkins可能会造成别的人误操作,导致部署失败。
优势:他的优势是比脚本的功能更加丰富。可以夸多个node节点去执行 ,支持暂停(可以选择停止或人工批准在执行) 已经重启或者中断不影响已经执行的job

语法简介

1
2
3
- stage: 阶段 ,一个pipline可以分成若干个stage,一个stage可以拥有多个step
- Node:节点,是让那个服务器运行,可以跨多个node
- Step: 步揍,从创建到构建分成几部分执行

脚本式pipline

如果不会写pipline语法的话,jenkins支持在线生成语法

node是slave节点名字,不写就随机分配给其中一个node,一定要写node的标签,一个stage就是一个任务,语法对缩进没有要求

代码clone: 点击流水线语法,选择git,以及分支main,在添加凭据生成流水线语法即可,clone成功会在node节点生成ll /var/lib/jenkins/workspace/yht-m44-pipline-web1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
node('master'){
stage('代码clone') {
deleteDir()
git branch: 'main', credentialsId: '2376883d-0210-46a4-ab50-119f6a7c240a', url: 'git@10.0.0.11:magedu/app1.git'
}
stage('代码构建') {
sh 'cd /var/lib/jenkins/workspace/yht-m44-pipline-web1 && tar czvf app1.tar.gz ./index.html'
}
stage('停止服务') {
sh 'ssh 10.0.0.12 "systemctl stop tomcat.service"'
}
stage('代码copy') {
sh 'scp /var/lib/jenkins/workspace/yht-m44-pipline-web1/app1.tar.gz 10.0.0.12:/data/tomcat/tomcat_appdir/'
}
stage('代码升级') {
sh 'ssh 10.0.0.12 "rm -rf /data/tomcat/tomcat_webapps/myapp/* && cd /data/tomcat/tomcat_appdir && tar -xvf app1.tar.gz -C /data/tomcat/tomcat_webapps/myapp"'
}
stage('启动服务') {
sh 'ssh 10.0.0.12 "systemctl start tomcat.service"'
}
}

声明试pipline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
pipeline { 
//agent any
agent { label 'master' }
stages {
stage('代码clone') {
steps {
echo '代码clone'
deleteDir()
git branch: 'main', credentialsId: '2376883d-0210-46a4-ab50-119f6a7c240a', url: 'git@10.0.0.11:magedu/app1.git'
}
}
stage('代码构建'){
steps {
sh 'cd /var/lib/jenkins/workspace/yht-m44-pipline-web1 && tar czvf app1.tar.gz ./index.html'
}
}
stage('停止服务') {
steps {
sh 'ssh 10.0.0.12 "systemctl stop tomcat.service"'
}
}

stage('代码copy'){
steps {
sh 'scp /var/lib/jenkins/workspace/yht-m44-pipline-web1/app1.tar.gz 10.0.0.12:/data/tomcat/tomcat_appdir/'
}
}


stage('代码升级'){
steps {
sh 'ssh 10.0.0.12 "rm -rf /data/tomcat/tomcat_webapps/myapp/* && cd /data/tomcat/tomcat_appdir && tar -xvf app1.tar.gz -C /data/tomcat/tomcat_webapps/myapp"'
}
}

stage('启动服务'){
agent { label 'jenkins-node2' }
steps {
sh 'ssh 10.0.0.12 "systemctl start tomcat.service"'
}
}

}
}

Jenkins实战项目

线上巡检

主要介绍生产环境常用的一些小案例以供学习,由于每周都需要对线上的服务器进行巡检,最基础的就是检测服务器的健康状态,脚本写好以后还需要每次去指定目录执行,所以可以直接使用Jenkins 每周巡检的时候点一下即可,另外可以结合邮件服务对其邮件告警这样更加直观

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Jenkins-web创建项目
名称:check server status
描述:⭐⭐⭐ 检测线上环境国内和国外服务器是否开启 firewalld,filebeat,zabbix-agent ⭐⭐⭐
脚本执行大概需要三分钟左右请耐心等待

- 构建选择化参数
This project is parameterized:勾选(Choice Parameter)
名称:Server
选项:
ALL
China
US
描述:
检测服务器状态,默认国内和国外一起巡检

构建:选择shell
以下是Jenkins-web里面配置的shell脚本,具体语法可以参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
check_CN () {
bash /home/hongtao.yang/inspection_server/check_prd_servers.sh
bash /home/hongtao.yang/inspection_server/output_log.sh
}

check_US () {
SSH_JMS="ssh -p22022 -i /data/ansible/.ssh/ansible_rsa 104.250.136.171"
${SSH_JMS} "/home/hongtao.yang/inspection_server/check_usprd_servers.sh"
${SSH_JMS} "/home/hongtao.yang/inspection_server/output_log.sh"
}

check_service () {
if [ "${Server}" == "ALL" ];then
check_CN
check_US
elif [ "${Server}" == "China" ];then
check_CN
elif [ "${Server}" == "US" ];then
check_US
fi
}
check_service

Jenkins服务器编写巡检脚本

由于web界面脚本写太多会显得臃肿,所以巡检脚本我直接写到Jenkins服务器上面,在Jenkins只做一些基础判断,由于还有一个国外的机房,巡检脚本是一样的这里就不在写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# 脚本说明,先解释一下每个脚本的作用,我们需要检测 filewalld 、zabbix-agent、filebeat的状态
check_ip #写巡检的服务器列表,需要ansible进行调用
check_filebeat.yml #检测filebeat服务状态
check_firewall.yml #检测filewalld服务状态
check_zabbix-agent.yml #检测zabbix-agent服务状态
check_prd_servers.sh #调用上面三个脚本 (为什么三个脚步不进行合并,因为ansible-playbook具有幂等性,如果第一次执行失败,最后的所有服务都会表示失败)
output_log.sh # 最后输出直观的结果展示


[root@cnsh-env-center-c-0-253 inspection_server]# cat check_ip |head
#### 这里只是写了一小部分,具体根据自己环境 ####
[slb]
10.10.10.44 ansible_ssh_user=root ansible_ssh_port=20000 ansible_ssh_private_key_file=/data/ansible/.ssh/ansible_rsa
10.10.10.45 ansible_ssh_user=root ansible_ssh_port=20000 ansible_ssh_private_key_file=/data/ansible/.ssh/ansible_rsa
10.10.10.134 ansible_ssh_user=root ansible_ssh_port=20000 ansible_ssh_private_key_file=/data/ansible/.ssh/ansible_rsa
10.10.10.144 ansible_ssh_user=root ansible_ssh_port=20000 ansible_ssh_private_key_file=/data/ansible/.ssh/ansible_rsa

###### check_filebeat.yml
[root@cnsh-env-center-c-0-253 inspection_server]# cat check_filebeat.yml
---
- hosts: all
gather_facts: no
tasks:
- name: ' ###### 国内服务器 查看filebeat是否开启 ######'
shell: systemctl status filebeat > /dev/null && echo -e "filebeat已开启"
###### check_firewall.yml
[root@cnsh-env-center-c-0-253 inspection_server]# cat check_firewall.yml
---
- hosts: all
gather_facts: no
tasks:
- name: ' ###### 国内服务器 查看防火墙是否开启 ######'
shell: systemctl status firewalld > /dev/null && echo -e "firewalld已开启"
###### check_zabbix-agent.yml
[root@cnsh-env-center-c-0-253 inspection_server]# cat check_zabbix-agent.yml
---
- hosts: all
gather_facts: no
tasks:
- name: ' ###### 国内服务器 查看zabbix-agent是否开启 ######'
shell: systemctl status zabbix-agent && echo -e "zabbbix-agent已开启"
###### check_prd_servers.sh
[root@cnsh-env-center-c-0-253 inspection_server]# cat check_prd_servers.sh
#!/bin/bash
Log=/home/hongtao.yang/inspection_server/log
file=/home/hongtao.yang/inspection_server
check_firewalld () {
ansible-playbook ${file}/check_firewall.yml -i ${file}/check_ip -l all > ${Log}/filewalld.log
}

check_filebeat () {
ansible-playbook ${file}/check_filebeat.yml -i ${file}/check_ip -l all > ${Log}/filebeat.log
}

check_zabbix-agent () {
ansible-playbook ${file}/check_zabbix-agent.yml -i ${file}/check_ip -l all > ${Log}/zabbix-agent.log
}

main () {
check_firewalld
check_filebeat
check_zabbix-agent
}
main
###### output_log.sh
[root@cnsh-env-center-c-0-253 inspection_server]# cat output_log.sh
#!/bin/bash
Log=/home/hongtao.yang/inspection_server/log

echo "⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐ 开始检测国内线上环境服务状态 ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐"
filewalld_log () {
Fail_IP=`cat ${Log}/filewalld.log |grep "^fatal"|awk '{print $2}'|egrep -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"`
#Success_IP=`cat ${Log}/filewalld.log |grep "^changed" |awk '{print $2}'|egrep -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"`
#echo "✅✅✅✅ 已开启的防火墙 ✅✅✅✅ "
#echo "${Success_IP}"
if [ -z "${Fail_IP}" ];then
echo "✅✅✅✅ 防火墙已全部开启 ✅✅✅✅ "
else
echo "❌❌❌❌ 未开启的防火墙_IP ❌❌❌❌"
echo "${Fail_IP}"
fi
}

filebeat_log () {
Fail_IP=`cat ${Log}/filebeat.log |grep "^fatal"|awk '{print $2}'|egrep -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"`
if [ -z "${Fail_IP}" ];then
echo "✅✅✅✅ filebeat已全部开启 ✅✅✅✅ "
else
echo "❌❌❌❌ 未开启的filebeat_IP ❌❌❌❌"
echo "${Fail_IP}"
fi
}

zabbix-agent_log () {
Fail_IP=`cat ${Log}/zabbix-agent.log |grep "^fatal"|awk '{print $2}'|egrep -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"`
if [ -z "${Fail_IP}" ];then
echo "✅✅✅✅ zabbix-agent已全部开启 ✅✅✅✅ "
else
echo "❌❌❌❌ 未开启的zabbix-agent_IP ❌❌❌❌"
echo "${Fail_IP}"
fi
}

main () {
filewalld_log
filebeat_log
zabbix-agent_log
}
main

最终实现如下图

线上发布流程

简单介绍一下我们公司的发布流程。

我们公司的发布软件使用的是Jenkins,代码仓库是使用的gitlab,首先我们的开发人员会将写好的代码提交的代码仓库里面,然后我在Jenkins服务器上调用maven进行编译,最终打包成为一个jar包,然后我们有UAT环境和prd环境,首先我会在UAT环境里对将要上线的服务进行发布测试,如果没有问题我在prd环境进行发布。 大致流程是 (编译打包–>jar包拷贝至远程服务器—>对旧的包进行备份(方便回滚)—> 停止服务—> 启动服务—->查看是否发布成功),最后没问题以后在对开发环境进行发布,流程基本一样

开发环境的话我们使用的有haproxy,首先我们会在haproxy上面停止一台到两台服务,然后在对其升级,升级完成后在放到haproxy通过一定的调度算法让用户进行访问,如果没问题在把剩下的几台服务器分批进行升级

发布脚本模板:

由于我们项目比较多,如果每个项目都写一个脚本非常耗费时间,后来想到我们每个项目以及启动路径都固定在同一个目录,然后通过Jenkins的内置变量可以调用,比如 ${JOB_NAME} 代表项目名称,这个时候我们在创建Jenkins的时候就可以以jar包前缀为我们的项目名称,最终实现所有项目调用一个脚本,如需修改就可以只修改一个脚本即可,大大减低认为失误率

  • 首先在Jenkins-web界面创建任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    # General
    - 描述: *** 业务!
    - 参数化构建
    Git 参数
    名称:Git_Branch
    描述:请选择git分支,默认master分支。
    --------------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    参数类型:分支
    默认值:origin/master

    在增加文本参数:
    名称:Host_list
    默认值:0.0.0.0
    描述:⬆️⬆️⬆️请选择发布的IP地址、如需多个IP地址请换行、下面是测试环境IP地址⬆️⬆️⬆️
    10.77.77.106
    10.77.77.112
    203.0.113.52
    # 源码管理
    - Git:
    http://gitlab.yanghongtao.com/java/yingqi-payment.git
    Credentials: 选择Jenkins的秘钥凭证
    Branches to build
    指定分支(为空时代表any)
    ${Git_Branch}
    源码库浏览器:自动
    # 构建触发器 :自定义
    # 构建环境 :自定义
    # 构建
    - 调用顶层Maven 目标
    maven版本:maven3-5-4
    目标:clean -U install -Dmaven.test.skip=true
    - 执行shell 下面代码可以自行优化
    #!/bin/bash
    Host_list=$(echo $Host_list | tr " " ",")
    echo "jar包处理!!!"
    Date=$(date "+%Y%m%d%H%M")
    cd ${WORKSPACE}
    Jar=$(find . -name ${JOB_NAME}.jar)
    if [ ! -d "/data/project/${JOB_NAME}/" ];then
    mkdir /data/project/${JOB_NAME}/
    else
    echo "=========================== Directory already exists! ==========================="
    fi
    cp $Jar /data/project/${JOB_NAME}/
    cp -r /data/project/${JOB_NAME}/${JOB_NAME}.jar /data/project/${JOB_NAME}/${JOB_NAME}.jar_${Date}.
    ls -lt /data/project/${JOB_NAME}/${JOB_NAME}.jar_*|sed -n '6,$p'|awk '{print $NF}'|xargs rm -rf
    #mv /data/project/${JOB_NAME}/${JOB_NAME}.jar /data/project/${JOB_NAME}/



    deploy () {
    ansible-playbook -i ${Host_list}, /data/ansible/playbook/release-uat-general-template.yml -e ansiblehosts=all -e ansible_ssh_port=20000 -e ansible_ssh_private_key_file=/root/.ssh/ansible_dev -e JOB_NAME=${JOB_NAME}
    }

    deploy
    # 构建后操作 :自定义,可以增加邮件告警,钉钉告警等等。

    ansible-playbook脚本

    最终根据自己环境需求去调试脚本,实现多个项目共用一个脚本进行发布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@cnsh-env-jenkins-c-161 playbook]# cat release-uat-general-template.yml
---
- hosts: "{{ ansiblehosts }}"
vars:
# JOB_NAME: "{{ JOB_NAME }}"
R_file: /opt/deploy/service/{{ JOB_NAME }}
Filebeat_path: /data/project/filebeat/filebeat.yml
timestamp: "{{lookup('pipe', 'date +%Y%m%d%H%M%S')}}"
tasks:
- name: Check service {{ JOB_NAME }}whether the folder exists
file: path=/opt/deploy/service/{{ JOB_NAME }} state=directory
- name: Stop {{ JOB_NAME }} Service
shell: cd {{ R_file }} && sh service.sh stop
ignore_errors: yes
- name: Copy {{ JOB_NAME }} Start Service file
copy: src=/data/ansible/jenkinsconf/service.sh dest={{ R_file }}
# - name: Copy {{ JOB_NAME }} logback.xml file
# copy: src=/data/project/logbackconf/logback.xml dest={{ R_file }}
# - name: Copy {{ JOB_NAME }} filebeat file
# copy: src={{ Filebeat_path }} dest=/etc/filebeat/
# - name: Start filebeat Service
# service: name=filebeat state=restarted
- name: Check whether the folder exists
file: path=/opt/jar_bak/ state=directory
- name: MV {{ JOB_NAME }}.jar package
shell: mv {{ R_file }}/{{ JOB_NAME }}.jar /opt/jar_bak/{{ JOB_NAME }}.jar-{{ timestamp }}
ignore_errors: yes
- name: Copy {{ JOB_NAME }}.jar package
copy: src=/data/project/{{ JOB_NAME }}/{{ JOB_NAME }}.jar dest={{ R_file }}
- name: Start {{ JOB_NAME }} Service
shell: cd {{ R_file }} && sh service.sh start

一键部署服务

由于经常需要批量按装nginx、vsftp、Mysql、zabbix-agent、Docker等等服务

思路:web界面输入需要安装的服务器IP地址,增加选择参数

  • 选择字符串参数 名称Host_list

    请输入需要安装的服务器IP地址,多个IP需要换行
    目前仅支持在253做好免密的服务器

  • 选择参数 名称 APP 选项:Nginx、filebeat、Mysql、zabbix-agent、Docker

    描述:目前仅支持Centos系统,不支持编译安装
    ⬇️⬇️⬇️ 在下方选择需要安装的服务

  • 在web界面构建shell,参考下方说明,另外需要安装什么服务直接在脚本里面添加即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/bin/bash
Host_list=$(echo $Host_list | tr " " ",")
success=`echo "✅✅✅✅"`
failed=`echo "❌❌❌❌"`
check_host () {
if [ "${Host_list}" == "0.0.0.0" ];then
echo "${failed} Info: Invalid Argument. ${failed} " && exit 1
fi

ifip=`echo ${Host_list} | sed 's/\,/ /g'`
for i in ${ifip};do
egrep -v "^$|#" /etc/ansible/hosts |grep ${i} >/dev/null
[ $? -eq 0 ] || { echo "${failed} Info: 请联系管理员将此IP ${i} 添加至hosts列表. ${failed} " ; exit 1; }
done
}

install_nginx () {
echo ${Host_list}
ansible-playbook -i /etc/ansible/hosts -l ${Host_list}, /data/ansible/playbook/nginx/install_nginx.yml -e Host_list=all
[ $? -eq 0 ] && echo "${success} install_nginx Success ${Host_list} ${success}" || echo "${failed} install_nginx Failed !${Host_list} ${failed}"
}

install_filebeat () {
ansible-playbook -i /etc/ansible/hosts -l ${Host_list}, /data/ansible/playbook/filebeat/install_filebeat.yml -e Host_list=all
echo "${success} install_filebeat ${Host_list} ${success}"
}

install_Mysql () {
ansible-playbook -i /etc/ansible/hosts -l ${Host_list}, /data/ansible/playbook/mysql/install_mysql5.7.yml -e Host_list=all
[ $? -eq 0 ] && echo "${success} install_Mysql success ${Host_list} ${success}" || echo "${failed} install_Mysql Failed !${Host_list} ${failed}"
echo "⭐======== The Mysql password is `ssh -p20000 -i /data/ansible/.ssh/ansible_dev 203.0.113.52 "cat /var/log/mysqld.log |grep -Po '(?<=A temporary password is generated for root@localhost:).*'"` ========⭐"
}

install_zabbix-agent () {
[ $? -eq 0 ] && echo "${success} install zabbix-agent success ${Host_list} ${success}" || echo "${failed} install zabbix-agent Failed !${Host_list} ${failed}"
}


deploy_service () {
if [ "${APP}" == "Nginx" ];then
install_nginx
elif [ "${APP}" = "filebeat" ];then
install_filebeat
elif [ "${APP}" = "Mysql" ];then
install_Mysql
elif [ "${APP}" = "zabbix-agent" ];then
install_zabbix-agent
fi
}

main () {
check_host
deploy_service
}
main

另外其他脚本部署脚本比较多,我直接打成压缩包放至以下连接,可以根据需求去取,还有一些小案例可以参考