Jenkins简介
介绍
jenkins是一个开源的、提供友好操作界面的持续集成工具(CI),起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控一些定时执行的任务。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。通常与版本管理工具(SCM)、构建工具结合使用:常用的版本控制工具有SVN、GIT,构建工具有Maven、Ant、Gradle。
持续集成
开发中,我们经常遇到一些奇怪问题,比如本地可以编译成功的代码但是同事们更新代码后编译出错,或者在项目有多个Target的时候,资源文件只添加到了当前的Target,另外一个Target这个时候是不能正常编译的,再比如写的工具类,被同事改了,或者自己有改动,很多地方用到了,怎么保证这个类的行为没有发生变化而影响到项目中的其它模块呢?诸如此类。 那么这些问题原因在哪,可否避免呢?当然是可以避免的,如果代码有新的改动,提交到版本库中的时候,有一个人帮我们检查必要事项,然后做做测试不就好了,这个当然是可以的,前提是老板同意专门招一个这样的人 引起各种奇怪问题的原因有很多,比如开发环境比较复杂不干净,IDE的bug,提交前有一些必要的检查需要做,但是开发时因为各种原因没做,这些机械重复的事情我们可以找一个工具来帮我们完成,而且这个工具跑在一个专门的服务器上,该服务器环境相对干净,可以运行一些自动化操作,而自动编译,代码检查,测试等环节,那么这种东西,就是接下来讲的[持续集成]。
是什么
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成,每次的集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早发现集成错误。简单来说,就是持续的定时的在多个团队成员的工作中进行集成,并且给予反馈。 持续集成需要开发人员一天多次的将代码集成到主干,并进行自动化编译、测试等操作,由于这种频繁集成,以及集成后及时开始的编译和测试,可以有效避免我们在提交代码时没有进行必要检查而导致的错误,以及一些超出预期效果的更改,从而保证代码的质量。 由于这种及时性,如果在一次提交后项目集成失败,可以快速的在这次提交中查找问题所在,缩小了找问题的范围,从而减少了一些debug时间。同时如果按照这种实践,那么我们的主干代码时刻都是正确的,这样我们可以更频繁的交付。
为什么
代码语言:javascript复制一般规模较小的项目,对外部系统的依赖和服务调用很小,对于软件的集成不是问题。但是随着软件复杂度的增加,对集成提出了更多的要求,持续集成的好处就体现出来了。
# 1> 对重复的编译发布等操作进行抽象,减少重复过程。
# 2> 及早发现各种冲突和错误,减少风险。
# 3> 任何时间、任何地点生成可部署的软件
怎么做
基本要求:要将这种实践付诸实际,需要一些必要的条件,如下 1> 一个自动构建过程,包括自动编译、分发、部署和测试等 2> 一个代码存储库,即需要版本控制软件来保障代码的可维护性,同时作为构建过程的素材库。 3> 一个持续集成服务器。 自动化构建成过程,可帮助我们节省大量时间,完成这个过程的自动化后,在以后的开发过程中,我们需要做的,就是只是提交代码到版本库中,构建自动完成,基本不再需要人工干预。 代码仓库作为构建的素材库,构建所需的代码从代码库中获得。 最好有一台服务器单独作为持续集成服务器,一方面保证了环境的纯净,一方面不影响开发,而且持续集成服务器一般是随时准备开始构建的,所以一般也不关机。 首先要有统一的代码库,服务器不断从版本控制服务器上检查代码状态,看代码是否有更新。如果发现有代码更新,那么就从版本控制服务器下载最新的代码。等代码完全更新以后,调用自动化编译脚本,进行代码编译。然后运行所有的自动化测试,并且进行代码分析。如果其中任何一个步骤失败,就表示build失败,持续集成服务器会给予响应的反馈。每次代码提交之后,都会在持续集成服务器上触发一个定时构建,然后进行编译、部署。
原则
1.开发人员必须及时向版本控制库中提交代码,也必须经常性地从版本控制库中更新代码到本地; 2.需要有专门的集成服务器来执行集成构建。根据项目的具体实际,集成构建可以被软件的修改来直接触发,也可以定时启动,如每半个小时构建一次; 3.必须保证构建的成功。如果构建失败,修复构建过程中的错误是优先级最高的工作。一旦修复,需要手动启动一次构建。 4.不更新构建失败的代码 开发人员及时的提交代码进行构建是符合上述实践的,及时拉取代码可以防止工作中的分支偏离主干分支太多。定时触发构建或者通过检测代码的修改情况在触发构建都是可以的,主要是根及时的构建新的代码。如果构建失败,则必要及时处理导致失败的问题,修复后重新构建。当然构建失败的代码就不要拉到本地了,会污染一个本来是可以运行的工作区。
持续集成工具
代码语言:javascript复制常见的持续集成工具如下:
jenkins
travis
gitlab
buddybuild
仅列举了一些典型的,Jenkins 是传统型的工具,前身是 Hudson,04 年到现在已经有十多年的历史,后几个是最近几年出现的新一批,多少都和容器技术有点关系,这里我们主要介绍 Jenkins,因为这个工具比较常用,各种开发实践都可以通过大量的插件来组合实现,可定制性好很多。
Jenkins有哪些功能
代码语言:javascript复制# 1.定时拉取代码并编译
# 2.静态代码分析
# 3.定时打包发布测试版
# 4.自定义额外的操作,如跑单元测试等
# 5.出错提醒
基本上都是持续集成实践中的要求和周边的一些实现措施,如提醒功能等,出错后及时提醒开发者修复,Jenkins 中通过配置 SMTP 配置信息(这个一般的邮件服务提供商都有提供),邮件模板等,创建事件触发器,在事件(如编译失败)发生时,及时发送邮件通知开发者,挺方便的。 Jenkins 有很多种触发构建的方式,如 webhook,定时更新代码等,同时可以在触发构建后执行自定义的构建操作,通过编辑自定义的构建脚本,几乎可以进行任何构建操作。
Jenkins部署
环境清单
代码语言:javascript复制* CentOS 7.3
* git-2.9.5.tar.gz
* Jenkins 2.203.war
* apache-tomcat-9.0.12.tar.gz
* jdk-8u151-linux-x64.tar.gz
* apache-maven-3.5.4-bin.tar.gz
初始化
代码语言:javascript复制mkdir -p /etc/yum.repos.d/backup
mv /etc/yum.repos.d/CentOS-* /etc/yum.repos.d/backup
curl -o /etc/yum.repos.d/163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo &>/dev/null
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum -y install ntpdate
ntpdate -b ntp1.aliyun.com
setenforce 0
sed -i '/^SELINUX=/ s/enforcing/disabled/' /etc/selinux/config
systemctl stop firewalld
systemctl disable firewalld
sed -i '/^GSSAPIAu/ s/yes/no/' /etc/ssh/sshd_config
sed -i '/^#UseDNS/ {s/^#//;s/yes/no/}' /etc/ssh/sshd_config
下载git.tar包安装
代码语言:javascript复制# Jenkins支持的git最低版本是1.8,使用rpm安装版本是1.8,这里采用源码安装使用2.9版本
# git官网下载最新版本GIT:
# https://mirrors.edge.kernel.org/pub/software/scm/git/
# 安装git 依赖包
yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
rpm -e git --nodeps # 卸载掉老版本git
tar xvf git-2.9.5.tar.gz -C /usr/local/src/
cd /usr/local/src/git-2.9.5/
make prefix=/usr/local/git all
make prefix=/usr/local/git install
# 修改/etc/bashrc配置文件末尾加入下面一行环境变量(建议针对用户生效,否则使用其他用户时候容易出问题)
tail -1 /etc/bashrc
export PATH=$PATH:$HOME/bin:/usr/local/git/bin
source /etc/bashrc
# 测试是否安装成功
git --version
git version 2.9.5
JDK环境部署
代码语言:javascript复制# jenkins对jdk版本有要求,不能用jdk9和10,且需要将系统自带的java环境清楚掉
# jdk下载地址
# http://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html
# 卸载系统自带的java环境
[root@jenkins-8 git-2.9.5]# rpm -qa |grep jdk
[root@jenkins-8 git-2.9.5]# java
bash: java: 未找到命令
# 解压安装jdk
tar xvf jdk-8u151-linux-x64.tar.gz -C /usr/local/
cd /usr/local/
mv jdk1.8.0_151/ jdk
# 修改/etc/bashrc配置文件,末尾加入下面一行环境变量.
tail -2 /etc/bashrc
JAVA_HOME=/usr/local/jdk
export PATH=$PATH:$JAVA_HOME/bin
source /etc/bashrc
java -version # 尽量不要用openjdk
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
部署Maven
代码语言:javascript复制# Maven官方下载地址
# http://mirror.bit.edu.cn/apache/maven/maven-3/3.5.4/binaries/
# 解压部署
tar xvf apache-maven-3.5.4-bin.tar.gz -C /usr/local/
mv /usr/local/apache-maven-3.5.4/ /usr/local/maven
# 修改/etc/bashrc配置文件,末尾加入下面一行环境变量
tail -3 /etc/bashrc
export M2_HOME=/usr/local/maven
export M2=$M2_HOME/bin
export PATH=$M2:$PATH:$HOME/bin:/usr/local/git/bin
source /etc/bashrc
# 测试maven是否安装成功
mvn -version
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:14 08:00)
Maven home: /usr/local/maven
Java version: 1.8.0_151, vendor: Oracle Corporation, runtime: /usr/local/jdk/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-514.el7.x86_64", arch: "amd64", family: "unix"
部署Tomcat
代码语言:javascript复制# tomcat官方下载地址: http://tomcat.apache.org/
# 解压部署
tar xvf apache-tomcat-9.0.12.tar.gz -C /usr/local/
mv /usr/local/apache-tomcat-9.0.12/ /usr/local/tomcat
tail -1 /etc/profile
CATALINA_HOME=/usr/local/tomcat
source /etc/profile
# 增加熵池大小,解决Tomcat在CentOS7巨慢的问题,具体原因请看Tomcat章节
yum -y install rng-tools
systemctl start rngd && systemctl enable rngd
# 测试tomcat是否安装成功
/usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/jdk
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 14054 root 49u IPv4 34484 0t0 TCP *:webcache (LISTEN)
部署jenkins
代码语言:javascript复制# war包部署
# cp jenkins.war /usr/local/tomcat/webapps/
# 停掉tomcat在启动一遍
# 将Jenkins的war放到tomcat的webapps下面,重启一下tomcat自己就解压了,但是访问可能有点慢
# 也可以通过jar包直接启动jenkins
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname="192.168.8.2 " -jar jenkins-2.138.3.war &
# 也可以用jenkins的rpm包安装
wget https://pkg.jenkins.io/redhat-stable/jenkins-2.222.1-1.1.noarch.rpm
rpm -ivh jenkins-2.150.1-1.1.noarch.rpm
# Jenkins配置
grep -v "#" /etc/sysconfig/jenkins | grep -v "^$"
JENKINS_HOME="/var/lib/jenkins"
JENKINS_JAVA_CMD=""
JENKINS_USER="root"
JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname="149.129.38.117" "
JENKINS_PORT="8080"
JENKINS_LISTEN_ADDRESS=""
JENKINS_HTTPS_PORT=""
JENKINS_HTTPS_KEYSTORE=""
JENKINS_HTTPS_KEYSTORE_PASSWORD=""
JENKINS_HTTPS_LISTEN_ADDRESS=""
JENKINS_DEBUG_LEVEL="5"
JENKINS_ENABLE_ACCESS_LOG="no"
JENKINS_HANDLER_MAX="100"
JENKINS_HANDLER_IDLE="20"
JENKINS_ARGS=""
# 如果启动报错一般是你java不是openjdk的,修改下java路径即可
vim /etc/init.d/jenkins
candidates="
/etc/alternatives/java
/usr/lib/jvm/java-1.8.0/bin/java
/usr/lib/jvm/jre-1.8.0/bin/java
/usr/lib/jvm/java-1.7.0/bin/java
/usr/lib/jvm/jre-1.7.0/bin/java
/usr/bin/java
/usr/local/jdk/bin/java # 加上你的Java路径即可
"
代码语言:javascript复制cat /root/.jenkins/secrets/initialAdminPassword # 这个密码以后可能会用到最后记下来,这个文件往后初始化就没有了
2775b0adf72e42a5bdea22297b81dd82
# 2> 复制密码上面进入下一步会出现一个页面安装插件图2,
# 我们不弄太复杂,就安装推荐的插件,
# 安装时间较长,请准备良好的网络环境,可能需要翻墙
代码语言:javascript复制# 可能因为网络波动,会安装失败,重试几次,
# 如果还不行换服务器,比如云服务器。或者手机开热点,图3
至此,就可以开始使用Jenkins了
此时,我们能看到反向代理设置有误,但此时我们不配置反向代理,忽略即可
实现Jenkins自动拉取GitLab代码
通过点击Jenkins里面的构建项目能自动拉取GitLab代码
环境清单
代码语言:javascript复制* Jenkins 参照刚初始化环境即可
* GitLab 参考之前的GitLab安装
注意事项
代码语言:javascript复制*
*
*
到Jenkins安装gitlab插件
1.打开初始化好的Jenkins,点击系统管理,进入下一个页面
到可选插件装上GitLab Hook和GitLab两个插件,图2
2.回到初始化好的GitLab,此时我们没有项目的,我们创建一个项目
此时我们点击Create project后会出现图4中的报错,我们已经有了Jenkins了,不需要GitLab自带的CI,我们去把他关掉,默认是开启的,图4 至于第一行报错说将SSH密钥添加到个人资料前,你将无法通过SSH提取或推送项目代码,这个我们待会把Jenkins密钥填进去就好了.
我们找到Auto DevOps,点击Expand就会出现下面的扩展菜单,我们把Auto DevOps管道的钩去掉,然后点击保存更改即可,因为我们有了jenkins,所以不需要GitLab自带的CI集成消耗性能. 创建一个gitlab新用户Jenkins并添加至项目中具备管理权限 因为在管理员账号里面创建还要邮箱验证改密码麻烦,我们直接退出管理员账户,通过GitLab首页快速创建一个Jenkins用户,并退出,切换到root用户,将刚刚创建的jenkins拉到项目里面,图4
这里我们可以看到刚刚下拉栏刚刚创建的用户.
此时我们可以看到项目中有了Jenkins成员
接下来我们要将添加Jenkins服务器的(公钥)密钥到GitLab创建项目的Repository,让Jenkins对这个项目具有拉取代码的权限
# 我们到Jenkins生成一下公钥,并取出来
ssh-keygen
cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDrv0SM S8FR6NFMQbgYwEbeWOw54aSCthBqTnF4noswiItmPANslrQrzq469bicijLXyPZMASCwtpCupBUoirxNNEl WN8i2RJxQjXgMC2J1HJKXxTtwamr6xUDQyXtI2fZ5nty04dXfZScFB50GqO2KRp/o577fe i5 aMs3egDA1A2HosKcjjAChTj9LAa4V2tR23C9ANFEa1F7b2 SRewByzP163RVpB4XHSjMpe snS7JVwFQWrMwvNTFdwrGbj73mcLbQ5HHZunGJzxgO96sBGQc7Vj Tf18VYIu1iq2nSb5KDes4wPBaY9SuDX6M zDU8/FWiI7n2WjWBQAF root@jenkins**
# 接下来复制好公钥,按图5走
代码语言:javascript复制接下来我们验证下Jenkins能不能拉取代码,克隆该项目地址,到Jenkins机器 服务器第一次连接新服务器可能会出现yes和no,修改下面配置文件StrcHostKeyChecking ask 为下面哪一行,重启sshd服务就行了
vim /etc/ssh/ssh_config
# StrictHostKeyChecking no
# systemctl restart ssdd
[root@jenkins ~]# git clone git@192.168.144.139:root/jenkins-test-project.git
Cloning into 'jenkins-test-project'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
Checking connectivity... done.
[root@jenkins ~]# cat jenkins-test-project/README.md
# Jenkins Test Project # 这个就是我们刚刚创建项目的备注,说明Jenkins拉取GitLab代码免密是成功的.
# 接下来我们修改这个文件,并提交
echo "touch /root/zhou" >> jenkins-test-project/README.md
git config --global user.name "jenkins"
[root@jenkins ~]# git config --global user.email "jenkins@admin.com"
[root@jenkins ~]# cd jenkins-test-project/
[root@jenkins jenkins-test-project]# git add .
[root@jenkins jenkins-test-project]# git commit -m "add createfile.sh"
[master a2ce49e] add createfile.sh
1 file changed, 2 insertions( ), 1 deletion(-)
[root@jenkins jenkins-test-project]# git push -u origin master
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 288 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To 192.168.144.139:root/jenkins-test-project.git
62e54ed..a2ce49e master -> master
Branch master set up to track remote branch master from origin.
# 此处上传没有输入密码,说明Deploy Key是成功的.
接下来我们将Jenkins服务器的私钥保存到Jenkins的web中,用于让Jenkins本身可以使用服务器私钥进行交互.
此处我们看到 Gitlab Hook Plugin插件警告报错了,让我们将Gitlab API令牌以纯文本形式存储,此时我们先不管他,后面再弄
我们点击凭据配置,
代码语言:javascript复制此处我们选择私钥,我们去Jenkins找到私钥,复制到Private Key中
[root@jenkins ~]# cat /root/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA679EjPkvBUejRTEG4GMBG3ljsOeGkgrYQak5xeJ6LMIiLZjw
DbJa0K86uOvW4nIoy18j2TAEgsLaQrqQVKIq8TTRJfljfItkScUI14DAtidRySl8
U7cGpq sVA0Ml7SNn2eZ7ctOHV32UnBQedBqjtikaf6Oe 33voufmjLN3oAwNQNh
6LCnI4wAoU4/SwGuFdrUdtwvQDRRGtRe29vkkXsAcsz9et0VaQeFx0ozKXvrJ0uy
VcBUFqzMLzUxXcKxm4 95nC20ORx2bpxic8YDverARkHO1Y/k39fFWCLtYqtp0m
Sg3rOMDwWmPUrg1 jPsw1PPxVoiO59lo1gUABQIDAQABAoIBAECNEd8sCAUBFaLH
huOAGHiGZ5az/rQUhhyMksYtelixG5yyqOCHOrizkne6FA/TRHpTZcR9km6fnhXx
cb3K3clINhCY1fXvURml wLPPXVjFNDpLCLcFdUkeyJUpGMRzEmem5ZyOcRuyxjN
qiuAtvzAM1zWl/s1MMYbAyu8x4QpvPoVl8dYv3vq7nu6J6V5ssIRUE1DU6pP/7A2
C/7b QiJgBs7h1/2CHg
4u1UnxdO5hubGC3488P0UyHV9pwnI27/tRzVho0dIgx0W
tLDpjjZzmTlQILbtTaIgtQ2HosLGMux4igyUts2c3rJ HZB9T5PgA2/5KSj6eQDU
Zcl7rq0CgYEA mlSWcLX4ie6EYwPLI1VU3BZ OJkvto5IPuzbYi2nbWrNQFyV0NN
/WeWC9fk1noSvtzoXy 62yJ3/WydctRf/ dSo7 4S2pSWgCXWxIJTHYZbysQKnR2
EvgRz5FdGB1hi8Rs8OlnUajcgAKMguz cCCyrxfeXrhHVQipkd5IyxsCgYEA8QIq
HzsUvs 0SKmzmvTG9Nz/D YSgmvVwSUU0FRNNVU8E8ndSXQngOmsbdM4LrayE57m
QKuWAqz nk884LYYlwQKjnN1WLatG2CmjOTRJiuxzORhic5dbzGdE9PkZ600DM5X
d3BGdQIm4nM/ll0zLSnEgDK2LOL IluB TUV818CgYBnhxmz4JlOd w2ivhPDBOl
zoJ0Im1Sdng CbHx7B7L7yrcXD/AkiPxS10 gkCq54dOf5hWmi4foQ2IqdoiemlC
LIn/BymTjF6FtU7eKQPNJ9p2GpCxbLrQNt1uOoQJj0Qf 9Kqe2Tq3uxixCsBiifb
hbk6KJ0X/goHvvAUTZk81wKBgQDD3Tt4SB6S9 APUYM6goWSiGvtctBGF/cO0eD5
chmRJ2T8vAhP4ssb9EwCsS6uoCFW2sNLeWcfY5JF/CWAhdy0Fj yB1ktsMA8SK7y
QB9NgyMrXct7IDBE5rA Zezw6Q0s/yCMW72W6BnL3VenDrVBlfkxKoVtM0jPiUi2
zBK7xwKBgQDvdxxpenLjUC96z8HoReqr5yNrQZmxt3ZJko7XJNqUaT421 NOSf2H
pNFxN6HNlDck5MYJ3jfuiWa8JD2h7vlM8mAmNHk8djK3voXrZeuFpp5JZhqXQH4
qDIChcpsBteyhzOm fy5Wh05eWpmb2/fsX5IY49s56a7p50KPeGRLg==
-----END RSA PRIVATE KEY-----
此时,我们就获得了一个ssh认证的私钥文件,像一把要是去解gitlab上的公钥
接下来我们创建一个新项目,用来测试我们做的对不对
我们往下拉,点击git,下面做完记得点保存
此刻我们看到是成功的
接下来我们去Jenkins的工作空间看有没有GitLab的项目
[root@jenkins ~]# cd /root/.jenkins/workspace/you-men
[root@jenkins you-men]# cat README.md
# Jenkins Test Project
This is Jenkins Test Project
touch /root/zhou
# 此刻,说明我们做的Jenkins自动拉取GitLab上代码是成功的
实现代码自动部署到测试环境
Jenkins点击构建项目能自动去GitLab上拉取代码并以Jenkins为中控机连接到测试环境并部署相关项目
Jenkins构建wordpress项目
代码语言:javascript复制往下拉,找到Build(构建)里面, 点击Execule shell(使用shell),这里面可以执行一条命令,是由jenkins执行,回车作为命令分隔符. 此处的39.108.140.0为中控机,但此处作为一个webserver使用,让他本地构建一次.当我们点击完save保存,这个项目就创建好了,我们需要到webserver(中控机)机器上创建wangle用户并设置密码.
[root@testa ~]# useradd wangle
[root@testa ~]# echo "123456" |passwd --stdin wangle
Changing password for user wangle.
passwd: all authentication tokens updated successfully.
[root@testa ~]# ssh-keygen
# 生成root用户的密钥对,root用户上传的是ssh-key是对整个仓库有修改删除的权限,
# 全权限.(如已经创建并使用,则无需再次创建)
[root@testa ~]# su - wangle # 切换到wangle用户
[wangle@testa ~]$ ssh-keygen
# 生成wangle用户的密钥对,wangle用户我们需要让他添加到deploy key里面,
# 让我们有拉取的权限,让开发者有拉取并上传上去的权限.
若此处出现403报错,权限问题拒绝,则按f5刷新页面重新登录操作,原因是jenkins登录超时了
GitLab创建wordpress项目
此刻我们看到每创建一个项目这个管道都是默认开启,我们把它关掉,占用系统资源,而且我们有Jenkins集成,不用他自带的,进入提示的设置将ta关掉,或者进入项目齿轮(Settings)设置找到CI/CD里面的Auto DevOps,参照Jenkins流水线一.
接下来我们找到项目的Repository,找到里面的Deploy Keys,将刚刚我们webserver机器上的wangle用户的公钥添加到这里.
代码语言:javascript复制[wangle@testa ~]$ cat /home/wangle/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUWa54eoOiEYTZKalbSeH3b3eIxc8Qu6Mbu9Tf/5FGQMdPjygdwycIyn2fRhM4VLO67GZg805dsNY0OVvyBtPwTr fjHtvH/qJPhRRQhkaZchg8lEaHcDE06Q5z/NPFdTzVbwsx/IuMfaqXeO1PmhFf4ovt2iSokjd94AKYgImuVRcKCMOyCPiVnp2AJVUPThZ1tcZO/6tkf4bcsYsATQl8emUvDZM56aK4enTl2dOwDmqyCxPkYfggUrXP7FnARuDYV0IWm1QD5ip1zDogN7NFjESJWySePYG9QZkCu/102oKvKpgHwy5DtMoL/V v1r4PMjYDTM1 rZ73RrED9p5 wangle@testa
接下来我们新建一个wangle用户,给开发用,为了避免邮箱验证改密码,我们直接注销再创建一个,并登陆进去,然后退出登录,切换到root用户登陆. 我们刚刚创建的wangle的GitLab用户添加到项目里面并给他开发者权限,配置什么时候到期.
WebServer服务器验证是否能拉取代码过来
代码语言:javascript复制webserver服务器切换成root用户装git,待会克隆仓库用,普通用户还没有管理员权限,装好后我们切换回去
[root@testa ~]# yum -y install git
[root@testa ~]# su - wangle
[wangle@testa ~]$ git clone git@116.196.83.113:root/wordpres.git
Cloning into 'wordpres'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
[wangle@testa ~]$ ls wordpres/ # 至此,说明拉取代码免密是没有问题的
README.md
# 接下来我们模拟上传一个网站php代码
[wangle@testa ~]$ git config --global user.name "wangle" # 此时的用户名为之前GitLab创建的普通用户,开发
[wangle@testa ~]$ git config --global user.email "wangle@163.com"
[wangle@testa ~]$ curl -o wordpress.tar.gz https://wordpress.org/latest.tar.gz # 我们去下载一个wordpress网站源码
[root@testa ~]# wget https://wordpress.org/latest.tar.gz # 速度可能有点慢.
# 下载源码wordpress网站出了点问题,报错429请求过多
[wangle@testa ~]$ ls # 此时当前目录有两个wordpres,一个是源码,一个是git仓库,还有一个是project,是为了把wordpress-4.8.tar.gz源码包解压出来的源码放到project做一个中转,不要弄混淆了
project wordpres wordpress-4.8.tar.gz
[wangle@testa ~]$ tar xvf wordpress-4.8.tar.gz -C project/
[wangle@testa ~]$ ls project/
wordpress
[wangle@testa ~]$ cp -rf project/wordpress/* wordpres/ # 将project目录下wordpress下的源码放到git仓库里面再提交.
[wangle@testa ~]$ cd wordpres
[wangle@testa wordpres]$ ls
index.php wp-admin wp-cron.php wp-mail.php
license.txt wp-blog-header.php wp-includes wp-settings.php
readme.html wp-comments-post.php wp-links-opml.php wp-signup.php
README.md wp-config-sample.php wp-load.php wp-trackback.php
wp-activate.php wp-content wp-login.php xmlrpc.php
# 因为我们事先知道配置,我们先把数据库什么先修改好
[wangle@testa wordpres]$ vim wp-config-sample.php
define('DB_NAME', 'wordpres');
/** MySQL database username */
define('DB_USER', 'nginx');
/** MySQL database password */
define('DB_PASSWORD', 'flying');
/** MySQL hostname */
define('DB_HOST', 'localhost');
# 在此之前需要为一台机器准备一个LNMP环境
代码语言:javascript复制[root@testa ~]# cat lnmp.sh
#!/usr/bin/env bash
systemctl stop firewalld
echo "firewalld stop"
echo "shut SELinux"
sed -r '/^SELINUX/cSELINUX=disabled' /etc/selinux/config
setenforce 0
if [ ! -d /etc/yum.repos.d/backup ];
then
mkdir /etc/yum.repos.d/backup -p
fi
if ! ping -c2 www.baidu.com &>/dev/null
then
echo "You can't get on the net"
exit
fi
echo "Download 163 source ..."
echo "Download nginx Source package ..."
yum -y install wget
wget -O /etc/yum.repos.d/163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum repolist
if [ ! -f /etc/yum.repos.d/nginx.repo ];then
cat > /etc/yum.repos.d/nginx.repo <<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
fi
rpm -qa |grep nginx &> /dev/null
if [ ! $? -eq 0 ] ;then
echo "dafew"
yum -y install nginx
fi
sed -ri '/ *# *proxy *the *PHP/,/ *# *proxy_pass/ d' /etc/nginx/conf.d/default.conf
sed -ri '/ *#location/,/ *#}/ s/( *)#/1/' /etc/nginx/conf.d/default.conf
sed -ri s/" "*root" "*html;/\troot"t"\/usr\/share\/nginx\/html;/ /etc/nginx/conf.d/default.conf
sed -ri s/" "*index" "*index.html" "*index.htm;/"tt"index" "index.php" "index.html" "index.htm;/ /etc/nginx/conf.d/default.conf
sed -ri '/SCRIPT_FILENAME/c\tt fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;' /etc/nginx/conf.d/default.conf
sed -i '/ *location *~ * /\.ht/,/ *}/ d' default.conf
systemctl start nginx
################## 安装PHP / *######################## ** //
yum -y install php php-fpm php-mysql php-gd gd
echo "switch to the PHP terminal..."
systemctl start php-fpm
###################### 安装Mysql #####################
yum -y install mariadb-server
systemctl start mariadb
systemctl enable mariadb
mysqladmin password '123456'
mysql -uroot -p123456 -e "grant all on *.* to nginx@'%' identified by 'flying';"
cd /usr/share/nginx/html
cat >index.php <<EOF
<?php
phpinfo();
?>
EOF
代码语言:javascript复制# 接下来上传代码:
[wangle@testa wordpres]$ git add .
[wangle@testa wordpres]$ git commit -m "add wordpress project."
[wangle@testa wordpres]$ git push -u origin master
# 看到下图有那么多代码文件说明上传成功.
代码语言:javascript复制此刻,wangle用户对webserver拉取和上传代码都是免密,但是webserver的root用户还没有对GitLab免密.我们将root用户的公钥放到GitLab上刚刚给开发创建的wangle用户,这样只要是开发项目,开发对这个项目就是完全免密.
[root@testa html]# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLvKKqqAnCAcwwuwGjAuSfq4y/0Q ZNTPm0vx7w9LqjrBnO801T3m9MBORftDQod3Q7GutC2Gin0fsVM/3QaHtv FXMoMhJnRSFJJ5bEITEktrXGJAaTYByERTurLuagdDnTj7V5PDr2nrFL023NF0HutR7ckGPF Ong2PAF3exUbUTnYIPPXoPXqZ7FkVhTi lK1cysoJZ0rQXeGIWKgAadTM6WOfBg4 Apt0PeDNog3esNdJqw IKXvmj8 Z0vPiE7nAQwZo4yxYtllpd9VsbmzNoAlaBXkkUAMHHSoJN3crfJEMAyMdx37QaeOH35IyeSfhOPeRW3 SEs2VShf3 root@testa
我们登陆到GitLab的wangle用户
代码语言:javascript复制接下来将wangle用户提升为管理员权限,因为考虑到生产环境不能用root进行操作,因此我们对于普通用户的文件传输,需要添加到wheel组中
[root@testa html]# usermod -aG wheel wangle
[root@testa html]# id wangle
uid=1001(wangle) gid=1001(wangle) groups=1001(wangle),10(wheel)
[root@testa html]# vim /etc/sudoers.d/wangle
# 加入下面其中一行文件.
wangle ALL=(ALL) NOPASSWD: /usr/sbin/ssh
wangle ALL=(ALL) NOPASSWD: ALL # 目前尽量使用ALL,如果使用上面哪一行还要考虑脚本内容中的命令sudo提权,比如将wangle用户git clone下的代码复制到nginx根目录下,如果不给cp 提权就没法cp过去.
# 接下来我们试试是否可以普通用户提权免密
[root@testa html]# su - wangle
[wangle@testa ~]$ ssh root@39.108.140.0
root@39.108.140.0's password:
# 至此说明sudo提权是没有问题的.接下来我们去写一个脚本,
[wangle@testa ~]$ cat Deploy.sh
#!/usr/bin/env bash
# Author: ZhouJian
# Mail: 18621048481@163.com
#
# 拉取远程的仓库,GitLab的ssh的仓库地址
git clone git@116.196.83.113:root/wordpres.git
cd wordpres
# 由于我们多次部署,为了保证每次是最新的状态,进入到项目中,获取他的增量
git pull
# grant to wangle user permission.
sudo setfacl -m u:wangle:rwx /usr/share/nginx/html
sudo cp -rf /home/wangle/wordpres/* /usr/share/nginx/html/
# 注意此处的wordpress,因为之前创建项目少了个s,所以后面都要少了个s,总之要确定项目名一致.
# 因为是普通用户,执行任何管理员相关命令,必须加上sudo ,否则到时构建项目容易报错权限拒绝.
# 因为当前这台机器可以当成一个中控端,只需要有一个脚本就行了,我们给脚本一个权限,然后把项目代码都删掉,以达到项目效果.
[wangle@testa ~]$ chmod a x Deploy.sh
[wangle@testa ~]$ rm -rf wordpres*
# 接下来将Jenkins的root用户密钥认证到webserver的wangle用户,ssh-copy
[root@jenkins ~]# ssh-copy-id wangle@39.108.140.0
[root@jenkins ~]# ssh wangle@39.108.140.0
Last login: Sat Nov 9 12:41:11 2019 from 47.92.24.137
Welcome to Alibaba Cloud Elastic Compute Service !
[wangle@testa ~]$ # 测试成功,接下来测试下webserver能否解析php代码
[wangle@testa ~]$ sudo cat /usr/share/nginx/html/index.php
<?php phpinfo(); ?>
[wangle@testa ~]$ elinks --dump 39.108.140.0/index.php
# 如果出来很多信息关于PHP版本相关信息,说明可以执行php文件
[wangle@testa ~]$ cat /usr/share/nginx/html/index.php
<?php
$link=mysql_connect('39.108.140.0','nginx','flying');
if ($link)
echo "Successfully";
else
echo "Failed";
mysql_close();
?>
# 至此,说明执行php文件和数据库访问都是没有问题的
[wangle@testa ~]$ elinks --dump 39.108.140.0/index.php
Successfully
# 接下来我们直接去Jenkins里面构建项目,然后去观看控制台输出,根据提示解决报错,当然最好一次成功.
# 接下来访问webserver的网址,看能不能直接访问到网站
至此说明我们的Jenkins的一键部署是没有问题的
开发一提交GitLab代码,直接部署到生产环境
开发push代码,自动把代码发布到LNMP环境中,GitLab直接出发Jenkins构建
安装Jenkins的一个插件(认证我们的令牌)
代码语言:javascript复制# Build Authorization Token Root
# 在Jenkins产生一个令牌,这个令牌可以发放到GitLab服务器上,
# 当开发人员上传代码,GitLab会告诉Jenkins,
# 我项目改变了,你赶紧过来拉,产生了一个通信(隧道通信)
安装Build Authorzation Token Root插件
构建项目触发
代码语言:javascript复制[root@jenkins ~]# openssl rand -hex 12 # 生成一个令牌
2357086b89dc205d2333712d
[root@jenkins ~]# echo "2357086b89dc205d2333712d" > token.txt
# 我们将该令牌保存好,免得终端断了或者其他网络原因令牌弄丢了
[root@jenkins ~]# cat token.txt
2357086b89dc205d2333712d
# 接下来我们去配置之前的wordpres项目,构建触发器,
代码语言:javascript复制接下来配置GitLab webhook<点击Test显示200,201则表示成功> 进入GitLab调整一下网络认证身份,因为GitLab经过9版本后,对于GitLab和Jenkins的配合必须使用https配合,如果不是需要调整一下本地之间允许http认证
# 接下来我们进入wordpres项目,找到Settings,二级菜单找里面的Integrations(集成)
# 此处Token有两种方法,
# 方法一(手动)
# 里面的URL是填写Jenkins的URL地址,此处URL以Jenkins的回调地址为准,不管Test403,404都能到Jnekins看到,见图3
# http://<IP||域名>:8080/jenkins/project/wordpress/buildByToken/build?job=项目名称&token=身份令牌token值
http://47.92.24.137:8080/jenkins/project/wordpress/buildByToken/build?job=wordpress&token=2357086b89dc205d2333712d
此时,多数会报403错误,说明匿名灭有对项目的权限,我们到全局安全配置里面给匿名用户权限即可.
至此,整个Jenkins差不多完事了,还有一种Token方法,见方法二
打开GitLab的Push权限,上传代码进行测试
代码语言:javascript复制# 如果开发用户,push代码报错,没有权限的话,去图下面去开启一下
代码语言:javascript复制# 接下来我们准备一台Development机器,模拟开发上传代码,看jenkins能不能自动构建到生产环境
[root@develoment ~]# mkdir project
[root@develoment ~]# cd project
[root@develoment project]# yum -y install git &>/dev/null &
[1] 11437
# 我们用此机器模拟程序员的电脑向GitLab提交代码,接下来我们把此机器的公钥上传到GitLab
[root@develoment project]# ssh-keygen
[root@develoment project]# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2/r4mcwmNI0LC0ga3QiT9Ykz4MGAHcsNIBg1x8oRRv1YMgO36HHkAUunUIiL6JpkVm74Fhb0zL 23Y31fRNugomYZnwjHnEtMvv/4a/bpemdmDqAVWfG2tcJz2m8wSpL9ro0gGu8RdyLJg8dPyxv4KfOYo92KAdV9vzpJ2mxmONpv8H0QbYAc/KXK1XrlyXVTYb6CR1GYTmJEPCqTxSoGO9Cg WtVjy1bGf5ttWAgSDMGowYTjI8TEG5plUqU6X2AsoNRdQ2cvLcccAE/pE4Afh0BPWm/tiPr9mf6unpAv3Empvfp7G2hvqoZ5wg4VZzDIpzhqzpZO0MfFNRZfmgz root@develoment
# 复制好此公钥,然后到GitLab创建一个用户Develoment1,然后退出来切换到管理员将刚刚创建的用户Develoment1加入到项目.
接下来我们切换到Develoment1开发,让我们以开发身份登录到GitLab,然后把开发机器的公钥上传到开发者的GitLab的Settings
1
代码语言:javascript复制# 接下来我们试试Develoment开发这台机器能不能拉取GitLab仓库项目代码.
[root@develoment project]# git clone git@116.196.83.113:root/wordpres.git
[root@develoment project]# ls wordpres/
index.php wp-admin wp-cron.php wp-mail.php
license.txt wp-blog-header.php wp-includes wp-settings.php
readme.html wp-comments-post.php wp-links-opml.php wp-signup.php
README.md wp-config-sample.php wp-load.php wp-trackback.php
wp-activate.php wp-content wp-login.php xmlrpc.php
# 至此说明拉取代码是成功的
# 接下来我们修改一下代码,然后上传看jenkins能不能自动构建项目
[root@develoment project]# echo you-men >> wordpres/README.md
[root@develoment wordpres]# git config --global user.email "Develoment1@163.com"
[root@develoment wordpres]# git config --global user.name "Develoment1"
[root@develoment project]# cd wordpres/
[root@develoment wordpres]# git add .
[root@develoment wordpres]# git commit -m "modiy README.md file"
[root@develoment wordpres]# git push -u origin master
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 316 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@116.196.83.113:root/wordpres.git
8cec4a5..a99149f master -> master
Branch master set up to track remote branch master from origin.
# 将代码上传上去,然后去管理员账号的GitLab和Jenkins构建有不有变化
`
`
代码语言:javascript复制# 至此说明GitLab代码的确能上传到管理员的项目仓库,并且Jenkins构建也是成功的,然后我们登陆到lnmp的test生产环境看代码有不有变化,
[root@testa ~]# cat /usr/share/nginx/html/README.md
# wordpres
Deploy a PHP websiteyou-men
# 至此说明现在只要开发那天机器上传代码,Lnmp环境都能实时部署更新
# 接下来我们真实修改一下wordpress并实时查看网页变化.
代码语言:javascript复制比如说我觉得这个username不好听,我们去程序员电脑修改项目代码上传看能不能实时更新.
进入vim里面/查找username修改为ZHOUjian,然后Push上传,看看测试环境的lnmp的Nginx网站根目录能不能实时更新.
[root@develoment wordpres]# git add .
[root@develoment wordpres]# git commit -m "modiy install.php"
[master 05e3f02] modiy install.php
1 file changed, 1 insertion( ), 1 deletion(-)
[root@develoment wordpres]# git push -u origin master
`
代码语言:javascript复制# 接下来我们去生产环境看一下修改代码
[root@testa ~]# cat /usr/share/nginx/html/wp-admin/install.php |grep ZHOUjian
<th scope="row"><label for="user_login"><?php _e('ZHOUjian'); ?></label></th>
生产环境也实时能更新开发上传的代码,可以修改网站的一些表现,能在浏览器查看实时更新,效果更明显,但一些公司为了保险不会直接将jenkins对接生产环境,这个看业务需求了