自动化部署
根据企业业务需求不同,自动化部署的流程设计也各不相同,所以一个自动化流程设计不是一成不变的,要根据企业的业务不同做相应的调整。
下面以下图的自动化流程为例做运维自动化部署:
根据上图的设计流程编写自动化部署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页面是否按照代码的内容显示: