自动化部署和持续集成


自动化部署

根据企业业务需求不同,自动化部署的流程设计也各不相同,所以一个自动化流程设计不是一成不变的,要根据企业的业务不同做相应的调整。

下面以下图的自动化流程为例做运维自动化部署:

根据上图的设计流程编写自动化部署shell脚本

 环境准备:

  web-deploy:192,168.1.11(部署机)   web-node1:192.168.1.12(web服务器、jenkins服务、sonar服务)    web-node2:192.168.1.13(web服务器)

 创建统一的代码部署用户及web服务管理用户

[root@web-deploy ~]# useradd   -u  1000  www
[root@web-deploy ~]# echo  'www'  |passwd  --stdin www
[root@web-node1 ~]# useradd   -u  1000  www
[root@web-node1 ~]# echo  'www'  |passwd  --stdin www
[root@web-node2 ~]# useradd   -u  1000  www
[root@web-node2 ~]# echo  'www'  |passwd  --stdin www

 设置ssh,让部署机web-deploy用户www到web-node1、web-node2用户www远程ssh无密码登录

[www@web-deploy ~]$ ssh    -t  rsa
#将web-deploy的公钥拷贝到web-node1和web-node2上
[www@web-deploy ~]$ ssh-copy-id  192.168.1.12
[www@web-deploy ~]$ ssh-copy-id  192.168.1.13
#在web-node1和web-node2上也生成公钥和私钥以备后面要用
[www@web-node1 ~]$ ssh    -t  rsa
[www@web-node2 ~]$ ssh    -t  rsa

 通过上面无秘登录设置后,接下来开始编辑自动化部署脚本了

 创建脚本前,首先创建要部署代码用到的目录并且授予这些目录www权限

#部署机上创建的目录并授权www用户
[root@web-deploy ~]# mkdir -p  /deploy/{code,config,tar,tmp}
[root@web-deploy ~]# mkdir -p  /deploy/code/web-demo/
[root@web-deploy ~]# mkdir -p  /deploy/config/web-demo/{base,other}
[root@web-deploy ~]# chown   www.www  -R  /deploy/    
[root@web-deploy ~]# su  -  www
#web服务器创建的目录并授权www用户
[root@web-node1 ~]# mkdir /opt/webroot
[root@web-node1 ~]# chown www.www  -R  /opt/webroot/
[root@web-node1 ~]# mkdir /webroot
[root@web-node1 ~]# chown  www.www -R  /webroot/
[root@web-node1 ~]# su  - www
[www@web-node1 ~]$ mkdir  /webroot/web-demo

[root@web-node2 ~]# chown www.www  -R  /opt/webroot/
[root@web-node2 ~]# mkdir /webroot
[root@web-node2 ~]# chown  www.www -R  /webroot/
[root@web-node2 ~]# su  -  www
[www@web-node2 ~]$ mkdir  /webroot/web-demo

 在web服务器上安装httpd服务

[root@web-node1 ~]$ yum  install  httpd  -y
#修改httpd的配置文件,设置web的访问根目录
[root@web-node1 ~]# vim  /etc/httpd/conf/httpd.conf
DocumentRoot "/webroot/web-demo"
<Directory "/webroot/web-demos">

[root@web-node2 ~]$ yum  install  httpd  -y
#web-node2的httpd配置文件修改和web-node1相同

 在部署机上创建脚本如下:

[www@web-deploy ~]$ vim  deploy.sh 
#!/bin/bash
  
#Dir List
#mkdir -p /deploy/code/web-demo/
#mkdir -p /deploy/config/web-demo/base
#mkdir -p /deploy/config/web-demo/other
#mkdir -p /deploy/tar
#mkdir -p /deploy/tmp
#mkdir -p /opt/webroot
#mkdir -p /webroot
#chown -R www:www /deploy
#chown -R www:www /opt/webroot
#chown -R www:www /webroot
  
#Node List
PRE_LIST="192.168.1.12"
GROUP1_LIST="192.168.1.13"
ROLLBACK_LIST="192.168.1.12 192.168.1.13"
  
# Date/Time Veriables
LOG_DATE='date "+%Y-%m-%d"'
LOG_TIME='date "+%H-%M-%S"'
 
CDATE=$(date "+%Y-%m-%d")
CTIME=$(date "+%H-%M-%S")
  
#Shell Env
SHELL_NAME="deploy.sh"
SHELL_DIR="/home/www"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
  
#Code Env
PRO_NAME="web-demo"
CODE_DIR="/deploy/code/web-demo"
CONFIG_DIR="/deploy/config/web-demo"
TMP_DIR="/deploy/tmp"
TAR_DIR="/deploy/tar"
LOCK_FILE="/tmp/deploy.lock"
# WEB-PORT
WEB_PORT="81"  
usage(){
    echo  $"Usage: $0 { deploy | rollback [ list |version ]}"
}
  
writelog(){
        LOGINFO=$1
        echo "${CDATE} ${CTIME} : ${SHELL_NAME} : ${LOGINFO}" >> ${SHELL_LOG}
}
  
shell_lock(){
    touch ${LOCK_FILE}
}
  
url_test(){
    URL=$1
    curl -s --head $URL | grep "200 OK"
    if [ $? -ne 0 ];then
      shell_unlock;
      writelog "test error" && exit;
    fi
}
  
shell_unlock(){
    rm -f ${LOCK_FILE}
}
  
code_get(){
    writelog "code_get";
    cd $CODE_DIR  && echo "git pull"
    cp -r ${CODE_DIR} ${TMP_DIR}/
    API_VER="456"
}
  
code_build(){
    echo code_build
}
  
code_config(){
    writelog "code_config"
    /bin/cp -r ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}"
    PKG_NAME="${PRO_NAME}"_"${API_VER}"_"${CDATE}-${CTIME}"
    cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME}
}
  
code_tar(){
    writelog "code_tar"
    cd ${TMP_DIR} && tar cfz ${PKG_NAME}.tar.gz ${PKG_NAME}
    writelog "${PKG_NAME}.tar.gz"
}
  
code_scp(){
    writelog "code_scp"
    for node in $PRE_LIST;do
      scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/
    done
    for node in $GROUP1_LIST;do
      scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/
    done
}
  
  
pre_deploy(){
    writelog "remove from cluster"
      ssh $PRE_LIST "cd /opt/webroot/ && tar xfz ${PKG_NAME}.tar.gz"
      ssh $PRE_LIST "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
}
  
pre_test(){
    url_test "http://${PRE_LIST}:${WEB_PORT}/index.html"
    echo "add to cluster"
}
  
group1_deploy(){
    writelog "remove  from cluster"
    for node in $GROUP1_LIST;do
      ssh $node "cd /opt/webroot/ && tar xfz ${PKG_NAME}.tar.gz"
      ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
    done
    scp ${CONFIG_DIR}/other/192.168.1.13.other.cnf 192.168.1.13:/webroot/web-demo/other.cnf
}
  
group1_test(){
    url_test "http://192.168.1.13:${WEB_PORT}/index.html"
    echo "add to cluster"
}
  
rollback_fun(){
    for node in $ROLLBACK_LIST;do
      ssh $node "rm -f /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo"
    done
}
  
rollback(){
if [ -z $1 ];then
    shell_unlock;
    echo "Please input rollback version" && exit;
fi
    case $1 in
    list)
              ssh ${PRE_LIST} "ls -l /opt/webroot/*.tar.gz"
            ;;
          *)
                rollback_fun $1
    esac
}
  
main(){
    if [ -f ${LOCK_FILE} ];then
    echo "Deploy is running"  && exit;
    fi
    DEPLOY_METHOD=$1
    ROLLBACK_VER=$2
    case $DEPLOY_METHOD in
    deploy)
            shell_lock;
            code_get;
            code_build;
            code_config;
            code_tar;
            code_scp;
            pre_deploy;
            pre_test;
            group1_deploy;
            group1_test;
        shell_unlock;
            ;;
    rollback)
            shell_lock;
            rollback ${ROLLBACK_VER};
            shell_unlock;
            ;;
    *)
            usage;
    esac
  
}
main $1 $2

 切换到部署机的代码部署目录,创建一个html页面和一个差异文件

[www@web-deploy ~]$ cd  /deploy/code/web-demo/other/
[www@web-deploy other]$ vim  192.168.1.13.other.cnf
this  is  192.168.1.13 other file
[www@web-deploy base]$ vim  index.html
goser.com

 执行自动化部署脚本

[www@web-deploy ~]$ chmod +x deploy.sh
[www@web-deploy ~]$ ./deploy.sh  deploy

 验证是否部署成功

  打开地址:http://192.168.1.12:81和http://192.168.1.13:81结果如下:

                  

  再修改index.html文件内容,来模拟代码重新发布

[www@web-deploy ~]$ vim  /deploy/code/web-demo/index.html 

www.goser.com
[www@web-deploy ~]$ ./deploy.sh  deploy 

  再次打开地址:http://192.168.1.12:81和http://192.168.1.13:81结果如下:内容发生了变化,说明代码重新发布成功

                        

 验证代码回滚操作

  列出有哪些版本可以回滚

[www@web-deploy ~]$ ./deploy.sh  rollback list
-rw-rw-r-- 1 www www 227 Jun 19 21:10 /opt/webroot/web-demo_456_2018-06-19-21-10-46.tar.gz
-rw-rw-r-- 1 www www 229 Jun 19 21:15 /opt/webroot/web-demo_456_2018-06-19-21-15-07.tar.gz

  测试回滚到上一个版本

[www@web-deploy ~]$ ./deploy.sh  rollback web-demo_456_2018-06-19-21-10-46

  打开地址:http://192.168.1.12:81和http://192.168.1.13:81结果如下。说明回滚成功

                  

通过脚本拉取gitlab上部署的代码来实现自动化部署和回滚代码

 首先部署gitlab环境

  GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。

  GitLab拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。它还提供一个代码片段收集功能可以轻松实现代码复用,便于日后有需要的时候进行查找。

  1、基础环境准备

[root@web-deploy ~]# yum install curl policycoreutils openssh-server openssh-clients postfix
[root@web-deploy ~]# /etc/init.d/postfix  start

  2.安装gitlab-ce

[root@web-deploy ~]# curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
[root@web-deploy ~]# yum install -y gitlab-ce
#上面安装gitlab很慢,建议使用国内的源来部署gitlab
#由于网络问题,国内用户,建议使用清华大学的镜像源进行安装:修改gitlab仓库源地址为清华大学
[root@web-deploy ~]# vim /etc/yum.repos.d/gitlab-ce.repo 
[gitlab-ce]
name=gitlab-ce
#centos6用下面地址,如果是centso7的话用https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el6/
repo_gpgcheck=0
gpgcheck=0
enabled=1
gpgkey=https://packages.gitlab.com/gpg.key
[root@web-deploy ~]# yum makecache
[root@web-deploy ~]# yum install gitlab-ce

  3.配置并启动gitlab-ce,使用gitlab-ctl reconfigure命令即可

[root@web-deploy ~]# gitlab-ctl reconfigure
[root@web-deploy ~]# gitlab-ctl status
run: gitlab-workhorse: (pid 12171) 231s; run: log: (pid 7817) 555s
run: logrotate: (pid 12175) 230s; run: log: (pid 7832) 548s
run: nginx: (pid 12181) 230s; run: log: (pid 7823) 549s
run: postgresql: (pid 12186) 229s; run: log: (pid 7683) 587s
run: redis: (pid 12194) 229s; run: log: (pid 7600) 592s
run: sidekiq: (pid 12198) 229s; run: log: (pid 7806) 558s
run: unicorn: (pid 14967) 6s; run: log: (pid 7774) 560s
关闭gitlab:[root@web-deploy ~]# gitlab-ctl stop
启动gitlab:[root@web-deploy ~]# gitlab-ctl start
重启gitlab:[root@web-deploy ~]# gitlab-ctl restart

 登录gitlab
      第一次登录gitlab,需要为root用户修改密码,root用户也是gitlab的超级管理员。设置root管理员密码为gitlab123

 修改gitlab的配置文件,把external_url之后域名改成IP,这样访问gitlab项目的url将变成ip地址的形式。

[root@web-deploy etc]# vim /etc/gitlab/
##! For more details on configuring external_url see:
external_url 'http://192.168.1.11'
# registry_external_url 'https://registry.gitlab.example.com'
# pages_external_url "http://pages.example.com/"
# mattermost_external_url 'http://mattermost.example.com'

#改完之后,需要重新配置才能生效
[root@web-deploy etc]# gitlab-ctl reconfigure

 去掉gitlab注册的功能,企业中使用gitlab,正常应该不让人随便注册,用户需要使用gitlab,超级管理员注册即可

  将Sign-up 前面的勾去掉即可,然后保存。再次推出登录,就没注册那一项了

 创建一个组,要创建一个项目,首先要创建一个组。组名称为web

  然后再组web中创建一个项目为:web-demo。当然项目也可以从其它平台导入,比如从github迁移过来

 

 要想从gitlab上拉取或提交代码需要ssh-key认证,所以这里就需要将需要拉取或提交代码的用户下ssh公钥放到gitlab上

 

  点击add an ssh key添加www用户生成的ssh  key的公钥

  通过查看创建的项目来获取项目对应的git地址

  添加一个readme.md文件

  验证是否可以在部署机上拉取和上传gitlab上的代码

#拉取代码,首先删除/deploy/code目录下的web-demo目录
[www@web-dloepy ~]$ cd  /deploy/code/
[www@web-deploy ~]$ rm  -fr web-demo/
[www@web-deploy ~]$ git clone git@192.168.182.120:web/web-demo.git

#在家目录克隆一份web-demo项目的代码,创建一个index.html文件并上传
[www@web-deploy ~]$ git  clone  git@192.168.182.120:web/web-demo.git
[www@web-deploy ~]$ cd  web-demo/
[www@web-deploy web-demo]$ vim  index.html
gitlab.goser.com
[www@web-deploy web-demo]$ git config --global user.name "goser"    
[www@web-deploy web-demo]$ git config --global user.email goser@gitlab.com
[www@web-deploy web-demo]$ git  add  *
[www@web-deploy web-demo]$ git  commit  -m 'add  index.html'
[master 4c9df04] add  index.html
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 index.html
[www@web-deploy web-demo]$ git push

#这时候再代码部署目录中执行git pull 便可从gitlab的web-demo项目中拉取代码
[www@web-deploy code]$ git  pull

  修改deploy.sh自动化部署脚本,修改拉取代码如下:

[www@web-deploy ~]$ vim  deploy.sh
code_get(){
    writelog "code_get";
    cd $CODE_DIR  &&  git pull
    cp -r ${CODE_DIR} ${TMP_DIR}/
    API_VER="456"
}

  执行自动化部署脚本,测试是否可以从gitlab上拉取代码并自动化部署到环境

#先修改index.html文件内容
[www@web-deploy ~]$ vim  web-demo/index.html 
test.gitlab.goser.com
#提交修改:
[www@web-deploy ~]$ cd  web-demo/
[www@web-deploy web-demo]$ git add  *
[www@web-deploy web-demo]$ git commit  -m 'modify index.html'
[www@web-deploy web-demo]$ git  push
#运行自动化部署脚本
[www@web-deploy ~]$ ./deploy.sh  deploy

  页面显示效果如下:说明自动化部署从gitlab上拉取代码成功。

                    

  继续修改上面的自动化部署脚本,修改拉取代码的版本号,可以根据获取git的commit号来定义为版本号

[www@web-deploy web-demo]$ git show|grep commit|cut -d " " -f2
[www@web-deploy web-demo]$ API_VER=$(git show|grep commit|cut -d " " -f2)
[www@web-deploy web-demo]$ echo  ${API_VER:0:6}
#修改自动化部署脚本,修改版本号定义
[www@goser01 ~]$ vim deploy.sh
code_get(){
    writelog "code_get";
    cd $CODE_DIR  &&  git pull
    cp -r ${CODE_DIR} ${TMP_DIR}/
    API_VER=$(git show|grep commit|cut -d " " -f2)
    API_VER=$(echo  ${API_VER:0:6})
}
#运行脚本,测试版本是否改成git commit的号
[www@goser01 ~]$ ./deploy.sh  deploy
[www@goser01 ~]$ ./deploy.sh  rollback  list
-rw-rw-r-- 1 www www 8279 6月  20 15:01 /opt/webroot/web-demo_0230b2_2018-06-20-15-01-16.tar.gz

jenkins-----持续集成

 jenkins的部署

  因为jenkins是使用java编写的,所以要有jdk的支持,首先部署jdk环境

[root@web-node1 src]# tar  xf  jdk-8u171-linux-x64.tar.gz  -C  /usr/local/
[root@web-node1 local]# ln -s /usr/local/jdk1.8.0_171  /usr/local/jdk 
[root@web-node1 ~]# echo 'export JAVA_HOME=/usr/local/jdk' >>/etc/profile
[root@web-node1 ~]# echo  'export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar' >>/etc/profile
[root@web-node1 ~]# echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile
[root@web-node1 local]# source  /etc/profile
[root@web-node1 ~]# java -version
java version "1.8.0_171

  jenkins安装

[root@web-node1 ~]# cd   /etc/yum.repos.d/
[root@web-node1 yum.repos.d]# wget http://pkg.jenkins.io/redhat/jenkins.repo
[root@web-node1 yum.repos.d]# rpm --import http://pkg.jenkins.io/redhat/jenkins.io.key
[root@web-node1 yum.repos.d]# yum install -y jenkins
#启动jenkins报错如下
[root@web-node1 yum.repos.d]# /etc/init.d/jenkins start
Starting Jenkins bash: /usr/bin/java: 没有那个文件或目录
                                                           [失败]
#因为我们的jdk环境安装使用编译安装,不是yum 安装的jdk,待安装完jenkins后就有可能找不到java环境而启动不起来
#解决办法为:修改jenkins启动脚本,让其启动时制定jdk环境,jdk安装的是1.8就修改1.8部分的路径,是1.7就修改1.7路径,其他不修改
[root@web-node1 local]# vim  /etc/init.d/jenkins 
candidates="
/etc/alternatives/java
/usr/local/jdk/bin/java
/usr/local/jdk/jre/bin/java
/usr/lib/jvm/java-1.7.0/bin/java
/usr/lib/jvm/jre-1.7.0/bin/java
/usr/bin/java
"
#再启动jenkins就正常了
[root@web-node1 init.d]# /etc/init.d/jenkins  start
Starting Jenkins                                           [确定]

  在浏览器输入http://192.168.182.140:8080来访问jenkins。首先需要解锁Jenkins,按照页面提示在/var/lib/jenkins/secrets/initialAdminPassword中查看文件内容。将内容粘贴到输入框中即可

  点击继续,页面显示网络离线,这说明jenkins状态是不正常的。显示如下:

  问题原因:jenkins的开发者用于更新插件的json配置文件默认先检查www.google.com连接是否通的,如果连接不通谷歌,提示就是网络不通,所以网页报离线错误。

  解决办法:修改jenkins的更新插件的json配置文件,让检查网络方位谷歌地址改成国内的任意可访问的网站,然后重启jenkins即可

