自動化部署
根據企業業務需求不同,自動化部署的流程設計也各不相同,所以一個自動化流程設計不是一成不變的,要根據企業的業務不同做相應的調整。
下面以下圖的自動化流程為例做運維自動化部署:
根據上圖的設計流程編寫自動化部署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頁面是否按照代碼的內容顯示: