Jenkins

Jenkins自动化构建服务

简介概览:Jenkins是开源的自动化服务器。持续集成/持续交付的事实标准。数千款插件连接各种平台,支持自动化构建、部署、交付和任何类型的项目。
下面开始部署 Jenkins,开启一台虚拟机,192.168.2.2

1. 安装 JDKMaven

#添加hosts解析文件
[root@jenkins ~]# cat <<END>> /etc/hosts
192.168.2.1 gitlab.lemon.com
192.168.2.2 jenkins.lemon.com
192.168.2.3 lb.lemon.com
END
[root@jenkins ~]# tar xf jdk-8u181-linux-x64.tar.gz 
[root@jenkins ~]# tar xf apache-maven-3.5.4-bin.tar.gz
[root@jenkins ~]# mv jdk1.8.0_181 /usr/local/java
[root@jenkins ~]# mv apache-maven-3.5.4 /usr/local/maven
[root@jenkins ~]# vi /etc/profile
export JAVA_HOME=/usr/local/java
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH
export MAVEN_HOME=/usr/local/maven
export PATH=$PATH:$MAVEN_HOME/bin
[root@jenkins ~]# source /etc/profile

[root@jenkins ~]# java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode) 

[root@jenkins ~]# mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:14+08:00)
Maven home: /usr/local/maven
Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: /usr/local/java/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-693.el7.x86_64", arch: "amd64", family: "unix"

#将maven的下载源换成国内的
[root@jenkins ~]# vim /usr/local/maven/conf/settings.xml +159
#在159行的上面添加以下内容
    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun maven</name>
      <url>https://maven.aliyun.com/repository/public </url>
    </mirror>
:wq!

2. 下载 jenkins-rpm 包并安装

//安装jenkins
[root@jenkins ~]# yum -y install jenkins-2.233-1.1.noarch.rpm

//修改jenkins配置文件
[root@jenkins ~]# vim /etc/sysconfig/jenkins
19 JENKINS_JAVA_CMD="/usr/local/java/bin/java"
29 JENKINS_USER="root"                          #这里为了方便,使用root用户运行jenkins
65 JENKINS_LISTEN_ADDRESS="192.168.2.2"

//启动jenkins
[root@jenkins ~]# systemctl start jenkins
[root@jenkins ~]# netstat -anptu|grep "8080"
tcp6   0   0   192.168.2.2:8080   :::*   LISTEN   67706/java

3. jenkins 的目录介绍

[root@gitlab ~]# rpm -ql jenkins
/etc/init.d/jenkins             #jenkins的启动文件
/etc/logrotate.d/jenkins        #记载Jenkins日至位置的文件
/etc/sysconfig/jenkins          #jenkins的配置文件
/usr/lib/jenkins                #jenkins的war包,升级就是在这做的 
/usr/lib/jenkins/jenkins.war    #jenkins的程序war包
/usr/sbin/rcjenkins             #jenkins的为二进制文件
/var/cache/jenkins              #jenkins的程序文件,运行程序解压出来的
/var/lib/jenkins                #jenkins的主目录
/var/log/jenkins                #jenkins的日志文件
/var/lib/jenkins/workspace      #拉取代码的存放路径
/var/lib/jenkins/plugins/       #这个目录下是我们安装所有的插件
/var/lib/jenkins/secrets/initialAdminPassword       #管理员密码文件

4. 跳过 jenkins 插件安装

[root@jenkins ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
3b99cdf79df747e494484426efb8bd1c         #管理员密码

  • 修改admin用户密码

5. 更换jenkins插件下载源

  • 完事之后将网页关掉并down掉 jenkins,替换完官方的 json 文件之后在启动。

  • 注:系统重启后,default.json 文件会还原,所以只要系统重启就执行下面这个命令

[root@jenkins ~]# systemctl stop jenkins
[root@jenkins ~]# cd /var/lib/jenkins/updates/
[root@jenkins updates]# sed -i 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json && sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
[root@jenkins updates]# systemctl start jenkins
[root@jenkins updates]# netstat -anptu|grep "java"
tcp6       0      0 192.168.2.2:8080      :::*       LISTEN      11591/java

6.离线安装 jenkins 插件

[root@jenkins ~]# systemctl stop jenkins
[root@jenkins ~]# rm -rf /var/lib/jenkins/plugins/
[root@jenkins ~]# tar xf jenkins-2.233_plugins.tar.gz -C /var/lib/jenkins/
[root@jenkins ~]# chown -R jenkins:jenkins /var/lib/jenkins/plugins/
[root@jenkins ~]# systemctl start jenkins
  • jenkins 插件安装完成

Jenkins 集成 Gitlab(持续集成)

整体思路:

1. 在 gitlab 上创建项目并将代码推送上去

  • 使用pm用户基于 java 组创建 monitor项目

  • 使用 dev1 或者 dev2 开发用户将monitor代码推送至此项目中
[root@dev1 ~]# unzip monitor_html.zip                #解压我本地的项目代码
[root@dev1 ~]# ll
总用量 13688
drwxr-xr-x 9 root root     4096 5月  20 08:57 monitor
-rw-r--r-- 1 root root 14008331 5月  20 08:59 monitor_html.zip
[root@dev1 ~]# cd monitor                            #进入解压后的代码目录中
[root@dev1 monitor]# git init                        #初始化monitor目录
重新初始化现存的 Git 版本库于 /root/monitor/.git/
[root@dev1 monitor]# git add .                       #加入到暂存区
[root@dev1 monitor]# git status                      #查看暂存区状态
[root@dev1 monitor]# git commit -m "NOW 1"           #提交至本地仓库
[master 9c1c324] NOW 1
 110 files changed, 65709 insertions(+), 65709 deletions(-)
 
[root@dev1 monitor]# git remote add origin git@gitlab.lemon.com:java/monitor.git   #添加远程仓库
[root@dev1 monitor]# git remote -v                      #查看远程仓库(ssh协议的)
origin	git@gitlab.lemon.com:java/monitor.git (fetch)
origin	git@gitlab.lemon.com:java/monitor.git (push)
[root@dev1 monitor]# git push -u origin master          #推送代码至远程仓库
Counting objects: 564, done.
Compressing objects: 100% (497/497), done.
Writing objects: 100% (564/564), 9.03 MiB | 0 bytes/s, done.
Total 564 (delta 159), reused 363 (delta 54)
remote: Resolving deltas: 100% (159/159), done.
To git@gitlab.lemon.com:java/monitor.git
 * [new branch]      master -> master
分支 master 设置为跟踪来自 origin 的远程分支 master。
  • 查看是否推送至monitor项目中

2. 下载集成 gitlab 的插件

  • 这些插件我都已经在上面安装好了,所以这一步可以跳过

3. 在 jenkins 里配置实现持续集成

进入主页--创建一个新任务

输入项目名称 freestyle-monitor---构建一个自由风格的软件项目---确认

General--填写项目描述--Discard old builds

源码管理--Git--添加 gitlab 项目的URL--授权认证

//在jenkins服务器上生成私钥,马上就用
[root@jenkins ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:cYOfmb21FU4/mqzakUqAqwFPW1G7Mz2hmLti6eDfia8 root@jenkins
The key's randomart image is:
+---[RSA 2048]----+
|       .         |
|      . ..       |
|     . .o.o    o |
|      = ++.*  o o|
| . . = *So= . .oo|
|  + o o + . oooo.|
| . +.o   . o.+.  |
|. .+= o . o o    |
| .+E+=   o.o     |
+----[SHA256]-----+

[root@jenkins ~]# cat .ssh/id_rsa.pub      #公钥
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDj13aUUWlOxpLv/tGDHF7v1dBUrs0wVirnxKXbFwetXUECnqGyd9UOHSrkkEiKW512ommbXDziX+TEa6S5QULZCrS0dM3tN4WCLyouhPbPzjiOA+HHJj0XpgXxnSz6MobeAVPByS0l9LhJkISIxl+gmz+e/VvMcSOmwOXHm70kIngA59X6xy5t2xeb0vwkQXGmoA5bQdQx32mugDT4HA1IBpoRRV3h6cfjhSW85wjdgWRGWFIRFLfLKCyBPBaGxGY7XJB9Fpu3SaMfBb85EYBk///L1Ha8dEKLkmiECrDo6SgQHWoF7GVcyzATku80NHR6boZFC4belELS2rPmTfe9 root@jenkins

[root@jenkins ~]# cat .ssh/id_rsa          #私钥
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA49d2lFFpTsaS7/7Rgxxe79XQVK7NMFYq58Sl2xcHrV1BAp6h
snfVDh0q5JBIiluddqJpm1w84l/kxGukuUFC2Qq0tHTN7TeFgi8qLoT2z844jgPh
xyY9F6YF8Z0s+jKG3gFTwcktJfS4SZCEiMZfoJs/nv1bzHEjpsDlx5u9JCJ4AOfV
+scubdsXm9L8JEFxpqAOW0HUMd9proA0+BwNSAaaEUVd4enH44UlvOcI3YFkRlhS
ERS3yygsgTwWhsRmO1yQfRabt0mjHwW/ORGAZP//y9R2vHRCi5JohAqw6OkoEB1q
BexlXMswE5LvNDR0em6GRQuG3pRC0tqz5k33vQIDAQABAoIBAQDcu22CG60uSGsq
X3CS2PWQ3VBL+l2HqrM+fuE/9HvXlTTaWNzGjhm25sMbVD0y7bcLrCUsApxppAV5
1d9sKrGcnCadfVvTqaqKiS8QiniismNQEqq1yXH+azXu8hsU+cZ3ZknCwCghUYkI
nB4KdEVIz58/ZK1+z01+y/rQ+yyux3GQQq7ZM+gQDhAmrgma+r/lov0itCM86Eo5
PN9ZQ5I7m23ACQsZNjZOQ9yxIqjsYYAo+iJuT96ZUlOkPnzTwQ2mtI1SaMgPUZJb
gjb4A3FaU0rVru+bsQX93mZEEWAQqBzr1JkE8gd4P5VCMmjxlNxQwzThKMaGsvU9
ijqXDZaBAoGBAPzZ7y/UDLd5cMgljPtGG3buk9vWKmL32DTRShj2OdrXJO49QGy3
uMUi9qQ3j8ShmvclKdQ3LXofEFruwBmkP0F/oEYJ5/MEXkgi1+dE8RgjIg6v7+Ww
sAhFJrhnK+rGbVSABJ5O9bb9qmEKgZq+2W1/4Y6RF/+DSSN/jxXllP3JAoGBAOat
zO34RMHemgQoRQCW6NOTHnWOpn1ubhMR21rNHfgwmsyaPMv/LDkBQObyKMLb4VgC
D7jD2NW9DlTcKiZjqmjgDALxR1tt3mXZ2znTWEDI774Tc2QebJCpRIdQqKG1nm5H
d131E5CS72cNCVmacVc9xi7kO107e6bc+34g8hRVAoGAe8/PcpEYBQN/OVJB3Yyv
yCX82unc6YdJJFvTN7PiEonE+K+fi1zPKiD7ut/GE1e6xQg6mkLGjwUFAjHkeOnX
W6A9/+272WCrNhFxvToiAFq7w4tdIhDJsdMCqctDUvwE7xqcqFQrt4Yw1sHJQtfv
KdIzxZbAtIo51xsQGn3H3hkCgYAZhpnqq1JQcaVxWFNqYUiaQOlZ8NMThijAC3XO
cmwijp5Sja60lCP8mtrns1w3U8V3y6KZu3I/FJCFa2duoBC3UjOCD9jpkRrPAnBz
0aMuaA2/Zr+aEJPK3jArGQ3P9xz07wuSZhAoK1o6eQLT23c3RCqt/atkAbUJHeLm
bhbbkQKBgFytaJklEVRibl0iiDYZfkzIhD/v1I43JyUmuv+VuTwGDYFx4b0jBOAm
EeKnpRzyvmSbG52XHcJeaGt0iLaZVnpby/y04aowJC+2sQ7fGKE61PYy9WDasHBr
uRuMiY5YzMC9LsGeSs4gF/oVt6d80M2itaqf+MSRZpT3VVpqGXw9
-----END RSA PRIVATE KEY-----
  • jenkins 服务器上的公钥放到 gitlab 的 pm 账户上用来拉取代码

  • 验证 jenkins 服务器能否克隆这个项目
[root@jenkins ~]# git clone git@gitlab.lemon.com:java/monitor.git
正克隆到 'monitor'...
remote: Enumerating objects: 564, done.
remote: Counting objects: 100% (564/564), done.
remote: Compressing objects: 100% (392/392), done.
remote: Total 564 (delta 159), reused 564 (delta 159)
接收对象中: 100% (564/564), 9.03 MiB | 0 bytes/s, done.
处理 delta 中: 100% (159/159), done.

[root@jenkins ~]# rm -rf monitor/

//很明显,jenkins服务器已经能够克隆gitlab上的项目了
  • 再回到 jenkins 的web页面上将他自己的私钥放到 jenkins 凭据上

Credentials—选择 root

4. 点击立即构建

5. 构建成功后点击 控制台输出 和 工作区

控制台输出,SUCCESS则构建成功

  • 点击工作区

  • 查看 jenkins 服务器上的 /var/lib/jenkins/workspace/ 目录是否下载了代码

可以看到,在工作目录下边有部署的代码;上面只是完成了第一步,也就是持续集成,下面我们先开始搭建集群,在修改此任务的配置(持续集成 + 持续部署)。

搭建web集群

打开三台虚拟机

IP host_name role
192.168.2.3 LB nginx充当负载均衡
192.168.2.4 web01 nginx充当web服务
192.168.2.5 Web02 nginx充当web服务

1. 在这三台节点上都安装nginx(操作相同)

#添加hosts解析文件
cat <<END>> /etc/hosts
192.168.2.1 gitlab.lemon.com
192.168.2.2 jenkins.lemon.com
192.168.2.3 lb.lemon.com
END

wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo

vim /etc/yum.repos.d/nginx.repo 
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

yum clean all
yum makecache

yum -y install nginx

#修改这三台的主配置文件(配置相同)
vim /etc/nginx/nginx.conf
user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  0;
    include /etc/nginx/conf.d/*.conf;
}

2. 配置 lb 主机

[root@lb ~]# cd /etc/nginx/conf.d/
[root@lb conf.d]# gzip default.conf              #将默认的虚拟主机文件注释掉

[root@lb conf.d]# vim proxy_lb.lemon.com.conf
upstream lb {
        server 192.168.2.4:80;
        server 192.168.2.5:80;
}

server {
        listen 80;
        server_name lb.lemon.com;
        root /code;
        location / {
                proxy_pass http://lb;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forward-For $remote_addr;
        }
}
:wq!

[root@lb conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

[root@lb conf.d]# systemctl start nginx;systemctl enable nginx
[root@lb conf.d]# netstat -anptu|grep 80
tcp        0      0 0.0.0.0:80     0.0.0.0:*     LISTEN      16216/nginx: master

3. 配置 web01 主机

[root@web01 ~]# cd /etc/nginx/conf.d/
[root@web01 conf.d]# gzip default.conf
[root@web01 conf.d]# vim nginx_01.conf
server {
        listen 80;
        server_name localhost;
        root /code/web;

        location / {
                index index.html;
        }
}
:wq!

[root@web01 conf.d]# mkdir -p /code/web

[root@web01 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

[root@web01 conf.d]# systemctl start nginx;systemctl enable nginx
[root@web01 conf.d]# netstat -anptu|grep 80
tcp        0      0 0.0.0.0:80        0.0.0.0:*     LISTEN      16171/nginx: master

4. 配置 web02 主机

[root@web02 ~]# cd /etc/nginx/conf.d/
[root@web02 conf.d]# gzip default.conf
[root@web02 conf.d]# vim nginx_02.conf
server {
        listen 80;
        server_name localhost;
        root /code/web;

        location / {
                index index.html;
        }
}
:wq!

[root@web02 conf.d]# mkdir -p /code/web

[root@web02 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

[root@web02 conf.d]# systemctl start nginx;systemctl enable nginx
[root@web02 conf.d]# netstat -anptu|grep 80
tcp        0      0 0.0.0.0:80        0.0.0.0:*     LISTEN      16171/nginx: master

5. 将 jenkins 服务器上的代码拷贝到两台web节点上

[root@jenkins ~]# cd /var/lib/jenkins/workspace/freestyle-monitor
[root@jenkins freestyle-monitor]# scp -r ./* root@192.168.2.4:/code/web
[root@jenkins freestyle-monitor]# scp -r ./* root@192.168.2.5:/code/web

6. 查看并访问 http://lb.lemon.com/

  • 思考一个问题:
    • 如果我更新了一次代码,是不是还得要再来一次上面的操作步骤?
    • 是的,所以就要用到下面 jenkins 的持续集成 + 持续部署 功能了。

配置freestyle-monitor任务 持续集成 + 持续部署

1. 将手动部署代码的操作编写成shell脚本,在由 jenkins 调度将其代码推送至web集群

[root@jenkins ~]# mkdir /jekins_scripts                   #创建jenkins脚本存放目录
[root@jenkins ~]# mkdir /jekins_code_tar                  #创建jenkins代码打包存放目录
[root@jenkins ~]# vim /jekins_scripts/monitor_html.sh  #创建jenkins任务的相关脚本存放目录
#!/bin/bash

#时间戳
DATE=`date +%Y-%m-%d-%H-%M-%S`

#jenkins的项目目录,这里也可以直接用jenkins自身的 WORKSPACE 变量
JENKINS_DIR="/var/lib/jenkins/workspace/freestyle-monitor"

#web集群的站点存放目录
WEB_DIR="/code"

#web集群IP地址
WEB_IP="192.168.2.4 192.168.2.5"

#进入到jenkins项目目录,并进行代码打包至/jekins_code_tar目录下,在将内容通过scp至web集群 并 进行新的代码上线
env_build() {
       cd ${JENKINS_DIR} && tar zcf /jekins_code_tar/web-${DATE}.tar.gz ./*
       for hosts in $WEB_IP;do
            ssh root@${hosts} "if [ ! -d /web_backup ]; then mkdir /web_backup ; fi"
            scp /jekins_code_tar/web-${DATE}.tar.gz root@${hosts}:/web_backup
            ssh root@${hosts} "rm -rf ${WEB_DIR}/* && mkdir -p ${WEB_DIR}/web-${DATE}"
            ssh root@${hosts} "tar xf /web_backup/web-${DATE}.tar.gz -C ${WEB_DIR}/web-${DATE}"
            ssh root@${hosts} "ln  -s ${WEB_DIR}/web-${DATE} ${WEB_DIR}/web"
       done
}

#调用env_build函数
env_build

[root@jenkins ~]# chmod -R +x /jekins_scripts

#配置web节点免登
[root@jenkins ~]# ssh-copy-id root@192.168.2.4
[root@jenkins ~]# ssh-copy-id root@192.168.2.5

2. 配置 freestyle-monitor 项目

  • 构建 -- Execute shell

3. 构建此项目

  • 在构建之前先将web集群的页面和 jenkins 之前拉取下的代码全都删除,以便验证
#jenkins服务器上
[root@jenkins ~]# ll /var/lib/jenkins/workspace/
总用量 0
[root@jenkins ~]# ll /jekins_code_tar/
总用量 0

#web01服务器上
[root@web01 ~]# ll /code/
总用量 0
[root@web01 ~]# ll /web_backup
ls: 无法访问/web_backup: 没有那个文件或目录

#web02服务器上
[root@web02 ~]# ll /code/
总用量 0
[root@web01 ~]# ll /web_backup
ls: 无法访问/web_backup: 没有那个文件或目录
  • 现在访问lb.lemon.com就会报错

4. 模拟开发更新代码推送至远程仓库

[root@dev1 ~]# cd monitor
[root@dev1 monitor]# vim index.html +43
<a class="logo pull-left" href="index.html" style="width: 233px">lemon管理平台</a>
:wq!
[root@dev1 monitor]# git add .
[root@dev1 monitor]# git commit -m "test"
[master 6cc63b2] test
 1 file changed, 1 insertion(+), 1 deletion(-)
[root@dev1 monitor]# git push origin master
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 282 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@gitlab.lemon.com:java/monitor.git
   481be52..6cc63b2  master -> master

5. jenkins构建项目

6. 然后在访问一下lb.lemon.com

7. 查看对应的目录

#jenkins服务器上
[root@jenkins ~]# ll  /var/lib/jenkins/workspace/
总用量 4
drwxr-xr-x 9 root root 4096 5月  22 00:50 freestyle-monitor
drwxr-xr-x 2 root root    6 5月  22 00:50 freestyle-monitor@tmp
[root@jenkins ~]# ll /jekins_code_tar/
总用量 4552
-rw-r--r-- 1 root root 4659825 5月  22 00:50 web-2020-05-22-00-50-30.tar.gz

#web01服务器上
[root@web01 ~]# ll /code/
总用量 4
lrwxrwxrwx 1 root root   29 5月  22 00:50 web -> /code/web-2020-05-22-00-50-30
drwxr-xr-x 8 root root 4096 5月  22 00:50 web-2020-05-22-00-50-30
[root@web01 ~]# ll /web_backup
总用量 4552
-rw-r--r-- 1 root root 4659825 5月  22 00:50 web-2020-05-22-00-50-30.tar.gz

#web02服务器上
[root@web02 ~]# ll /code/
总用量 4
lrwxrwxrwx 1 root root   29 5月  22 00:50 web -> /code/web-2020-05-22-00-50-30
drwxr-xr-x 8 root root 4096 5月  22 00:50 web-2020-05-22-00-50-30
[root@web02 ~]# ll /web_backup
总用量 4552
-rw-r--r-- 1 root root 4659825 5月  22 00:50 web-2020-05-22-00-50-30.tar.gz

8. 注意事项:

1. Jenkins的启动用户得是root,不然会报错!因为ssh免登用的是root用户做的

2. 如果做了上面的步骤后还是报错,就执行命令删除rm -rf known_hosts。

3. 以上就是一个简单的不能再简单的静态页面 持续集成 + 持续部署项目

9. 现在这个项目的配置还存在一些问题

  • 怎么指定要构建的版本?

    • 答:需要定义 参数化构建过程的(Choice Parameter 和 Git Parameter)
  • 怎么不让已经构建成功后项目 构建?

    • 答:使用 jenkins 自带的两个变量进行判断

10. 解决上面两个存在的问题

  • 由于之前的上线方式是直接获取最新代码,它会对后期版本回退的困难。
  • 如果采用tag方式,比如第一次上线 v1.1 、第二次上线 v1.2 ,如果上线 v1.2 出现问题后,我们还可以使用tag快速回退至上一个版本的 v1.1 。

11. 实现tag版本上线的思路

  1. 开发如果需要发布新版本上线,必须将当前的版本打上一个标签。
  2. 配置jenkins任务的参数化构建过程;Choice Parameter 和 Git Parameter
  3. jenkins需要让其脚本支持传参,比如:用户传递 v1.1 则拉取项目的 v1.1 标签

12. jenkins配置tag版本的部署

  • 首先安装 Git Parameter插件,然后配置jenkins参数化构建,再让用户构建时选择对应的tag版本。

  • 添加 参数化构建过程(This project is parameterized)---> Choice Parameter ---> Git Parameter

  • 配置 Choice Parameter 选项参数

  • 配置 Git Parameter 并 修改源码管理的 Git分支参数

  • 修改jenkins上的 monitor_html.sh 脚本
[root@jenkins ~]# vim /jekins_scripts/monitor_html.sh
#!/bin/bash

#时间戳
DATE=`date +%Y-%m-%d-%H-%M-%S`
DATE_TAG=${DATE}-${GIT_VERSION}

#jenkins的项目目录,这里也可以直接用jenkins自身的 WORKSPACE 变量
JENKINS_DIR="/var/lib/jenkins/workspace/freestyle-monitor"

#web集群的站点存放目录
WEB_DIR="/code"

#web集群IP地址
WEB_IP="192.168.2.4 192.168.2.5"

#进入到jenkins项目目录,并进行代码打包至/jekins_code_tar目录下,在将内容通过scp至web集群 并 进行新的代码上线
env_build() {
       cd ${JENKINS_DIR} && tar zcf /jekins_code_tar/web-${DATE_TAG}.tar.gz ./*
       for hosts in $WEB_IP;do
            ssh root@${hosts} "if [ ! -d /web_backup ]; then mkdir /web_backup ; fi"
            scp /jekins_code_tar/web-${DATE_TAG}.tar.gz root@${hosts}:/web_backup
            ssh root@${hosts} "rm -rf ${WEB_DIR}/* && mkdir -p ${WEB_DIR}/web-${DATE_TAG}"
            ssh root@${hosts} "tar xf /web_backup/web-${DATE_TAG}.tar.gz -C ${WEB_DIR}/web-${DATE_TAG}"
            ssh root@${hosts} "ln  -s ${WEB_DIR}/web-${DATE_TAG} ${WEB_DIR}/web"
       done
}

#jenkins这边保留最近提交的五个代码tar包,其余的全部删掉,web那里只保留三个tar包
env_clear() {
       #-----------清除web节点的tar包(只保留三个)------
       for hosts in $WEB_IP;do
            ssh root@${hosts} "bash -x /opt/clear_latest.sh"
       done
       #-----------清除jenkins节点的tar包(只保留五个)--
       ReservedNum=5
       FileDir=/jekins_code_tar
       FileNum=$(ls -l $FileDir|grep ^- |wc -l)
       while(( $FileNum > $ReservedNum));do
       OldFile=$(ls -rt $FileDir| head -1)
            rm -rf $FileDir/$OldFile
            let "FileNum--"
       done       
}

#判断到底是调用env_build函数 还是调用evn_clear函数;其实这里的值就是根据上面的 Choice Parameter 选项而定的
if [ $BUILD_CLEAR == "build" ];then
       env_build
elif [ $BUILD_CLEAR == "clear" ];then
       env_clear
fi
  • 在web节点上的opt目录下编写 clear_latest.sh 脚本(在此只实例web01,一样的内容)
[root@dev1 ~]# vim /opt/clear_latest.sh 
#!/bin/bash
#保留文件数,这里只保留最新的前三个版本
ReservedNum=3
FileDir=/web_backup
date=$(date "+%Y%m%d-%H%M%S")

FileNum=$(ls -l $FileDir|grep ^- |wc -l)

while(( $FileNum > $ReservedNum));do
    OldFile=$(ls -rt $FileDir| head -1)
    echo  $date "Delete File:"$OldFile
    rm -rf $FileDir/$OldFile
    let "FileNum--"
done

[root@web01 ~]# chmod a+x /opt/clear_latest.sh
  • 开发更新代码,推送至远程仓库并打上标签(这里我实际上推送了三个tag标签)
[root@dev1 ~]# cd monitor
[root@dev1 monitor]# vim index.html +43
<a class="logo pull-left" href="index.html" style="width: 233px">lemon管理平台 v1.1</a>
:wq!
[root@dev1 monitor]# git add .
[root@dev1 monitor]# git commit -m "v1.1"
[root@dev1 monitor]# git push origin master
[root@dev1 monitor]# git tag -a "v1.1" -m "v1.1"
[root@dev1 monitor]# git push origin v1.1
  • 查看一下效果 并 进行构建 并查看 控制台信息

  • 访问web服务查看是否更新到我想要的版本中

  • 查看我构建的tar包有多少了,然后使用clear清除(注意:此功能在工作环境上要慎重使用!!!!)

  • 调用clear构建 --> 就是在运行脚本中的env_clear函数 ---> 查看 控制台信息

  • 与上面对比一下可以看到,这个功能也实现了

13. 解决项目重复构建 和 无法精确回滚 的问题 (可在生产环境使用)

  • 在jenkins任务中的参数化构建中的选项构建那里 在添加一个rollback的选项参数

  • 修改脚本
    • 在脚本中添加一个 env_rollabck 的函数,并在脚本中使用 Jenkins自带的 GIT_COMMITGIT_PREVIOUS_SUCCESSFUL_COMMIT 进行判断
[root@jenkins ~]# vim /jekins_scripts/monitor_html.sh
#!/bin/bash

#时间戳
DATE=`date +%Y-%m-%d-%H-%M-%S`
DATE_TAG=${DATE}-${GIT_VERSION}

#jenkins的项目目录,这里也可以直接用jenkins自身的 WORKSPACE 变量
JENKINS_DIR="/var/lib/jenkins/workspace/freestyle-monitor"

#web集群的站点存放目录
WEB_DIR="/code"

#web集群IP地址
WEB_IP="192.168.2.4 192.168.2.5"

#进入到jenkins项目目录,并进行代码打包至/jekins_code_tar目录下,在将内容通过scp至web集群 并 进行新的代码上线
env_build() {
       cd ${JENKINS_DIR} && tar zcf /jekins_code_tar/web-${DATE_TAG}.tar.gz ./*
       for hosts in $WEB_IP;do
            ssh root@${hosts} "if [ ! -d /web_backup ]; then mkdir /web_backup ; fi"
            scp /jekins_code_tar/web-${DATE_TAG}.tar.gz root@${hosts}:/web_backup
            ssh root@${hosts} "rm -rf ${WEB_DIR}/* && mkdir -p ${WEB_DIR}/web-${DATE_TAG}"
            ssh root@${hosts} "tar xf /web_backup/web-${DATE_TAG}.tar.gz -C ${WEB_DIR}/web-${DATE_TAG}"
            ssh root@${hosts} "ln  -s ${WEB_DIR}/web-${DATE_TAG} ${WEB_DIR}/web"
       done
}

#回滚函数
env_rollback() {
       ROLL_BACKUP=`ssh root@192.168.2.4 "find /web_backup -maxdepth 1 -type f -name "*${GIT_VERSION}*" "`
       for hosts in $WEB_IP;do
            ssh root@${hosts} "rm -rf ${WEB_DIR}/* && mkdir -p ${WEB_DIR}/web-${DATE_TAG}"
            ssh root@${hosts} "tar xf ${ROLL_BACKUP} -C ${WEB_DIR}/web-${DATE_TAG}"
            ssh root@${hosts} "ln  -s ${WEB_DIR}/web-${DATE_TAG} ${WEB_DIR}/web"
       done
}

#jenkins这边保留最近提交的五个代码tar包,其余的全部删掉,web那里只保留三个tar包
env_clear() {
       #-----------清除web节点的tar包(只保留三个)------
       for hosts in $WEB_IP;do
            ssh root@${hosts} "bash -x /opt/clear_latest.sh"
       done
       #-----------清除jenkins节点的tar包(只保留五个)--
       ReservedNum=5
       FileDir=/jekins_code_tar
       FileNum=$(ls -l $FileDir|grep ^- |wc -l)
       while(( $FileNum > $ReservedNum));do
       OldFile=$(ls -rt $FileDir| head -1)
            rm -rf $FileDir/$OldFile
            let "FileNum--"
       done       
}

#判断到底是调用env_build函数 还是调用evn_clear函数,并且在构建的时候会先判断一下此
#次构建的版本之前有没有构建够,如果构建过,那么将不再构建,如果没有,就构建此项目
if [ $BUILD_CLEAR == "build" ];then
       if [ ${GIT_COMMIT} == ${GIT_PREVIOUS_SUCCESSFUL_COMMIT} ];then
                echo "你已经成功构建过web-${DATE_TAG}项目了"
                echo "你可以直接使用rollback的方式进行回滚web-${DATE_TAG}项目版本"
                exit 1
       else
                env_build
       fi
elif [ $BUILD_CLEAR == "rollback" ];then
       env_rollback
elif [ $BUILD_CLEAR == "clear" ];then
       env_clear
fi
  • 开发在重新推送两个新的分支
[root@dev1 ~]# cd monitor
[root@dev1 monitor]# vim index.html +43
<a class="logo pull-left" href="index.html" style="width: 233px">lemon管理平台 v1.4 </a>
:wq!
[root@dev1 monitor]# git add .
[root@dev1 monitor]# git commit -m "v1.4"
[root@dev1 monitor]# git push origin master
[root@dev1 monitor]# git tag -a "v1.4" -m "v1.4"
[root@dev1 monitor]# git push origin v1.4

[root@dev1 monitor]# vim index.html +43
<a class="logo pull-left" href="index.html" style="width: 233px">lemon管理平台 v1.5 </a>
:wq!
[root@dev1 monitor]# git add .
[root@dev1 monitor]# git commit -m "v1.5"
[root@dev1 monitor]# git push origin master
[root@dev1 monitor]# git tag -a "v1.5" -m "v1.5"
[root@dev1 monitor]# git push origin v1.5
  • 重复构建一下v1.5的版本

  • 那比如我想在使用构建回到了v1.4的版本中,怎么才可以重新再回到v1.5版本的?
    • 答:使用我上面定义好的rollback函数会退就行了

  • 再来测试清空tar包的功能还能否使用(注意:此功能在工作环境上要慎重使用!!!!)

注意:如果此时在想回退到v1.1 和v1.3 版本的时候会失败的,因为web节点上的这两个版本包已经被被我清空了,所以 clear这个函数在公司的时候要慎重使用!!!!【最好就别写这个函数方法最好】

至此,jenkins的使用就算是基本完成了,只要上面的内容会了,那么至于java项目那块基本上和上面的操作没有太大的区别

八、GitLab + Jenkins + Sonar Qube 持续集成

1. java项目部署的基本概述

1.1 什么是 java 项目?

  • 简单来说就是用 java 编写的代码,我将其称为 java 项目

1.2 为什么java项目需要Maven编译?

  • 由于 java 编写的代码是无法直接在服务器上运行的,需要使用Maven工具进行构建打成war包后才能在服务器上运行
  • 简单理解:java 源代码就是你在菜市场的买回家的菜,你买了之后并不是直接放嘴里就吃的,而是先回到家里进行一次加工后(Maven)才吃的。

2. jenkins手动部署java项目至web集群

2.1 搭建Nginx + Tomcat + MySQL + Sonar Qube 集群

  • 这里前 nginx 和 tomcat 这两部分的机器我们就不用考虑了,因为我们在上面就已经准备好了,我们只需要重新配置一下 nginx 负载均衡并在另外两台机器上安装一下Tomcat就行了。至于 MySQL 和 Sonar Qube 的话,我这里因机器不够用了,所以就直接把 MySQL 部署到 dev1 主机上 Sonar Qube 部署到 dev2 上就行了,不会有什么影响。
  1. 修改lb的 nginx 配置文件
[root@lb ~]# vim /etc/nginx/conf.d/proxy_lb.lemon.com.conf
upstream lb {
        server 192.168.2.4:8080;
        server 192.168.2.5:8080;
}

server {
        listen 80;
        server_name lb.lemon.com;
        root /code;
        location / {
                proxy_pass http://lb;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forward-For $remote_addr;
        }
}

[root@lb ~]# systemctl restart nginx
  • 现在访问负载均衡的话会报502错误,这很正常,因为我们还没有部署tomcat

  1. 在另外两台web节点上关闭 nginx 服务 并安装启动 Tomcat
systemctl stop nginx
tar xf jdk-8u181-linux-x64.tar.gz
mv jdk1.8.0_181 /usr/local/java
cat <<END>> /etc/profile
export JAVA_HOME=/usr/local/java
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib
END
source /etc/profile
tar xf apache-tomcat-8.5.32.tar.gz
mv apache-tomcat-8.5.32 /usr/local/tomcat
/usr/local/tomcat/bin/startup.sh 
netstat -anptu|grep "8080"
tcp6       0      0 :::8080      :::*            LISTEN      1353/java
  • 在访问一下负载均衡

  • 但是看不出来是否已经负载均衡了,我们去修改两个tomcat的页面就行了
[root@web01 ~]# vim /usr/local/tomcat/webapps/ROOT/index.jsp +52
<h2>Tomcat web01-192.168.2.4</h2>
#最好重启一下tomcat

[root@web02 ~]# vim /usr/local/tomcat/webapps/ROOT/index.jsp +52
<h2>Tomcat web02-192.168.2.5</h2>
#最好重启一下tomcat
  • 再来访问

  1. 提前先在 dev1 节点上部署好 MySQL ,一会用的 Sonar Qube 的时候会使用,现在还用不上
[root@dev1 ~]# yum -y install mariadb-server
[root@dev1 ~]# systemctl start mariadb;systemctl enable mariadb
[root@dev1 ~]# mysqladmin -u root password '123123'
[root@dev1 ~]# mysql -uroot -p123123
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 5.5.65-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

MariaDB [(none)]> exit

2.2 新建一个gitlab的 hello world 项目仓库

2.3 使用git将其java代码上传到hello-world仓库

[root@dev1 hello-world]# pwd
/root/hello-world

[root@dev1 hello-world]# ll -a
总用量 16
-rw-r--r--  1 root root  700 12月 23 2018 .classpath
-rw-r--r--  1 root root 1113 12月 23 2018 pom.xml
-rw-r--r--  1 root root 1081 12月 23 2018 .project
drwxr-xr-x  2 root root  322 6月  11 16:31 .settings
drwxr-xr-x  3 root root   18 6月  11 16:31 src
drwxr-xr-x  5 root root   56 6月  11 16:31 target
-rw-r--r--  1 root root  491 12月 20 2018 time.java

[root@dev1 hello-world]# git init
初始化空的 Git 版本库于 /root/hello-world/.git/
[root@dev1 hello-world]# git add .
[root@dev1 hello-world]# git commit -m "Initial commit"
[root@dev1 hello-world]# git remote add origin git@gitlab.lemon.com:java/hello-world.git
[root@dev1 hello-world]# git push origin master
[root@dev1 hello-world]# git tag -a "v1.1" -m "v1.1"
[root@dev1 hello-world]# git push origin v1.1

2.4 在jenkins上拉取gitlab代码后手动编译成war包

  • 安装maven,由于我之前就安装过了 JDKmaven,所以这里就不用安装了,直接跳过

  • 克隆刚才上传的 java 项目 并 手动编译成war包

[root@jenkins ~]# git clone git@gitlab.lemon.com:java/hello-world.git
[root@jenkins ~]# cd hello-world/

[root@jenkins hello-world]# mvn package -D maven.test.skip=true      #-D 跳过测试用例

  • 将其编译好的 war包 scp 到web节点的对应位置下
#停止两台tomcat服务
[root@web01 ~]# /usr/local/tomcat/bin/shutdown.sh

#删除tomcat默认页面
[root@jenkins hello-world]# for i in 192.168.2.{4..5};do ssh root@$i "rm -rf /usr/local/tomcat/webapps/ROOT"; done

#将编译好的test1.war包scp至web节点上
[root@jenkins hello-world]# for i in 192.168.2.{4..5};do scp target/test1.war root@$i:/usr/local/tomcat/webapps/ROOT.war; done

#查看war包是否拷贝过去
[root@jenkins hello-world]# for i in 192.168.2.{4..5};do ssh root@$i "ls -h /usr/local/tomcat/webapps/ROOT*"; done
/usr/local/tomcat/webapps/ROOT.war
/usr/local/tomcat/webapps/ROOT.war

#启动两台tomcat服务;会自动生成一个ROOT网站目录
[root@web01 ~]# /usr/local/tomcat/bin/startup.sh
[root@web01 ~]# ll /usr/local/tomcat/webapps/
总用量 32
drwxr-x--- 14 root root  4096 6月  11 16:20 docs
drwxr-x---  6 root root    83 6月  11 16:20 examples
drwxr-x---  5 root root    87 6月  11 16:20 host-manager
drwxr-x---  5 root root   103 6月  11 16:20 manager
drwxr-x---  4 root root    54 6月  11 17:00 ROOT
-rw-r--r--  1 root root 24711 6月  11 16:59 ROOT.war
  • 访问

以上就是手动部署 java 代码的流程

posted @ 2023-05-24 15:40  ArMinLi  阅读(366)  评论(0编辑  收藏  举报