CICD详解之gitlab,Jenkins
持续集成概念
- 持续集成Continuous Integration
- 持续交付Continuous Delivery
- 持续部署Continuous Deployment
什么是持续集成:
持续集成是指开发者在代码的开发过程中,可以频繁的将代码部署集成到主干,并进程自动化测试
什么是持续交付:
持续交付指的是在持续集成的环境基础之上,将代码部署到预生产环境
持续部署:
在持续交付的基础上,把部署到生产环境的过程自动化,持续部署和持续交付的区别就是最终部署到生产环境是自动化的。
部署代码上线流程
- 代码获取(直接了拉取)
- 编译 (可选)
- 配置文件放进去
- 打包
- scp到目标服务器
- 将目标服务器移除集群
- 解压并放置到Webroot
- Scp 差异文件
- 重启 (可选)
- 测试
- 加入集群
Gitlab介绍
GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。
GitLab拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。它还提供一个代码片段收集功能可以轻松实现代码复用,便于日后有需要的时候进行查找。
清华源镜像:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
gitlab部署
[root@mcw01 ~]$ ls anaconda-ks.cfg gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm [root@mcw01 ~]$ cat /etc/yum.repos.d/gitlab-ce.repo [gitlab-ce] name=gitlab-ce baseurl=http://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7 repo_gpgcheck=0 gpgcheck=0 enabled=1 gpgkey=https://packages.gitlab.com/gpg.key [root@mcw01 ~]$ [root@mcw01 ~]$ yum localinstall gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm Loaded plugins: fastestmirror Examining gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm: gitlab-ce-10.0.0-ce.0.el7.x86_64 [root@mcw01 ~]$ yum install -y git 配置并启动gitlab-ce [root@linux-node1 ~]# gitlab-ctl reconfigure #时间可能比较长,耐心你等待即可!---- gitlab常用命令: 关闭gitlab:[root@linux-node2 ~]# gitlab-ctl stop 启动gitlab:[root@linux-node2 ~]# gitlab-ctl start 重启gitlab:[root@linux-node2 ~]# gitlab-ctl restart 重载配置文件: gitlab-ctl reconfigure 可以使用gitlab-ctl管理gitlab,例如查看gitlab状态: [root@mcw01 ~]$ gitlab-ctl status run: gitaly: (pid 17644) 1226s; run: log: (pid 17193) 1366s run: gitlab-monitor: (pid 17671) 1224s; run: log: (pid 17339) 1339s run: gitlab-workhorse: (pid 17659) 1225s; run: log: (pid 17254) 1359s run: logrotate: (pid 17279) 1351s; run: log: (pid 17278) 1351s run: nginx: (pid 17261) 1358s; run: log: (pid 17260) 1358s run: node-exporter: (pid 17324) 1345s; run: log: (pid 17323) 1345s run: postgres-exporter: (pid 17693) 1223s; run: log: (pid 17447) 1321s run: postgresql: (pid 17019) 1444s; run: log: (pid 17018) 1444s run: prometheus: (pid 17680) 1224s; run: log: (pid 17374) 1327s run: redis: (pid 16959) 1455s; run: log: (pid 16958) 1455s run: redis-exporter: (pid 17354) 1333s; run: log: (pid 17353) 1333s run: sidekiq: (pid 17176) 1372s; run: log: (pid 17175) 1372s run: unicorn: (pid 17138) 1378s; run: log: (pid 17137) 1378s [root@mcw01 ~]$ 提示: 我们要保证80端口不被占用 我们可以查看一下端口
[root@mcw01 ~]$ gitlab-ctl restart
ok: run: gitaly: (pid 2137) 0s
ok: run: gitlab-monitor: (pid 2148) 1s
ok: run: gitlab-workhorse: (pid 2151) 0s
ok: run: logrotate: (pid 2159) 0s
ok: run: nginx: (pid 2166) 0s
ok: run: node-exporter: (pid 2169) 1s
ok: run: postgres-exporter: (pid 2176) 0s
ok: run: postgresql: (pid 2181) 0s
ok: run: prometheus: (pid 2194) 1s
ok: run: redis: (pid 2200) 0s
ok: run: redis-exporter: (pid 2209) 0s
ok: run: sidekiq: (pid 2232) 0s
ok: run: unicorn: (pid 2240) 0s
[root@mcw01 ~]$
lsof -i:80
页面操作
版本:gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm
访问:
提示:启动gitlab需要时间!
Web页面提示我们需要设置一个账号密码(我们要设置最少8位数的一个账号密码)我们设置密码为:12345678
我们在后面的页面设置用户名
12345678
我们现在是以管理员的身份登陆
第一步:我们关闭自动注册,因为我们内部使用不需要用户自己注册,由运维分配用户即可
提示:Save在页面最下放!!!!!! 记得点保存!!!!!!!!!!!!
现在在查看首页就没有注册页面了
第二步:我们创建一个用户,在创建一个项目
先创建一个组
**提示:**gitlab上面有一个项目跟组的概念,我们要创建一个组,才可以在创建一个项目。因为gitlab的路径上首先是ip地址,其次是组
私有,只有项目组成员才能访问
然后我们在组里面创建项目
下一步,填写项目名称。项目可以从其它地方导入。项目路径已经有了,私有,点击创建项目
项目创建成功。项目组,项目名称
创建完成之后它提示我们可以创建一个key对它进行管理
我们点击上面的README然后我们随便在里面写点东西
项目名称下,文件
填写完成我们点击前面进行查看
我们复制项目地址,去10.0.0.11主机上克隆项目。这时是需要输入用户密码的,我们一般是想要进行免密克隆
我们要做免密验证,现在去10.0.0.11复制下面的.ssh/id_rsa.pub,目前没有公钥,那就需要创建
[root@mcw01 ~]$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created directory '/root/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: SHA256:6ofcUS0A/xWeS9DJrpORLdPRemBMPPwJgTLDrFdj3no root@mcw01 The key's randomart image is: +---[RSA 2048]----+ | .+ .O++ | | .B =o&o. | | ..O X=B . | | . ..OoB.+ | | .S..O.. | | .. = E | | ..o . o | | .o o | | .. | +----[SHA256]-----+ [root@mcw01 ~]$ ls -a . anaconda-ks.cfg .bash_logout .bashrc gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm .ssh .viminfo .. .bash_history .bash_profile .cshrc .pki .tcshrc [root@mcw01 ~]$ ls .ssh/ id_rsa id_rsa.pub [root@mcw01 ~]$
[root@mcw01 ~]$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDa2frV273ZGG8BKHKCBOuuLYIOM/1XhYolKPKFyBw2aTwdW5F5faQ2sFqI2E7mdSoa6CL2MpBtFnURCVNG74YkQ5F10ur7jNOgx1CET8lL84UBlR4OOWJ8AfqMppILrtqMvcuXGtLWFvW5a8V9ceQmllAY0a0X63JZgg7ovLys5wkERGLkwlG0Yo4ZvSDw4QLjNnqsGc6vdM2jSKl+9Dvfp3pllYIcWdV1IiQWS1Q4JWImmPQngegUSVmTuAR1Bq0nj7TxdP5isjh/60IuJXMm7lreyA8Ht6TIPQnk+4H3tNZbArCXtm3mZ2TtM4TBYi7G4J6LYqp+oASSw3NUluBJ root@mcw01
[root@mcw01 ~]$
将公钥复制过来,title自动生成,点击添加
点击你的项目
选择SSH,我们要将代码拉下来
由于是第一次连接,所以确认了一次,不过已经不用输入用户密码即可克隆项目文件了
[root@mcw01 ~]$ ls anaconda-ks.cfg gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm [root@mcw01 ~]$ git clone git@gitlab.example.com:web/web-demo.git Cloning into 'web-demo'... The authenticity of host 'gitlab.example.com (10.0.0.11)' can't be established. ECDSA key fingerprint is SHA256:1TxynA6n0UD3ZO0xutB2zsCTeq3wtp+O3L5p34As/4Q. ECDSA key fingerprint is MD5:b0:3d:ab:dd:d7:93:68:ae:3d:b8:7a:35:c6:03:49:1d. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'gitlab.example.com,10.0.0.11' (ECDSA) to the list of known hosts. remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Receiving objects: 100% (3/3), done. [root@mcw01 ~]$ ls anaconda-ks.cfg gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm web-demo [root@mcw01 ~]$ ls web-demo/ README.md [root@mcw01 ~]$
我们来模拟开发继续写代码提交
[root@mcw01 ~]$ vim web-demo/index.html [root@mcw01 ~]$ cd web-demo/ [root@mcw01 ~/web-demo]$ ls index.html README.md [root@mcw01 ~/web-demo]$ git add * [root@mcw01 ~/web-demo]$ git commit -m "add index.html" *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: unable to auto-detect email address (got 'root@mcw01.(none)')
需要身份验证:
[root@mcw01 ~/web-demo]$ git config --global user.email "you@example.com" [root@mcw01 ~/web-demo]$ git config --global user.name "Your Name" [root@mcw01 ~/web-demo]$ git commit -m "add index.html" [master 0f2d55a] add index.html 1 file changed, 1 insertion(+) create mode 100644 index.html
git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。
[root@mcw01 ~/web-demo]$ git push warning: push.default is unset; its implicit value is changing in Git 2.0 from 'matching' to 'simple'. To squelch this message and maintain the current behavior after the default changes, use: git config --global push.default matching To squelch this message and adopt the new behavior now, use: git config --global push.default simple See 'git help config' and search for 'push.default' for further information. (the 'simple' mode was introduced in Git 1.7.11. Use the similar mode 'current' instead of 'simple' if you sometimes use older versions of Git) Counting objects: 4, done. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 283 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To git@gitlab.example.com:web/web-demo.git 2696039..0f2d55a master -> master [root@mcw01 ~/web-demo]$
push上去之后,就可以在gitlab上刷新网页,查看到多了index.html文件了
gitlab配置文件存放在/etc/gitlab/gitlab.rb
我们想把上面标记的改为ip访问
编辑配置文件,将域名改为ip。
[root@mcw01 ~]$ ls /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb [root@mcw01 ~]$ grep external_url /etc/gitlab/gitlab.rb |grep -v "#" external_url 'http://10.0.0.11' [root@mcw01 ~]$
[root@mcw01 ~]$ gitlab-ctl reconfigure
Starting Chef Client, version 12.12.15
- #提示:修改完需要使用reconfigure重载配置才会生效
我们重新登陆进行查看 。刷新页面之后就变成ip了
自动化运维之DevOps
DevOps(英文Development(开发)和Operations(技术运营)的组合)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。
它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作
简单的来说DevOps是一种文化,是让开发开发、运维、测试能够之间沟通和交流
自动化运维工具:saltstack、jenkins、等。因为他们的目标一样,为了我们的软件、构建、测试、发布更加的敏捷、频繁、可靠
如果运维对git不熟,是无法做自动化部署。因为所有的项目都受制于开发
Jenkins 介绍
1.5Jenkins 介绍 Jenkins只是一个平台,真正运作的都是插件。这就是jenkins流行的原因,因为jenkins什么插件都有 Hudson是Jenkins的前身,是基于Java开发的一种持续集成工具,用于监控程序重复的工作,Hudson后来被收购,成为商业版。后来创始人又写了一个jenkins,jenkins在功能上远远超过hudson Jenkins官网:https://jenkins.io/ 安装 安装JDK Jenkins是Java编写的,所以需要先安装JDK,这里采用yum安装,如果对版本有需求,可以直接在Oracle官网下载JDK。
yum安装,发现下载repo文件出错了。
[root@mcw01 ~]$ yum install -y java-1.8.0 [root@mcw01 ~]$ cd /etc/yum.repos.d/ [root@mcw01 /etc/yum.repos.d]$ wget http://pkg.jenkins.io/redhat/jenkins.repo --2022-09-27 22:44:39-- http://pkg.jenkins.io/redhat/jenkins.repo Resolving pkg.jenkins.io (pkg.jenkins.io)... 151.101.110.133, 2a04:4e42:8c::645 Connecting to pkg.jenkins.io (pkg.jenkins.io)|151.101.110.133|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://pkg.jenkins.io/redhat/jenkins.repo [following] --2022-09-27 22:44:39-- https://pkg.jenkins.io/redhat/jenkins.repo Connecting to pkg.jenkins.io (pkg.jenkins.io)|151.101.110.133|:443... connected. ERROR: cannot verify pkg.jenkins.io's certificate, issued by ‘/C=US/O=Let's Encrypt/CN=R3’: Issued certificate has expired. To connect to pkg.jenkins.io insecurely, use `--no-check-certificate'. [root@mcw01 /etc/yum.repos.d]$ rpm --import http://pkg.jenkins.io/redhat/jenkins.io.key
页面访问下,发现配置是需要坚持,那么就手动添加为不检查
[jenkins] name=Jenkins baseurl=http://pkg.jenkins.io/redhat gpgcheck=0
然后yum安装,可以成功安装
[root@mcw01 ~]$ yum install -y jenkins
启动Jenkins
[root@mcw01 ~]$ systemctl start jenkins Job for jenkins.service failed because the control process exited with error code. See "systemctl status jenkins.service" and "journalctl -xe" for details. [root@mcw01 ~]$
新版本的jenkins为了保证安全,在安装之后有一个锁,需要设置密码之后才可以解锁
Jenkins Web访问地址:10.0.0.11:8080
友情提示:jenkins如果跟gitlab在一台服务器需要将jenkins的端口进行修改,需要将jenkins的8080修改为8081
Jenkins部署
网上下载的包没有管用的, 还是用以前下载的包安装的。
[root@mcw01 ~]$ ls anaconda-ks.cfg gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm jenkins-2.73.1-1.1.noarch.rpm web-demo [root@mcw01 ~]$ yum localinstall jenkins-2.73.1-1.1.noarch.rpm [root@mcw01 ~]$ java -version openjdk version "1.8.0_345" OpenJDK Runtime Environment (build 1.8.0_345-b01) OpenJDK 64-Bit Server VM (build 25.345-b01, mixed mode) [root@mcw01 ~]$ systemctl start jenkins [root@mcw01 ~]$ grep 8081 /etc/sysconfig/jenkins #gitlab也在用8080端口 JENKINS_PORT="8081" [root@mcw01 ~]$
启动的过程有点慢,感觉过了三四分钟吧
复制这个文件下面的ID,否则不可以进行安装。
我们选择推荐安装即可
[root@mcw01 ~]$ cat /var/lib/jenkins/secrets/initialAdminPassword e7d3087517bc4bd39ba88bb7e9e07109 [root@mcw01 ~]$
点击安装推荐插件没反应,先跳过插件安装吧
jenkins基础功能的了解
我们点击新建
这里就是构建一个项目
用户界面:主要是一些用户的管理
可以看到当前登陆用户及用户权限等
任务历史:可以查看到所有构建过的项目的历史
#之所以叫构建,是因为都是java,因为如果不是java程序就没有构建这个词。但是我们也可以把一些工作称之为构建
系统管理:存放jenkins所有的配置
My Views:视图功能,我们可以自己创建一个自己的视图
构建队列:如果当前有视图任务都会显示在这里
构建执行状态:显示在正构建的任务
系统管理:-系统设置
设置Jenkins全局设置&路径
Jenkins系统管理比较重要的就是插件管理了
#因为jenkins所有的东西都需要靠插件来完成,
点击已安装可以查看我们的安装
我们想安装什么插件,我们可以选择可选插件
手动将很多插件传到插件目录,前端页面上传一个后,发现这个是已经安装,可卸载。其它也在已安装列表,但是是灰色的,也没有可卸载
Jenkins插件下载地址: https://wiki.jenkins-ci.org/display/JENKINS/Plugins 清华源国内 Jenkins插件下载地址: https://mirrors.tuna.tsinghua.edu.cn/jenkins/war
把插件地址更新为国内ch地址插件:
将地址替换:
替换为下面地址:右击复制地址
https://mirror.tuna.tsinghua.edu.cn/jenkins/updates/
点击提交:
我们为了和gitlab和在一起,我们需要安装一个插件
查看还可以去jenkins官网下载,然后上传插件
因为很多插件需要FQ才可以继续下载,jenkins还提供了代理的设置
- 还是在服务器目录下进行上传插件
- 目录路径= /var/lib/jenkins/plugins/
- 这个目录下是我们安装所有的插件
2.汉化jenkins
3.修改admin密码
点击退出
已成功修改
4.修改安装源为清华镜像源
1、系统设置->插件管理-> 高级,滑动到下方找到“升级站点”
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 用这个替换掉升级站点里面的地址
2、将 http://mirror.esuni.jp/jenkins/updates/update-center.json 这个下载源 复制粘贴到输入框内,然后提交。
备用:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/current/update-center.json
3、再重启jenkins!!!重启才生效(方法:在url后添加 restart,回车即可)
jenkins的插件网址:http://updates.jenkins-ci.org/download/plugins/
使用git+jenkins实现持续集成
开始构建
General
源码管理
web项目的项目文件地址
源码管理
我们安装的是git插件,还可以安装svn插件 。将gitlab上项目文件地址复制过来
我们将git路径存在这里还需要权限认证,否则会出现error
我们添加一个认证
之前在gitlab上已经做了免密克隆了,将mcw01主机的公钥复制到gitlab里面,实现正常在mcw01主机上git免密克隆gitlab上的项目文件。可参考前面gitlab的内容。这次将mcw01主机上的私钥放入到Jenkins里,注意,gitlab上放的是公钥,Jenkins上放的是私钥
使用刚刚创建的密钥,这样权限认证失败的错误就没有了
再开一个页面,可以看到权限认证的刚刚创建的gitlab-demo
刚刚返回刚刚的区域,继续配置。点击刚刚保存的部分设置的项目
点击配置,因为还没有配置完
返回到配置页面
我们选择gitlab,url如下图 。填写源码库浏览器。我们这里选择gitlab。填写gitlab上源码的地址,以及gitlab的版本号
源码地址url,也就是gitlab上这个项目文件的访问地址
查看gitlab版本
[root@mcw01 ~]$ rpm -qa|grep gitlab gitlab-ce-10.0.0-ce.0.el7.x86_64 [root@mcw01 ~]$
这个url这里配置错了,源码库浏览器下的url需要是http方式的。上面那个是ssh。下面这个使用ssh方式,结果不能拉取程序下了,卡了我半天时间。重新修改为http方式后,也不行,回到住房重新开机,相当于重启的服务,这才好了
我们现在就添加了一个git仓库,现在保存就可以了!
保存完毕后,我们选择立即构建
点击Console Output 可以显示控制台的输出
ssh方式错了,这里的参数用http方式。这点要注意了。
然后构建任务:
这次成功了。现在基本就算是构建成功了
持续集成之代码质量管理-Sonar
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及以上版本。
上篇文章我们已经可以成功的使用git进行拉去,Sonar的功能就是来检查代码是否有BUG。除了检查代码是否有bug还有其他的功能,比如说:你的代码注释率是多少,代码有一些建议,编写语法的建议。所以我们叫质量管理
Sonar还可以给代码打分,并且引用了技术宅的功能(告诉你有很多地方没改)
Sonar部署
[root@linux-node1 ~]# yum install -y java-1.8.0 [root@linux-node1 ~]# cd /usr/local/src 软件包我们通过wget或者下载,rz上传到服务器 #软件包下载:https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-5.6.zip
http://www.sonarqube.org/downloads/
下载上传
Sonar部署 [root@linux-node1 ~]# yum install -y java-1.8.0 [root@linux-node1 ~]# cd /usr/local/src 软件包我们通过wget或者下载,rz上传到服务器 #软件包下载:https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-5.6.zip [root@mcw01 ~]$ unzip sonarqube-8.9.9.56886.zip [root@mcw01 ~]$ mv sonarqube-8.9.9.56886 /opt/ [root@mcw01 ~]$ ln -s /opt/sonarqube-8.9.9.56886 /opt/sonarqube 准备Sonar数据库 如果没有数据库请执行 [root@mcw01 ~]$ yum install -y mariadb mariadb-server [root@mcw01 ~]$ systemctl start mariadb [root@mcw01 ~]$ systemctl enable mariadb Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service. [root@mcw01 ~]$ mysql_secure_installation [root@mcw01 ~]$ mysql update mysql.user set Password=password('123456') where User='root' and Host='127.0.0.1'; update mysql.user set Password=password('123456') where User='root' and Host='localhost'; CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci; GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar@pw'; GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar@pw'; FLUSH PRIVILEGES; Welcome to the MariaDB monitor. Commands end with ; or \g. MariaDB [(none)]> MariaDB [(none)]> update mysql.user set Password=password('123456') where User='root' and Host='127.0.0.1'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [(none)]> CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci; Query OK, 1 row affected (0.00 sec) MariaDB [(none)]> GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar@pw'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar@pw'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> update mysql.user set Password=password('123456') where User='root' and Host='localhost'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [(none)]> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> [root@mcw01 ~]$ cd /opt/sonarqube/conf/ [root@mcw01 /opt/sonarqube/conf]$ ls sonar.properties wrapper.conf [root@mcw01 /opt/sonarqube/conf]$ 编写配置文件,修改数据库配置 [root@mcw01 /opt/sonarqube/conf]$ vim sonar.properties #我们只需要去配置文件里面修改数据库的认证即可 sonar.jdbc.username=sonar #数据库用户 sonar.jdbc.password=sonar@pw #数据库密码 sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance 配置Java访问数据库驱动(可选) 默认情况Sonar有自带的嵌入的数据库,那么你如果使用类是Oracle数据库,必须手动复制驱动类到${SONAR_HOME}/extensions/jdbc-driver/oracle/目录下,其它支持的数据库默认提供了驱动。其它数据库的配置可以参考官方文档: http://docs.sonarqube.org/display/HOME/SonarQube+Platform 启动Sonar 你可以在Sonar的配置文件来配置Sonar Web监听的IP地址和端口,默认是9000端口。 [root@mcw01 /opt/sonarqube/conf]$ vim sonar.properties 99 #sonar.web.host=0.0.0.0 06 #sonar.web.port=9000 启动命令如下: [root@mcw01 ~]$ sh /opt/sonarqube/bin/linux-x86-64/sonar.sh start Starting SonarQube... Started SonarQube. [root@mcw01 ~]$ ss -lntup|grep 9000 [root@mcw01 ~]$ 如果有什么问题可以看一下日志[/opt/sonarqube/logs/sonar.log] 检查是否有相应的端口 [root@mcw01 ~]$ tail /opt/sonarqube/logs/sonar.20220928.log WrapperSimpleApp: Encountered an error running main: java.lang.IllegalStateException: SonarQube requires Java 11 to run java.lang.IllegalStateException: SonarQube requires Java 11 to run [root@mcw01 ~]$ ln -s /usr/lib/jvm/java-11-openjdk/bin/java /usr/bin/java2 [root@mcw01 ~]$ java2 -version openjdk version "11.0.16.1" 2022-08-12 LTS OpenJDK Runtime Environment (Red_Hat-11.0.16.1.1-1.el7_9) (build 11.0.16.1+1-LTS) OpenJDK 64-Bit Server VM (Red_Hat-11.0.16.1.1-1.el7_9) (build 11.0.16.1+1-LTS, mixed mode, sharing) [root@mcw01 ~]$ java.lang.RuntimeException: can not run elasticsearch as root [root@mcw02 ~]$ su - machangwei [machangwei@mcw02 ~]$ logout [root@mcw02 ~]$ chown machangwei.machangwei -R /opt/sonarqube/ [root@mcw02 ~]$ su - machangwei Last login: Wed Sep 28 23:22:52 CST 2022 on pts/0 [machangwei@mcw02 ~]$ sh /opt/sonarqube/bin/linux-x86-64/sonar.sh start Starting SonarQube... Started SonarQube. 过了一阵子端口才起来 [machangwei@mcw02 ~]$ ss -lntup|grep 9000 tcp LISTEN 0 25 :::9000 :::* users:(("java",pid=2201,fd=12)) [machangwei@mcw02 ~]$
Web登陆:IP:9000
提示:
sonar跟jenkins类似,也是以插件为主
sonar安装插件有2种方式:第一种将插件下载完存放在sonar的插件目录,第二种使用web界面来使用安装
存放插件路径[/usr/local/sonarqube/extensions/plugins/]
安装中文插件
登陆:用户名:admin 密码:admin
输入密码登录后,让更新密码,更新为87654321
安装中文插件
没有安装的按钮。从后面三个点找到插件地址,下载下来插件
将插件上传到插件目录,重启sonar。安装插件需要重启才会生效
[machangwei@mcw02 ~]$ cd /opt/sonarqube/extensions/plugins/ [machangwei@mcw02 /opt/sonarqube/extensions/plugins]$ ls README.txt [machangwei@mcw02 /opt/sonarqube/extensions/plugins]$ rz [machangwei@mcw02 /opt/sonarqube/extensions/plugins]$ ls README.txt sonar-l10n-zh-plugin-8.9.jar [machangwei@mcw02 /opt/sonarqube/extensions/plugins]$ cd [machangwei@mcw02 ~]$ /opt/sonarqube/bin/linux-x86-64/sonar.sh restart Gracefully stopping SonarQube... Stopped SonarQube. Starting SonarQube... Started SonarQube. [machangwei@mcw02 ~]$
重新访问,过一会儿,就呈现中文展示页面
查看插件安装,可以看到刚刚安装的插件
再看看全部,可以看到已经有了安装和卸载按钮
安装扫描器sonar-scanner
下载:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/ (含简单的使用说明)
我下载了sonar-scanner-cli-4.2.0.1873-linux.zip sonar-scanner-cli-4.7.0.2747-linux.zip
解压到/opt/目录下(任意目录都可以,这里只是为了方便管理),得到如下文件夹:
(6.2)切换到root用户,修改/etc/profile,添加sonnar环境变量,如下:
export MAVEN_HOME=/usr/share/maven export SONAR_SCANNER_HOME=/opt/sonar-scanner export PATH=$PATH:${MAVEN_HOME}/bin:${SONAR_SCANNER_HOME}/bin
保存退出后,执行source /etc/profile 使环境变量生效
(6.3)输入sonar-scanner -v 显示如下,则表示安装成功了:
(6.4)关联sonarqube 和sonnar scanner
在/opt/sonar-scanner/conf/sonar-scanner.properties中添加如下内容:
sonar.host.url=http://sonnar_ip:9000 sonar.login=admin sonar.password=admin sonar.jdbc.username=sonar sonar.jdbc.password=sonar123 sonar.jdbc.url=jdbc:mysql://sonnar_ip:3306/sonar?useUnicode=true&characterEncoding=utf8
使用sonarqube + sonar-scanner做代码检测:
(7.1)打开要进行代码分析的项目根目录,新建sonar-project.properties文件
(7.2)输入以下信息:
# must be unique in a given SonarQube instance sonar.projectKey=my:project # this is the name displayed in the SonarQube UI sonar.projectName=apiautocore sonar.projectVersion=1.0 # Path is relative to the sonar-project.properties file. Replace "" by "/" on Windows. # Since SonarQube 4.2, this property is optional if sonar.modules is set. # If not set, SonarQube starts looking for source code from the directory containing # the sonar-project.properties file. sonar.sources=src # Encoding of the source code. Default is default system encoding #sonar.sourceEncoding=UTF-8
其中:projectName是项目名字,sources是源文件所在的目录
(7.3)设置成功后,启动sonarqube服务
(7.4)进入项目所在的根目录,输入命令:sonar-runner,分析成功后会有success信息
(7.5)浏览器输入http://sonar_ip:9000登陆sonnarqube,就能看到你刚才扫描的工程信息
sonar 启动失败,es报错(查看logs目录下的es.log即可):
es[][o.e.b.BootstrapChecks] max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
解决:
在 /etc/sysctl.conf文件最后添加一行
vm.max_map_count=262144
代码流水线管理
Pipeline名词顾名思义就是流水线的意思,因为公司可能会有很多项目。如果使用jenkins构建完成后,开发构建项目需要一项一项点击,比较麻烦。所以出现pipeline名词。
代码质量检查完毕之后,我们需要将代码部署到测试环境上去,进行自动化测试
新建部署代码项目(脚本执行任务)
使用Jenkins构建一个自由风格的项目。其它不管,构建里增加构建步骤 ,选择执行shell,然后在命令框里填写执行命令,点击保存,然后立即构建任务。命令框里可以写Jenkins主机远程ssh连接其它主机执行命令,执行的命令放到双引号里。执行的命令可以是执行某个脚本。或许可以是个部署脚本,这样就能直接部署了。不过Jenkins主机上,程序用户是Jenkins,它想要远程连接其它主机执行命令,需要有权限,可以将Jenkins主机的公钥分发到要连接的主机,保证可以免密ssh登录远程主机,保证Jenkins用户有该脚本的执行权限。
点击新建
这里只需要写一下描述
温馨提示:执行命令主要涉及的是权限问题,我们要明白,jenkins是以什么权限来执行命令的。那么问题来了,我们现在192.168.56.11上,如果在想192.168.56.12上执行命令。需要怎么做呢?
我们做无秘钥有2种分案:
1、使用jenkins用户将秘钥分发给192.168.56.12上
2、使用root用户将秘钥分发给192.168.56.12上,如果使用root用户还要进行visudo授权。因为Web上默认执行命令的用户是jenkins
1.我们使用root做密码验证
#这里我们的key已经做好,如果没做可以直接 ssh-keygen -t ras 来生成秘钥
我们将192.168.56.11上的公钥复制到192.168.56.12上
- [root@linux-node1 ~]# cat .ssh/id_rsa.pub
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChVQufrGwqP5dkzIU4ZwXCjRuSvMVGN5lJdvL/QFckmlVphWMsQw06VsPhgcI1NDjGbKOh5pbjrylyJUCig5YIJ1xuMOZ2YAK32SceMxnVhEb/G4wNb9VMsGQ/Vs4CxrU1HdATktH9zDAV4Qz81x2POYJW5B5LAvwZ4owqnIpZ7o3ya6xBxEvCIMSVtD17oKrNqAphsg+e68KvRexiNCEbCbRGGq3bKevgiDsWpSGnCYsJC0+cSrUxuzEO3G6AqGI/qR3nOeg91rOsoAP3FpFjBKgb/sXggkwwjmGIqFXJrUG+XmczeF4kG/rUrNbdy84e5RyHoIS3XKnJuRjTxHyD root@linux-node1
- [root@linux-node2 ~]# vim .ssh/authorized_keys
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChVQufrGwqP5dkzIU4ZwXCjRuSvMVGN5lJdvL/QFckmlVphWMsQw06VsPhgcI1NDjGbKOh5pbjrylyJUCig5YIJ1xuMOZ2YAK32SceMxnVhEb/G4wNb9VMsGQ/Vs4CxrU1HdATktH9zDAV4Qz81x2POYJW5B5LAvwZ4owqnIpZ7o3ya6xBxEvCIMSVtD17oKrNqAphsg+e68KvRexiNCEbCbRGGq3bKevgiDsWpSGnCYsJC0+cSrUxuzEO3G6AqGI/qR3nOeg91rOsoAP3FpFjBKgb/sXggkwwjmGIqFXJrUG+XmczeF4kG/rUrNbdy84e5RyHoIS3XKnJuRjTxHyD root@linux-node1
- [root@linux-node1 ~]# ssh 192.168.56.12
- The authenticity of host '192.168.56.12 (192.168.56.12)' can't be established.
- ECDSA key fingerprint is b5:74:8f:f1:03:2d:cb:7d:01:28:30:12:34:9c:35:8c.
- Are you sure you want to continue connecting (yes/no)? yes
- Warning: Permanently added '192.168.56.12' (ECDSA) to the list of known hosts.
- Last login: Sat Dec 17 02:14:31 2016 from 192.168.56.1
- [root@linux-node2 ~]# ll
- total 4
- -rw-------. 1 root root 1021 Dec 13 05:56 anaconda-ks.cfg
- #现在SSH连接就不需要密码了
- 授权jenkins用户,使用visudo或者编辑配置文件/etc/sudoers
- [root@linux-node1 ~]# vim /etc/sudoers
- 92 jenkins ALL=(ALL) NOPASSWD:/usr/bin/ssh
- #jenkins授权所有主机,不需要密码执行ssh。切记不要授权ALL
我们在192.168.56.12上写一个简单shell脚本,检测是否可以执行成功。正式环境可以写一个自动化部署的脚本
- [root@linux-node2 ~]# echo "echo "hello word"" >demo.sh
- [root@linux-node2 ~]# chmod +x demo.sh
- [root@linux-node2 ~]# ll demo.sh
- -rwxr-xr-x 1 root root 16 Dec 17 02:24 demo.sh
jenkins编写执行脚本
保存后点击立即构建
我们可以看到成功执行
构建任务完成后会触发构建另一个任务
需要安装插件。在某个项目的设置构建下面的构建后操作里,添加操作步骤。也就是该项目构建完成后,我们选择的是触发构建其它项目。然后指定那个要构建的Jenkins项目名称。
现在我们要将代码质量管理和测试部署连接起来。
这时候就用到了git钩子
我们需要安装jenkins插件parameterized
我们选择demo-deploy
再次点击项目设置的时候就会出现Trigger parameterized build on other projects
提示:Projects to build是为构建设置一个项目。例如我们想构建完代码项目后执行测试的,这里就填写测试的就可以。
最后点击保存,点击构建。我们查看效果
#这样我们每次点击demo-deploy 它就会在构建完成之后在对auto-deploy进行构建
Pipeline简介
概念
Pipeline,就是一套运行在Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
使用Pipeline有以下好处: ·
●代码: Pipeline以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流程。
●持久:无论是计划内的还是计划外的服务器重启,Pipeline都是可恢复的。
●可停止: Pipeline可接收交互式输入,以确定是否继续执行Pipeline。
●多功能: Pipeline支持现实世界中复杂的持续交付要求。它支持fork/join、循环执行,并行执行任务的功能。
●可扩展: Pipeline插件支持其DSL的自定义扩展,以及与其他插件集成的多个选项。
3)如何创建Jenkins Pipeline呢
Pipeline 脚本是由Groovy语言实现的,但是我们没必要单独去学习Groovy
Pipeline 支持两种语法: Declarative (声明式)和 scripted Pipeline(脚本式〉语法 Pipeline有两种创建方法:
●直接在Jenkins 的web UI界面中输入脚本:
●通过创建一个Jenkinsfile 脚本文件放入项目源码库中(一般我们都推荐在Jenkins 中直接从源代码控制(scm)中直接载入、JenkinsilePipeline这种方法)。
安装Pipeline插件
(推荐的插件己默认安装) Manage Jenkins -> Manage Plugins ->可选插件->安装Pipeline
Pipeline语法快速入门
Scripted脚本式Pipeline
新建item ->任务名称(web_demo_pipeline) Pipeline ->确定
流水线->定义选择Pipeline script ->选择scripted Pipeline
下载pipeline。这样只需要构建一个项目,就会帮我们完成所有相关项目
插件管理里搜索下载插件pipeline
我们点击首页+号,新建一个视图
点击OK
没有发现构建pipeline视图的选项,那新建pipeline项目应该差不多意思吧。
写一个简单的脚本式Pipeline
定义stage,也就是阶段,一般设置拉取代码,代码编译,代码检测,项目部署等等阶段。每个阶段就是stage (){} ,stage小括号花括号。小括号写‘阶段名称,名称在视图和控制台都能明显的看到,花括号里放,命令
node { def mvnHome stage('拉取代码') { echo '拉取代码' } stage('代码编译') { echo '代码编译' } stage('项目部署') { echo '项目部署' } }
将脚本放到框中,点击保存,点击立即构建,结果如下
案例:
node { def mvnHome stage('Preparation') { // for display purposes // Get some code from a GitHub repository git 'https://github.com/jglick/simple-maven-project-with-tests.git' // Get the Maven tool. // ** NOTE: This 'M3' Maven tool must be configured // ** in the global configuration. mvnHome = tool 'M3' } stage('Build') { // Run the maven build withEnv(["MVN_HOME=$mvnHome"]) { if (isUnix()) { sh '"$MVN_HOME/bin/mvn" -Dmaven.test.failure.ignore clean package' } else { bat(/"%MVN_HOME%\bin\mvn" -Dmaven.test.failure.ignore clean package/) } } } stage('Results') { junit '**/target/surefire-reports/TEST-*.xml' archiveArtifacts 'target/*.jar' } }
● Node:节点,一个Node 代表一个Jenkins节点,Master或者Agent 节点,是执行 Step的具体运行环境,后续讲到Jenkins的Master-slave架构的时候用到。 ● Stage:阶段,一个 Pipeline可以划分为若干个stage,每个stage 代表一组操作,比如: Build、Test、Deploy,Stage是一个逻辑分组的概念。 ● Step:步骤,Step 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker镜像,由各类venkins 插件提供,比如命令:sh ‘make',就相当于我们平时shell 终端中执行make 命令一样。
Declarative声明式Pipeline
流水线->选择Helloworld模板
生成内容如下:
pipeline { agent any stages { #stages:代表整个流水线的所有执行阶段。通常stages只有1个,里面包含多个stage stage('Hello') { #stage:代表流水线中的某个阶段,可能出现n个。一般分为拉取代码,编译构建,部署等阶段 steps { #steps:代表一个阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等任意内容 echo 'Hello World' } } } }
简单构建声明式Pipeline
pipeline { agent any stages { stage('拉取代码') { steps { echo 'pull code' } } stage('编译构建') { steps { echo 'make & build' } } stage('部署项目') { steps { echo 'deploy project' } } } }
将上面声明式的放入到下面框中。点击保存,点击立即构建
使用代码生成器生成流水线脚本()
流水线->流水线语法->片段生成器
生成一个pull stage 选择checkout : check out from version control
SCM选择Git,Repository URL: git@192.168.37.103:devops_group/web_demo.git
Credentials下拉选择gitlab-auth-ssh 指定分支 * /master 点击生成流水线脚本 把生成的脚本复制到流水线中后,点击保存,尝试构建;认证就用之前创建的认证就行,参考前面的。
连接的认证凭证用之前创建好的。
指定分支,点击生成流水线脚本,复制脚本放到配置中
将生成的拉取代码的流水线代码放到拉取代码的阶段.点击保存,点击立即构建
构建结果如下
看控制台输出,可以看到已经将gitlab上的程序拉取过来了。Jenkins服务器将代码拉取下来了
jenkens将gitlab上的项目文件拉取到了Jenkins项目工作目录中了,如下,如果是java程序,那么就可以使用命令去打包,然后上传到web服务器中,
生成一个构建stage
选择sh: shell script shell script输入mvn clean package点击生成流水线脚本 把生成的脚本复制到流水线中后,点击保存,尝试构建;
复制粘贴保存构建
[root@mcw01 ~]$ mvn
-bash: mvn: command not found
[root@mcw01 ~]$ yum install -y maven
[root@mcw02 ~]$ rz -E rz waiting to receive. [root@mcw02 ~]$ java -version openjdk version "1.8.0_345" OpenJDK Runtime Environment (build 1.8.0_345-b01) OpenJDK 64-Bit Server VM (build 25.345-b01, mixed mode) [root@mcw02 ~]$ ls anaconda-ks.cfg mcw apache-tomcat-8.0.27.tar.gz sonarqube demo.sh sonar-scanner-cli-4.7.0.2747-linux.zip jpress-web-newest.war tomcat [root@mcw02 ~]$ mv tomcat/ bin/ LICENSE RELEASE-NOTES webapps/ conf/ logs/ RUNNING.txt work/ lib/ NOTICE temp/ [root@mcw02 ~]$ mv jpress-web-newest.war tomcat/webapps/ [root@mcw02 ~]$ [root@mcw02 ~]$ ls tomcat/ bin lib logs RELEASE-NOTES temp work conf LICENSE NOTICE RUNNING.txt webapps [root@mcw02 ~]$ ls tomcat/webapps/ docs examples host-manager jpress-web-newest.war manager ROOT [root@mcw02 ~]$ ./tomcat/bin/startup.sh Using CATALINA_BASE: /root/tomcat Using CATALINA_HOME: /root/tomcat Using CATALINA_TMPDIR: /root/tomcat/temp Using JRE_HOME: /usr Using CLASSPATH: /root/tomcat/bin/bootstrap.jar:/root/tomcat/bin/tomcat-juli.jar Tomcat started. [root@mcw02 ~]$ systemctl stop firewalld.service [root@mcw02 ~]$ ls tomcat/webapps/ docs host-manager jpress-web-newest.war ROOT examples jpress-web-newest manager [root@mcw02 ~]$ ls tomcat/webapps/jpress-web-newest META-INF robots.txt static templates WEB-INF [root@mcw02 ~]$
访问加上路径就行:后台http://10.0.0.12:8080/jpress-web-newest/admin,不写路径默认访问上面的了
这下我们有java程序,而不是war包了,将java程序上传到git服务器,
将java程序上传到代码仓库 [root@mcw01 ~]$ ls tomcat/webapps/ jpress-web-newest [root@mcw01 ~]$ cd tomcat/webapps/ [root@mcw01 ~/tomcat/webapps]$ ls jpress-web-newest [root@mcw01 ~/tomcat/webapps]$ git add . fatal: Not a git repository (or any of the parent directories): .git [root@mcw01 ~/tomcat/webapps]$ git init Initialized empty Git repository in /root/tomcat/webapps/.git/ [root@mcw01 ~/tomcat/webapps]$ ls jpress-web-newest [root@mcw01 ~/tomcat/webapps]$ ls -a . .. .git jpress-web-newest [root@mcw01 ~/tomcat/webapps]$ git add . [root@mcw01 ~/tomcat/webapps]$ git commit -m 'java pro' [master (root-commit) fb7ab68] java pro 605 files changed, 78419 insertions(+) create mode 100644 jpress-web-newest/.ehcache/.ehcache-diskstore.lock ...... [root@mcw01 ~/tomcat/webapps]$ git push fatal: No configured push destination. Either specify the URL from the command-line or configure a remote repository using git remote add <name> <url> and then push using the remote name git push <name> [root@mcw01 ~/tomcat/webapps]$
由于没有指定上传的远程仓库地址,我们需要添加一个。在gitlab上新建一个项目,写项目名称,然后创建。
在git服务器上添加远程仓库,然后上传代码。
因为该目录已经初始化为本地仓库了,并且代码已经提交到本地仓库了。所以直接push到远程仓库gitlab上
[root@mcw01 ~/tomcat/webapps]$ ls /root/ anaconda-ks.cfg gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm jenkins-2.73.1-1.1.noarch.rpm jpress-web-newest.tar.gz sonarqube-8.9.9.56886.zip tomcat [root@mcw01 ~/tomcat/webapps]$ ls jpress-web-newest [root@mcw01 ~/tomcat/webapps]$ git remote add origin git@10.0.0.11:root/javaPro.git #添加远程仓库 [root@mcw01 ~/tomcat/webapps]$ git push -u origin master #上传代码 Counting objects: 752, done. Compressing objects: 100% (686/686), done. Writing objects: 100% (752/752), 19.17 MiB | 9.49 MiB/s, done. Total 752 (delta 80), reused 0 (delta 0) remote: Resolving deltas: 100% (80/80), done. To git@10.0.0.11:root/javaPro.git * [new branch] master -> master Branch master set up to track remote branch master from origin. [root@mcw01 ~/tomcat/webapps]$
然后在gitlab页面上,该项目下可以看到上传的代码
生成拉取代码的流水线代码,指定仓库地址为刚刚创建的javaPro仓库
将流水线代码复制粘贴到流水线任务配置的代码拉取中。将编译构建命令改成当前目录创建目录命令,因为mvn构建命令目前没成功,先跳过这个步骤。目前Jenkins的工作目录下是这样的。
保存构建:
拉取代码和创建目录都是成功的
查看Jenkins工作目录中,可以看到拉取的代码和执行shell命令创建的目录。如果拉取过来的不是代码而是war,其实我们直接可以执行shell命令将war包上传到指定主机的Tomcat中,这样就完成了部署。这个任务的重新构建,使得上次构建在工作目录中保存的文件删掉了。
在目录中的权限是这样的。
由于我这里打包有问题,那么i我直接将war包放到这个目录下,前面的拉取代码和编译打包改成打印操作。模拟后面的部署操作
将war包上传到Jenkins工作目录中,授权为Jenkins用户。
生成一个部署stage
选择deploy: Deploy war/ear to a containerwAR files 输入targer/* . war containers -> Add container ->Tomcat 8.x Remote -> Credentials 下拉选择 tomcat-authTomcat URL输入http://192.168.37.108:8080/ 点击生成流水线脚本 把生成的脚本复制到流水线中后,点击保存,尝试构建部署。
没有找到deploy这个语法,暂且先用sh脚本的方式将Jenkins工作目录中的war包上传到Tomcat服务器上把
将主机2这个Tomcat服务器上的包和解压文件移走。保证主机1的Jenkins用户有权限免密scp上传文件到这个目录
[root@mcw01 ~]$ grep scp /etc/sudoers
jenkins ALL=(ALL) NOPASSWD:/usr/bin/ssh,/usr/bin/scp
[root@mcw01 ~]$
将其它阶段的执行操作注释掉,然后部署项目阶段的配置修改为刚刚根据语法生成的上传war包到Tomcat服务器目录的命令,点击保存立即构建
没加sudo,上传失败
加上sudo之后,就能使用scp将war包从Jenkins工作目录上传到Tomcat服务器站点目录
控制台输出
可以看到Tomcat服务器目录已经存在war包了,并且在Tomcat的机制下自动解压了
http://10.0.0.12:8080/jpress-web-newest/
页面又可以正常访问了,这样就实现的自动部署
上面的pipeline程序
pipeline { agent any stages { stage('拉取代码') { steps { echo 'pull code' // checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'cec19ba3-6eaf-49c9-b83f-f21d605beebe', url: 'git@10.0.0.11:root/javaPro.git']]]) } } stage('编译构建') { steps { echo 'make & build' // sh 'mvn clean package' // sh 'mkdir mcw123' } } stage('部署项目') { steps { sh 'sudo scp -rp *.war root@10.0.0.12:/root/tomcat/webapps/' } } } }
管理Jenkinsfile脚本文件
之前我们都是直接在Jenkins的 Ur界面编写Pipeline代码,这样不方便脚本维护,而且如果Jenkins服务器崩溃也会导致Pipeline代码丢失,所以建议把Pipeline 脚本放在项目中来一起进行版本控制。
在项目根目录中建立Jenkinsfile文件,把 Pipeline 代码内容复制到该文件中,并上传到 Gitlab
将war包上传到git仓库
[root@mcw01 ~/mcw2]$ ls jpress-web-newest.war [root@mcw01 ~/mcw2]$ git init Initialized empty Git repository in /root/mcw2/.git/ [root@mcw01 ~/mcw2]$ git remote add origin git@10.0.0.11:root/warbao.git [root@mcw01 ~/mcw2]$ git add . [root@mcw01 ~/mcw2]$ git commit -m "war bao" [master (root-commit) eb04021] war bao 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 jpress-web-newest.war [root@mcw01 ~/mcw2]$ git push -u origin master Counting objects: 3, done. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 19.76 MiB | 33.90 MiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To git@10.0.0.11:root/warbao.git * [new branch] master -> master Branch master set up to track remote branch master from origin. [root@mcw01 ~/mcw2]$
添加Jenkinsfile文件到代码仓库,文件中包含从gitlab拉取war包,将war包从Jenkins工作目录复制到Tomcat服务器站点目录,从而实现部署
[root@mcw01 ~/mcw2]$ vim Jenkinsfile [root@mcw01 ~/mcw2]$ cat Jenkinsfile pipeline { agent any stages { stage('拉取代码') { steps { echo 'pull code' checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'cec19ba3-6eaf-49c9-b83f-f21d605beebe', url: 'git@10.0.0.11:root/warbao.git']]]) } } stage('编译构建') { steps { echo 'make & build' // sh 'mvn clean package' } } stage('部署项目') { steps { echo 'deploy project' // deploy adapters: [tomcat9(credentialsId: '3506afe2-2e3c-4bfd-abab-e27489305d6c', path: '', url: 'http://192.168.37.108:8080/')], contextPath: null, war: 'target/*.war' sudo scp -rp jpress-web-newest.war root@10.0.0.12:/root/tomcat/webapps/ } } } } [root@mcw01 ~/mcw2]$ git add .
[root@mcw01 ~/mcw2]$ git commit -m "add Jenkinsfile"
[master 608ee0c] add Jenkinsfile
1 file changed, 27 insertions(+)
create mode 100644 Jenkinsfile
[root@mcw01 ~/mcw2]$
[root@mcw01 ~/mcw2]$ git push -u origin master #添加文件到仓库
Counting objects: 4, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 820 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@10.0.0.11:root/warbao.git
eb04021..608ee0c master -> master
Branch master set up to track remote branch master from origin.
[root@mcw01 ~/mcw2]$
在项目中引用该Jenkinsfile文件
流水线->定义下拉选择Pipeline script from SCM
#此处需与脚本文件名称相同 点击保存,尝试构建部署
测试将Tomcat主机的war包删除
[root@mcw02 ~]$ ls tomcat/webapps/ docs examples host-manager jpress-web-newest jpress-web-newest.war manager ROOT [root@mcw02 ~]$ rm -rf tomcat/webapps/jpress-web-newest* [root@mcw02 ~]$ ls tomcat/webapps/ docs examples host-manager manager ROOT [root@mcw02 ~]$
将Jenkins主机这个项目的工作目录清空
[root@mcw01 ~/mcw2]$ ls /var/lib/jenkins/workspace/demo-pipeline jpress-web-newest jpress-web-newest.war [root@mcw01 ~/mcw2]$ rm -rf /var/lib/jenkins/workspace/demo-pipeline/jpress-web-newest* [root@mcw01 ~/mcw2]$ ls /var/lib/jenkins/workspace/demo-pipeline [root@mcw01 ~/mcw2]$
点击保存立即构建
Jenkinsfile格式有问题,报错了
改正后如下:
[root@mcw01 ~/mcw2]$ cat Jenkinsfile pipeline { agent any stages { stage('拉取代码') { steps { echo 'pull code' checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'cec19ba3-6eaf-49c9-b83f-f21d605beebe', url: 'git@10.0.0.11:root/warbao.git']]]) } } stage('编译构建') { steps { echo 'make & build' // sh 'mvn clean package' } } stage('部署项目') { steps { echo 'deploy project' // deploy adapters: [tomcat9(credentialsId: '3506afe2-2e3c-4bfd-abab-e27489305d6c', path: '', url: 'http://192.168.37.108:8080/')], contextPath: null, war: 'target/*.war' sh 'sudo scp -rp *.war root@10.0.0.12:/root/tomcat/webapps/' } } } } [root@mcw01 ~/mcw2]$
然后重新上传到gitlab,重新构建任务。
这次pipeline流水线代码来自gitlab上定义好的Jenkinsfile,运行成功
拉取Jenkinsfile和war包
部署到Tomcat服务器
再次访问,可以成功访问了。
查看Jenkins项目工作目录
查看Tomcat服务器站点目录,有war包,且让Tomcat解压了。
Jenkins 项目构建细节
1、内置构建触发器
1、常用的内置构建触发器 前面我们使用的都是手动点击触发构建,而Jenkins 内置4种构建触发器来实现触发构建:
●触发远程构建
●其他工程构建后触发(Build after other projects are build)
●定时构建(Build periodically)
●轮询SCM( Poll SCM)
1)触发远程构建(需要第三方应用调用URL地址传递加密token字符串来触发远程构建)
demo-pipeline项目下点击配置->构建触发器->勾选触发远程构建
还是上面那个pipeline项目,做下修改
复制框框下方URL地址然后修改一下:JENKINS_URL/job/demo-pipeline/build?token=TOKEN_NAME
生成远程访问地址:http://10.0.0.11:8081/job/demo-pipeline/build?token=abc123
点击保存,然后在新建浏览器窗口访问: http://10.0.0.11:8081/job/demo-pipeline/build?token=abc123
目前是任务12
在浏览器上通过地址栏访问地址的方式,再去Jenkins平台上查看,可以看到该项目构建信任并成功运行
通过网址(api)做访问请求,成功构建并运行任务
其他工程构建后触发(当前项目需要依赖一个前置项目工程构建完成后才能触发构建)
#创建一个前置项目工程 新建
item ->任务名称(pre_job) Freestyle Project ->确定
构建->添加构建步骤-> Execute shell,命令输入echo "构建前置工程"
该任务起个名字后,选择执行shell,echo打印一个输出,点击保存
#配置需要触发的工程
demo-pipeline 项目下点击配置-→构建触发器-→勾选加build after other projects are built,并取消其它勾选项,关注的项自输入pre_job 点击保存
目前最后一个任务是13;
#构建前置工程来触发项目工程构建 先构建pre_job前置项目工程,当此工程构建完成后则会立即引发构建demo-pipeline项目工程
当前置工程构建完成后,这个任务也构建了一次
时间有先后,后面那个是触发构建的
定时构建
定时字符串从左往右分别为:分时日月周
#定时表达式的示例
●每分钟构建一次: * * * * * ● 每小时构建一次:H为形参,代表以传入值为起点 H * * * * ●每10分钟构建一次: H/10 * * * * ●每2个小时构建一次: 5 5/2 * * * ●每天的8点,12点,22点,一天构建3次:(多个时间点中间用逗号隔开) 0 8,12,22 * * * ●每天中午12点定时构建一次: H 12 * * * ●每天下午6点定时构建一次: H 18 * * * ●在每个小时的前半个小时内的每10分钟: H(0-29)/10 * * * * ●每两小时一次,每个工作日上午9点到下午5点(也许是上午10:38,下午12:38,下午2:38,下午4:38): H H(9-16)/2 * * 1-5
demo-pipeline 项目下点击配置->构建触发器->勾选 Build periodically,并取消其它勾选项日程表输入
H/2 * * * *
点击保存,尝试构建 会发现前后两次构建相隔2分钟
如下,可以看到项目每两分钟构建一次
轮询SCM
轮询SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建:如果没有变更则不会触发项目构建。
demo-pipeline 项目下点击配置->构建触发器->勾选 poll SCM,并取消其它勾选项
目前是这个
上传代码到gitlab
会发现代码有变更,会触发项目构建。设置的是两分钟轮询一次,发现仓库有变化就构建一次项目
注意:轮询scw构建触发器,Jenkins会定时扫描本地整个项目的代码,会增大系统的开销,不建议使用轮询sCM。
下载插件地址:https://updates.jenkins-ci.org/download/plugins/multibranch-scan-webhook-trigger/
查看Jenkins版本:
[root@mcw01 ~/mcw2]$ grep version /var/lib/jenkins/config.xml
<?xml version='1.0' encoding='UTF-8'?>
<version>1.0</version>
[root@mcw01 ~/mcw2]$
在Jenkins的内置构建触发器中,虽然轮询sCM可以实现Gitlab代码更新,项目自动构建,但是该方案的性能不佳。我们利用Gitlab的webhook实现代码push到仓库,立即触发项目自动构建。
轮询SCM原理: Jenkins --发生定时请求--> Gitlab变更 webhook原理: Gitlab变更--发送构建请求--> Jenkins
安装Gitlab Hook插件:
Manage Jenkins -> Manage Plugins >可选插件->安装GitLab和Generic webhook Trigger
gitlab-hook下载地址: https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/gitlab-hook/
jenkins插件地址集合:
国内云厂商提供的镜像 参考 https://github.com/lework/jenkins-update-center tencent mirrors.cloud.tencent.com/jenkins huawei mirrors.huaweicloud.com/jenkins tsinghua mirrors.tuna.tsinghua.edu.cn/jenkins ustc mirrors.ustc.edu.cn/jenkins bit http://mirror.bit.edu.cn/jenkins 对应的文件 https://cdn.jsdelivr.net/gh/lework/jenkins-update-center/updates/tencent/update-center.json https://cdn.jsdelivr.net/gh/lework/jenkins-update-center/updates/huawei/update-center.json https://cdn.jsdelivr.net/gh/lework/jenkins-update-center/updates/tsinghua/update-center.json https://cdn.jsdelivr.net/gh/lework/jenkins-update-center/updates/ustc/update-center.json https://cdn.jsdelivr.net/gh/lework/jenkins-update-center/updates/bit/update-center.json
上图gitlab-plugin就是gitlab hook插件,在网上找了半天gitlab-hook名字的插件都不能用,却不知道自己已经有了,白白浪费了好多时间。
Jenkins 设置自动构建
demo-pipeline 项目下点击配置-〉构建触发器→取消其它勾选项,勾选 Build when a change is pushed to GitLab. GitLab CI Service URL: http://10.0.0.11:8081/project/demo-pipeline等会需要把生成的webhook URL配置到Gitlab中 其它保持默认值,点击保存
#Gitlab配置 webhook
1)开启webhook功能 使用root账户登录到后台,
点击管理中心->点击左边菜单 设置-〉选择子菜单网络->点击外发请求展开勾选“Allow requests to the local network from web hooks and services"让网络钩子允许请求本地网络
点击save changes
在项目添加webhook
点击项目->点击左边菜单设置->选择子菜单集成 URL输入http://10.0.0.11:8081/project/demo-pipeline Trigger '勾选Push events,其它可根据使用场景自行选择 点击Add webhook Webhooks 下方即会出现保存的 webhook,但此时若点击Test ->选择 Push events测试连接,会报错
地址是填的Jenkins上构建触发器时显示的服务url
报错:
解决方法:在Jenkins 中,Manage Jenkins -> Configure System -> Gitlab -〉取消勾选Enable authentication for '/project ' end-point点击保存
在gitlab上再次测试:
成功了
此时,已经构建,当我们再次修改代码,上传到gitlab时,钩子自动发现自动构建
目前是这样的
web服务器情况,没有war包:
git服务器修改代码,然后推送到gitlab仓库
再看Jenkins上,可以看到自动构建部署任务,开始于gitlab的推送
再去web服务器查看,成功部署
在浏览器上成功访问到服务:http://10.0.0.12:8080/jpress-web-newest/
以上,成功实现,当程序员将代码push到gitlab上时,gitlab发现变动会自动推送到Jenkins上构建任务并运行。
Jenkins 的参数化构建
有时在项目构建的过程中,我们需要根据用户的输入来动态传入一些参数,从而影响整个构建结果,这时我们可以使用参数化构建。比如在原来Jenkinsfile中只指定了 master 分支,那么我们可以使用参数替换分支。
通过输入gitlab项目的分支名称来部署不同分支项目:
Jenkins设置参数化构建
web_demo_pipeline项目下点击配置->构建触发器->取消构建触发器勾选项点击应用 General ->勾选 This project is parameterized ->添加参数选择string Parameter名称branch
默认值master 描述请输入一个分支的名称 点击保存,此时左边菜单会多出一个Build with Parameter选项
添加参数,可以添加和删除多个参数,点击保存
向git传入分支传入代码。将原来的分支改成变量
将修改推送到gitlab,
点击构建参数任务
点击构建
构建成功
我再加两个参数,有个参数名字相同了,这样估计调用参数的时候不一定会是你要的那个值
点击构建,可以看到我们设置的参数。Jenkinsfile中使用了变量,就会调用这里的参数值。
原文链接:https://blog.csdn.net/weixin_53443677/article/details/125518696
原文链接:https://blog.csdn.net/qq_15290209/article/details/126230624
https://blog.csdn.net/qq_27229113/article/details/125522388
https://blog.csdn.net/weixin_39850981/article/details/111257716
https://blog.csdn.net/weixin_48404074/article/details/125250175