自動化部署和持續集成


自動化部署

根據企業業務需求不同,自動化部署的流程設計也各不相同,所以一個自動化流程設計不是一成不變的,要根據企業的業務不同做相應的調整。

下面以下圖的自動化流程為例做運維自動化部署:

根據上圖的設計流程編寫自動化部署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