#修改jenkins用于更新的json配置文件,将谷歌地址改成百度
[root@web-node1 home]# vim  /var/lib/jenkins/updates/default.json 
{"connectionCheckUrl":"http://www.google.com/","core":{"buildDate":"Jun 17, 2018"
,"name":"core","sha1":"tWZZrBZivRRAz3c0c2y/sFMbuEQ=","sha512":"DM/rq++vlkD1als9Gt
T2U2hZkSJDjXCMbchh4g8CIx/Q4dA8GIIXrNMJZa8Yb3C/pdzPW/4FM6yXjNIq6bf5uQ==","url":"ht
tp://updates.jenkins-ci.org/download/war/2.128/jenkins.war","version":"2.128"},"i
d":"default","plugins":{"AnchorChain":{"buildDate":"Mar 11, 2012","dependencies":
[],"developers":[{"developerId":"direvius","email":"direvius@gmail.com","name":"A
lexey Lavrenuke"}],"excerpt":"Adds links from a text file to sidebar on each buil
#在编辑环境中批量替换
:g/wwwgoogle.com/s//www.baidu.com/g
#重启jenkins,正常访问
[root@web-node1 updates]# /etc/init.d/jenkins  restart

  下一步,进入安装插件,最好保证各个插件安装完成再下一步

  设置管理员为admin和密码为:admin

   登录jenkins,点击系统管理,可能出现页面报错,提示依赖插件没有安装成功,这是由于首次添加插件没有添加上,接着又重试,但是系统会认为没有加载重试成功的插件,其实只要重启jenkins即可

  如果时间长了忘记jenkins的admin用户账号密码,可以通过下面处理

#删除/jenkins/config.xml中的以下内容:

[root@web-node1 jenkins]# vim  /var/lib/jenkins/config.xml

<useSecurity>true</useSecurity>  
<authorizationStategy class="hudson.sucrity.FullControlOnceLoggedInAuthorizationStrategy">   
......   
</authorizationStategy>   
<securityRealm class="hudson.security.HudsonPrivateSecurityRealm">   
<disableSignup>false</disableSignup> ..  
</securityRealm>
#重启jenkins即可:[root@web-node1 jenkins]# /etc/init.d/jenkins restart

 让jenkins和gitlab关联起来,这就需要再jenkins中安装gitlab插件,我们知道jenkins主要功能就是通过各种插件来管理,所以想要jenkins提供什么功能,只要安装具有这个功能插件即可

  点击安装重启jenkins让安装的插件生效

  或者你放在这个目录下,可以把别人的整个目录拷贝过来,重启Jenkins即可生效

[root@web-node2 ~]# ls  /var/lib/jenkins/plugins/

 jenkins构建一个项目,让jenkins从gitlab上拉取代码仓库

  首先在gitlab上添加jenkins设备的deploy key(jenkins用户root或www的ssh公钥),部署代码尽量是用deploy key,因为这种方式是只读的。而不是使用SSH KEY

  在jenkins设备上root用户环境下验证是否可以拉取gitlab上代码;

#如下显示说明可以拉取gitlab上的代码
[root@web-node2 ~]# git  clone git@192.168.1.11:webtest/web-demo.git
Initialized empty Git repository in /root/web-demo/.git/
remote: Counting objects: 10, done.
remote: Compressing objects: 100% (6/6), done.
Receiving objects: 100% (10/10), 900 bytes, done.
remote: Total 10 (delta 0), reused 0 (delta 0)

  接下来设置jenkins,让jenkins在构建项目的时候从gitlab上拉取代码。也就是要授权jenkins可以连接gitlab

  接下来就可以创建一个项目了

 

  保存后点击立即构建,通过控制台查看运行结果

  从控制台可以看到它的工作路径

[root@web-node2 ~]# ls  /var/lib/jenkins/workspace/web-deploy
index.html  README.md

sonar----代码质量管理

 Sonar 是一个用于代码质量管理的开放平台。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具。与持续集成工具(例如 Hudson/Jenkins 等)不同。Sonar 并不是简单地把不同的代码检查工具结果(例如 FindBugs,PMD 等)直接显示在 Web 页面上,而是通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。在对其他工具的支持方面,Sonar 不仅提供了对 IDE 的支持,可以在 Eclipse 和 IntelliJ IDEA 这些工具里联机查看结果,同时 Sonar 还对大量的持续集成工具提供了接口支持,可以很方便地在持续集成中使用 Sonar。此外,Sonar 的插件还可以对 Java 以外的其他编程语言提供支持,对国际化以及报告文档化也有良好的支持。

 sonar部署

  Sonar的相关下载和文档可以在下面的链接中找到:http://www.sonarqube.org/downloads/。需要注意最新版的Sonar需要至少JDK 1.8及以上版本。这里已经部署完jdk

[root@linux-node2 src]# cd  /usr/local/src/
[root@linux-node2 src]# wget  https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-5.6.zip
[root@linux-node2 src]# unzip  sonarqube-5.6.zip 
[root@linux-node2 src]# mv sonarqube-5.6  /usr/local/sonarqube-5.6
[root@linux-node2 src]# ln  -s  /usr/local/sonarqube-5.6  /usr/local/sonarqube

  准备Sonar数据库

   这里的数据库是连接到宿主机的mysql数据库,宿主机的ip地址为:192.168.1.4,注意点:mysql版本必须在5.6及以上,不然sonar就是启动了过会会自动关掉

mysql> CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar@pw';
mysql> GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar@pw';
mysql> FLUSH PRIVILEGES;

  配置Sonar:配置sonar连接的数据库源在哪里,默认的监听端口为9000

[root@linux-node2 ~]# vim  /usr/local/sonarqube/conf/sonar.properties 
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar@pw
sonar.jdbc.url=jdbc:mysql://192.168.1.4:3306/sonar?useUnicode=true&characterEnco
ding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance
sonar.web.host=0.0.0.0
sonar.web.port=9000

  soanr配置文件中已经说明mysql版本的要求:

[root@linux-node2 web]# vim  /usr/local/sonarqube/conf/sonar.properties 
#----- MySQL 5.6 or greater
# Only InnoDB storage engine is supported (not myISAM).
# Only the bundled driver is supported. It can not be changed.

  启动Sonar

[root@linux-node2 ~]# /usr/local/sonarqube/bin/linux-x86-64/sonar.sh start
Starting SonarQube...
Started SonarQube.

  这时候启动sonar可能不成功,因为jdk的安装是编译安装的,而不是yum安装的方式,所以需要修改sonar的配置,让sonar启动指定jdk的位置

[root@linux-node2 ~]# vim  /usr/local/sonarqube/conf/wrapper.conf 
wrapper.java.command=/usr/local/jdk/bin/java
#重新启动sonar,这样sonar便启动成功
[root@linux-node2 ~]# /usr/local/sonarqube/bin/linux-x86-64/sonar.sh  restart

  通过地址http://192.168.1.12:9000打开sonar,使用admin用户(密码默认为admin)登录,安装中文插件

  如果在线安装失败,可以通过下载插件,将插件放到sonar的插件目录中,然后重启sonar服务即可。

  下载sonar中文插件地址为:https://github.com/SonarQubeCommunity

  注意点:下载插件的时候一定要注意插件对应的sonar版本,如果下载版本不一致将导致sonar启动不起来

#sonar插件存放的路径
[root@linux-node2 ~]# ls  /usr/local/sonarqube/extensions/plugins/
README.txt                        sonar-l10n-zh-plugin-1.21.jar
sonar-csharp-plugin-5.0.jar       sonar-scm-git-plugin-1.2.jar
sonar-java-plugin-3.13.1.jar      sonar-scm-svn-plugin-1.3.jar
sonar-javascript-plugin-2.11.jar
#比如讲中文插件下载放到这个路径中
[root@linux-node2 ~]# cd  /usr/local/sonarqube/extensions/plugins/
[root@linux-node2 plugins]# wget  https://github.com/SonarQubeCommunity/sonar-l10n-zh/releases/download/sonar-l10n-zh-plugin-1.11/sonar-l10n-zh-plugin-1.11.jar
#重启sonar服务
[root@linux-node2 plugins]# /usr/local/sonarqube/bin/linux-x86-64/sonar.sh restart

  官方sonar插件地址为:https://github.com/SonarSource,比如下载php插件。登录https://github.com/SonarSource,搜索php找到插件对应的sonar版本下载即可

  进入sonar的插件目录下载php插件,下载完重启sonar就会把新安装的插件加载到sonar中

[root@linux-node2 plugins]# wget https://github.com/SonarSource/sonar-php/releases/download/2.7-RC2/sonar-php-plugin.jar
[root@linux-node2 plugins]# ls
README.txt                            sonar-l10n-zh-plugin-1.11.jar
sonar-csharp-plugin-5.0.jar           sonar-php-plugin.jar
sonar-css-plugin.jar                  sonar-python-plugin-1.7.0.1187.jar
sonar-java-plugin-3.13-build4945.jar  sonar-scm-git-plugin-1.2.jar
sonar-javascript-plugin-2.11.jar      sonar-scm-svn-plugin-1.3.jar

 那么sonar怎么分析代码的好坏呢,这就要用到sonar-scanner工具了,sonar-scanner通过连接sonar后,扫描代码,然后把扫描结果存入数据库,sonar界面进行展示

  sonar-scanner下载地址:https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner

  部署sonar-scanner:

[root@linux-node2 src]# unzip sonar-scanner-cli-3.2.0.1227-linux.zip 
[root@linux-node2 src]# mv sonar-scanner-3.2.0.1227-linux  /usr/local/
[root@linux-node2 local]# ln  -s  /usr/local/sonar-scanner-3.2.0.1227-linux  /usr/local/sonar-scanner
[root@linux-node2 local]# cd sonar-scanner
[root@linux-node2 sonar-scanner]# vim  conf/sonar-scanner.properties 
#----- Default SonarQube server
sonar.host.url=http://192.168.1.12:9000

#----- Default source code encoding
sonar.sourceEncoding=UTF-8

#----- Global database settings 
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar@pw
  
#----- MySQL
sonar.jdbc.url=jdbc:mysql://192.168.1.4:3306/sonar?useUnicode=true&charact
erEncoding=utf8

  sonar官方提供了许多语言样板包,我们可以下载下来使用sonar-scanner来测试扫描,样本包下载地址为:https://github.com/SonarSource/sonar-scanning-examples

[root@linux-node2 ~]# unzip sonar-scanning-examples-master.zip 
#查看支持的样本语言包
[root@linux-node2 ~]# ll sonar-scanning-examples-master/sonarqube-scanner/src/
drwxr-xr-x 2 root root 4096 Apr 30 23:11 abap
drwxr-xr-x 2 root root 4096 Apr 30 23:11 cobol
drwxr-xr-x 2 root root 4096 Apr 30 23:11 css
drwxr-xr-x 2 root root 4096 Apr 30 23:11 directory
drwxr-xr-x 2 root root 4096 Apr 30 23:11 erlang
drwxr-xr-x 2 root root 4096 Apr 30 23:11 flex
drwxr-xr-x 2 root root 4096 Apr 30 23:11 javascript
drwxr-xr-x 2 root root 4096 Apr 30 23:11 package
drwxr-xr-x 2 root root 4096 Apr 30 23:11 php
drwxr-xr-x 2 root root 4096 Apr 30 23:11 pli
drwxr-xr-x 2 root root 4096 Apr 30 23:11 python
drwxr-xr-x 2 root root 4096 Apr 30 23:11 rpg
drwxr-xr-x 2 root root 4096 Apr 30 23:11 samples
drwxr-xr-x 2 root root 4096 Apr 30 23:11 sql
drwxr-xr-x 2 root root 4096 Apr 30 23:11 swift
drwxr-xr-x 2 root root 4096 Apr 30 23:11 vb6
drwxr-xr-x 2 root root 4096 Apr 30 23:11 web
drwxr-xr-x 2 root root 4096 Apr 30 23:11 xml

#样本语言包中有个sonar项目配置文件,这个文件一定要有,否则sonar-scanner无法对语言包进行扫描
#这个配置文件定义了sonar项目名称、版本、源等信息
[root@linux-node2 ~]# cd sonar-scanning-examples-master/sonarqube-scanner
[root@linux-node2 sonarqube-scanner]# cat sonar-project.properties 
sonar.projectKey=org.sonarqube:sonarqube-scanner
sonar.projectName=Example of SonarQube Scanner Usage
sonar.projectVersion=1.0

sonar.sources=src,copybooks

sonar.sourceEncoding=UTF-8

## Cobol Specific Properties

# comma-separated paths to directories with copybooks
sonar.cobol.copy.directories=copybooks
# comma-separated list of suffixes
sonar.cobol.file.suffixes=cbl,cpy
sonar.cobol.copy.suffixes=cpy

## Flex Specific Properties

# retrieve code coverage data from the Cobertura report
sonar.flex.cobertura.reportPath=coverage-report/coverage-cobertua-flex.xml

# PL/I Specific Properties
sonar.pli.marginLeft=2
sonar.pli.marginRight=0
#在sonar-scanning-examples-master/sonarqube-scanner这个目录中执行sonar-scanner命令来测试扫描样本包的代码好坏
[root@linux-node2 sonarqube-scanner]# /usr/local/sonar-scanner/bin/sonar-scanner

  最好扫描结果就会在sonar页面上显示出来,显示的名称就是配置文件sonar-project.properties中定义的sonar项目的名称

关于sonarqube最新版本安装介绍

 使用老版本sonar(比如sonarqube5.6)在安装语言插件的时候会报:要安装的插件和sonar版本不兼容的想象,这是因为要下载的插件自动下载的插件是最新版的,所以sonar常常在线下载不了插件,只能通过离线下载。

 为了使用sonar的最新功能和支持多版本语言插件的下载,应该及时的升级老版本的sonar,尽量使用新版本的sonar提供服务。

 现在介绍sonarqube-6.7版本的安装部署,这个老版本的sonarqube-5.6最主要的区别是不能使用root来启动sonar,还有新版本加入了elasticsearch。

#首先检查系统中是否安装了jdk,没有安装jdk的话,要先部署jdk环境
#下载新版本的sonar
[root@nfs-server src]# wget  https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-6.7.4.zip
#解压到/user/local/目录中
[root@nfs-server src]# unzip  sonarqube-6.7.4.zip -d  /usr/local/
#创建软连接
[root@nfs-server local]# ln  -s  /usr/local/sonarqube-6.7.4  /usr/local/sonarqube
#创建sonar数据库,这个和安装sonarqube-5.6方式一样,这里略
#修改sonar的配置文件
[root@nfs-server local]# vim  sonarqube/conf/sonar.properties 
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar@pw
#----- MySQL 5.6 or greater
# Only InnoDB storage engine is supported (not myISAM).
# Only the bundled driver is supported. It can not be changed.
sonar.jdbc.url=jdbc:mysql://192.168.182.1:3306/sonar?useUnicode=true&characterEn
coding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
#配置wrapper文件,指定java的环境
[root@nfs-server local]# vim  sonarqube/conf/wrapper.conf 
# Path to JVM executable. By default it must be available in PATH.
# Can be an absolute path, for example:
#wrapper.java.command=/path/to/my/jdk/bin/java
wrapper.java.command=/usr/local/jdk/bin/java

  然后启动sonar,发现sonar启动不起来,查看es.log和sonar.log日志文件报错:启动不了elasticsearch和不能使用root用户启动sonar

[root@nfs-server local]# more sonarqube/logs/sonar.log 
--> Wrapper Started as Daemon
Launching a JVM...
Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
  Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.

2018.05.07 16:41:38 INFO  app[][o.s.a.AppFileSystem] Cleaning or creating temp d
irectory /usr/local/sonarqube-6.7.4/temp
2018.05.07 16:41:38 INFO  app[][o.s.a.es.EsSettings] Elasticsearch listening on 
/127.0.0.1:9001
2018.05.07 16:41:38 INFO  app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key
='es', ipcIndex=1, logFilenamePrefix=es]] from [/usr/local/sonarqube-6.7.4/elast
icsearch]: /usr/local/sonarqube-6.7.4/elasticsearch/bin/elasticsearch -Epath.con
f=/usr/local/sonarqube-6.7.4/temp/conf/es
2018.05.07 16:41:38 INFO  app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch t
o be up and running
2018.05.07 16:41:39 INFO  app[][o.e.p.PluginsService] no modules loaded
2018.05.07 16:41:39 INFO  app[][o.e.p.PluginsService] loaded plugin [org.elastic
search.transport.Netty4Plugin]
2018.05.07 16:41:47 WARN  app[][o.s.a.p.AbstractProcessMonitor] Process exited w
ith exit value [es]: 1
2018.05.07 16:41:47 INFO  app[][o.s.a.SchedulerImpl] Process [es] is stopped
2018.05.07 16:41:47 INFO  app[][o.s.a.SchedulerImpl] SonarQube is stopped

  既然不能用root来启动sonar服务及elasticsearch启动不起来,那么我们就修改elasticsearch配置文件并且创建一个用户用来启动sonar

#修改es的配置文件
[root@nfs-server local]# vim  sonarqube/elasticsearch/config/elasticsearch.yml
network.host: 192.168.182.141
http.port: 9200

#创建用户sonar来启动sonar,授权sonar用户管理sonarqube
[root@nfs-server local]# useradd  sonar  
[root@nfs-server local]# chown  sonar.sonar -R /usr/local/sonarqube/
[root@nfs-server local]# su  sonar
[sonar@nfs-server local]$ /usr/local/sonarqube/bin/linux-x86-64/sonar.sh start

  待启动完成后,打开地址:http://192.168.182.141:9000,输入用户名:admin  密码:admin

   这样新版本的sonar就安装完成了,比老版本的功能更丰富,更炫。同时在新版本界面中在线安装语言插件也没问题了。

sonar和jenkins结合

 jenkins负责从gitlab上拉取代码,然后通过sonar的sonar-scanner来扫描、分析代码,将结果报告展现在sonar上

  要是jenkins结合sonar,那么就要在jenkins上安装sonar插件

  在jenkins中点击系统管理---系统设置,可以看到出现了sonarqube的设置项,接下来设置sonarqube,保存

  然后点击系统管理------全局工具配置-----配置sonar-scanner。

  需要注意:sonar-scanner一定要和jenkins装在一台设备上,因为添加sonar-scanner的时候要求输入sonar-scanner的根目录

  接下来重新配置web-deploy项目,让此项目既可以从gitlab上拉取代码,同时要求对拉取的代码做sonar代码分析,这就要在项目中添加sonar构建

  我们知道要使用sonar-scanner来扫描代码,就必要要有对代码扫描的配置文件,可以参看样本包中的配置文件做修改如下:

#参考样本包中的配置文件sonar-project.properties
[root@linux-node2 sonarqube-scanner]# cat  sonar-project.properties

#将sonar-project.properties配置文件中的参数拷贝出来放在一个文本中修改如下:
sonar.projectKey=web-demo
sonar.projectName=web-demo
sonar.projectVersion=1.0
sonar.sources=./
sonar.sourceEncoding=UTF-8
sonar.cobol.copy.directories=copybooks
sonar.cobol.file.suffixes=cbl,cpy
sonar.cobol.copy.suffixes=cpy
sonar.flex.cobertura.reportPath=coverage-report/coverage-cobertua-flex.xml
sonar.pli.marginLeft=2
sonar.pli.marginRight=0

#将上面的参数填入sonar scanner中

  点击立即构建,查看控制台输出结果如下。说明在构建项目的时候会将sonar-scanner配置的参数传给sonar-scanner命令执行

 > git config core.sparsecheckout # timeout=10
 > git checkout -f faa280be6118a81a1a4e0ad2b722b7254ecbe3db
Commit message: "test"
 > git rev-list --no-walk 0375574c5c4b9779a8f1fed8dd37080ed6865d2a # timeout=10
[web-deploy] $ /usr/local/sonar-scanner/bin/sonar-scanner -Dsonar.host.url=http://192.168.1.12:9000 -Dsonar.sourceEncoding=UTF-8 -Dsonar.cobol.copy.directories=copybooks -Dsonar.sources=./ -Dsonar.pli.marginRight=0 -Dsonar.projectVersion=1.0 -Dsonar.projectKey=web-demo -Dsonar.cobol.file.suffixes=cbl,cpy -Dsonar.flex.cobertura.reportPath=coverage-report/coverage-cobertua-flex.xml -Dsonar.cobol.copy.suffixes=cpy -Dsonar.pli.marginLeft=2 -Dsonar.projectName=web-demo -Dsonar.projectBaseDir=/var/lib/jenkins/workspace/web-deploy

  返回工程,点击工程下的SonarQube进入到sonar界面,就可以在sonar界面中看到jenkins构建项目后扫描代码的报告

 在jenkins中设置多个jobs关联

  比如设置一个项目为:deploy-sonar负责从gitlab上拉取代码并使用sonar-scanner分析代码。另一个项目为:deploy-web负责执行自动化部署web脚本

  将上面的web-deploy项目改名称为deploy-sonar

        

  新建deploy-web项目,添加一个构建即可:执行shell脚本的构建

  因为jenkins运行的时候是使用jenkins用户,所以上面配置的执行shell参数使用sudo方式连到部署机上,注意要拷贝公钥到部署机上,同时去掉tty要求

[root@linux-node2 ~]# cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2RVbMYwv9EhAn+0y/R4VSfRsNAJjawAvyo7zhwkoIhJPhL08mECFubjtdkJpAyqTxt9N8l+CASTMBUpCMdUeQGsQfARuuJMW8q0Bjk+28NNnHfQdnImf1I/6G+vOp5rtIAJanR7MWp/x0MykBE1y8CtOba13yVlXDmiUmfQP3gwbXlWfpAaetnlmGvf+IUdgbFH3JzTz2P/p6vymaGGH2E4h2tHqhUNo7pozjirvqRobFQl9rplF9Hg3h0JctWKO6B7u5UIIrsbo3mPS75dNPAQ3aC0dXfZkXG1VlHAKsPBFUs19XxyG6FELF2cstbVT6wSVmiKpujUCO817yu2F0Q== root@linux-node2.goser.com

[www@linux-node1 .ssh]$ vim authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2RVbMYwv9EhAn+0y/R4VSfRsNAJjawAvyo7zhwkoIhJ
PhL08mECFubjtdkJpAyqTxt9N8l+CASTMBUpCMdUeQGsQfARuuJMW8q0Bjk+28NNnHfQdnImf1I/6G+
vOp5rtIAJanR7MWp/x0MykBE1y8CtOba13yVlXDmiUmfQP3gwbXlWfpAaetnlmGvf+IUdgbFH3JzTz2
P/p6vymaGGH2E4h2tHqhUNo7pozjirvqRobFQl9rplF9Hg3h0JctWKO6B7u5UIIrsbo3mPS75dNPAQ3
aC0dXfZkXG1VlHAKsPBFUs19XxyG6FELF2cstbVT6wSVmiKpujUCO817yu2F0Q== root@linux-nod
e2.goser.com

#在jenkins机器上配置suder文件,添加jenkins用户可以使用sudo命令,注掉tty要求
[root@linux-node2 ~]# visudo 
# Defaults  requiretty

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
jenkins ALL=(ALL)       NOPASSWD: /usr/bin/ssh

  下面验证部署代码然后让deploy-web项目的立即构建是否成功

[www@linux-node1 ~]$ cd  web-demo/
[www@linux-node1 web-demo]$ vim  index.html 

gitlab.goser.com
[www@linux-node1 web-demo]$ git  add  *
[www@linux-node1 web-demo]$ git  commit -m "test  jenkins deploy-web"
[www@linux-node1 web-demo]$ git  push

  这时候再执行deploy-web项目的立即构建,查看输出控制是成功的。这样就实现了自动化代码部署的项目

  web页面验证:

               

实现一个job完成后自动执行下一个job

 在jenkins中添加插件Parameterized Trigger,这个插件就启动串联job的作用。它是一个触发器插件

  设置deploy-sonar项目,添加一个Parameterized Trigger,指定构建后操作选项为下一个项目为deploy-web

  这样在执行完deploy-sonar构建会自动执行deploy-web构建。。。。。

jenkins的piplines插件使用

  安装piplines插件

  构建一个pipelines视图

  选择初始化job为deploy-sonar,保存

  点击pipelines视图中的run,job便按照编排的顺序执行

实现在gitlab上部署的代码做git push的时候,jenkins自动执行构建项目

 这需要再jenkins上安装一个gitlab hook plugin,前面已经安装过了,这里就不再赘述了

 还需要一个身份认证插件,让gitlab和jenkins通过token令牌环做认证

  使用openssl的方式生成一段字符串作为token

[root@linux-node2 ~]# openssl  rand  -hex  10
e75494263ae7e5c271a4

  编辑deploy-sonar项目,让其可以被gitlab远程触发后自动构建的功能

  接下来就是指定gitlab关联的jenkins的deploy-sonar项目,添加好后,点击add webhook即可

  至于上面的URL的书写方式可以参考https://wiki.jenkins.io/display/JENKINS/Build+Token+Root+Plugin,这里有详细的书写说明

  对添加好的webhook,测试是否成功,点击TEST

   执行test后返回的结果如下图所以

  按照提示,应该是gitlab设置了不允许gitlab的hook访问网络的原因,解决办法为:在设置里设置gitlab允许hook访问网络

  接下来再执行test---push events,访问的结果就正常了,同时触发了jenkins项目的运行

 下面通过gitlab提交代码实现jenkins持续化集成,完成代码自动化部署工作

  首先使用git push来提交代码

[www@linux-node1 ~]$ cd  web-demo/
[www@linux-node1 web-demo]$ vim index.html 

web_deploy.goser.com
[www@linux-node1 web-demo]$ git  add  *
[www@linux-node1 web-demo]$ git  commit -m "web deploy"
[www@linux-node1 web-demo]$ git  push

  然后查看jenkins项目状态,项目在立即构建,说明gitlab的git push操作触发了jenkins的项目

  查看sonar,sonar也对项目deploy-sonar的构建生成了报告:

  最后查看web页面是否按照代码的内容显示:

            


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM