一.敏捷开发相关概念
1.微服务的痛点
再来看一下我们的微服务架构 , 每个组件都需要服务器去部署,加起来可能需要几十个甚至上百个服务器。这样的微服务项目在部署上会遇到什么问题?
需要很多很多的服务器,服务器的采购安装,布线都很麻烦
每个服务都需要:编译,构建,打包,测试,发布,运维重复的工作量重复做
操作麻烦(编译,打包,测试,发布,上线等等都很麻烦)
2.什么是DevOps
问题:软件的迭代过程包括,设计,编码,编译,构建,测试,发布,运维等等流程,早期的软件开发模式为瀑布式开发,这种开发模式迭代更新太慢,每个环境都需要耗费大量人力和时间成本。往往很长时间才迭代一次。如今企业追求的都是敏捷开发:快速开发快速迭代,尽可能的缩短软件的开发生命周期。
DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件。
DevOps是一种方法或理念,它涵盖开发、测试、运维的整个过程。DevOps是提高软件开发、测试、运维、运营 等各部门的沟通与协作质量的方法和过程,DevOps强调软件开发人员与软件测试、软件运维、质量保障(QA)部 门之间有效的沟通与协作,强调通过自动化的方法去管理软件变更、软件集成,使软件从构建到测试、发布更加快 捷、可靠,最终按时交付软件。
DevOps是一套项目从开发到运维的解决方案,而不是具体的一个技术,DevOps需要整合一些列的技术来实现,比如:通过Git拉取代码,通过Mavn的命令进行项目的清理,编译,打包,测试等,通过Docker命令进行镜像构建...。
DevOps使用到的技术如:GitHub、Git/SVN、Docker、Jenkins、 Hudson、Ant/Maven/Gradle(编译,打包)、Selenium(自动化测试)、QUnit、JMeter(性能测试)等
下面普及2个概念
CI : Continuous Intergration : 持续集成 ,持续交付的核心意义:尽快的将最终的产品发布到线上环境,给用户使用。持续交付是每个企业追求的目标,我们常说的CI/CD里的CD一般指的就是持续交付
CD:Continuous Deployment :持续部署就是在持续交付的基础上,将编译、测试、打包部署到生产环境的过程做成自动化。
3.什么是敏捷开发
传统的瀑布式开发模型要求一个项目版本的所有功能都开发完成才会进行版本地迭代,这种开发模式不仅项目版本迭代速度慢,没法尽早的发现软件的质量问题,和持续的项目交付。
而敏捷开发最重要的目标是通过及早和持续不断地交付有价值的软件使客户满意;要达到这一目的就需要更高频率的版本迭代,包括:编译,打包,测试,运维。且应该自动化的完成,才有可能达到更快的软件开发生命周期。
敏捷与 DevOps 之间的主要区别在于:敏捷是关于如何开发和交付软件的哲学,而 DevOps 则描述了如何通过使用现代工具和自动化流程来持续部署代码。
4.什么是云原生
云原生的定义最早也是由 Pivotal 公司的 Matt Stine 于 2013 年提出的,云原生是基于分布部署和统一运管的分布式云 [1] ,以容器、微服务、DevOps等技术为基础建立的一套云技术产品体系。 它具有:**DevOps、持续交付、微服务、容器、**等特点 。
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统做出频繁和可预测的重大变更。
5.什么是jenkins
Jenkins是一个开源的、可扩展的持续集成、交付、部署(软件/代码的编译、打包、部署)的基于web界面的平台。
起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不做解释)。
允许持续集成和持续交付项目,无论用的是什么平台,可以处理任何类型的构建或持续集成。
它可以在代码上传仓库(如github,gitee,gitlab)后,在jenkins(一个网站界面)中通过获取代码仓库中最新代码,进行自动化部署,而省去手动打包、上传服务器、部署这一系列步骤,非常方便。
Jenkins的特性
开源的java语言开发持续集成工具,支持CI,CD;
易于安装部署配置:可通过yum安装,或下载war包以及通过docker容器等快速实现安装部署,可方便web界面配置管理;
消息通知及测试报告:集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知,生成JUnit/TestNG测试报告;
分布式构建:支持Jenkins能够让多台计算机一起构建/测试;
文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等;
丰富的插件支持:支持扩展插件,你可以开发适合自己团队使用的工具,如git,svn,maven,docker等。
二.Jenkins安装
1.方案设计
现在我们已经有docker的环境了,可以用来部署项目,现在我们只需要使用Jenkins实现一键部署即可,整体方案如下
在和安装了docker的服务器上安装好jenkins
程序员把代码提交到远程 git 仓库,jenkins可以自动从git仓库拉取代码到本地
jenkins安装好maven和jdk,然后执行 package 对代码进行打包如:app.jar
jenkins执行事先准备好的Dockerfile脚本构建docker镜像
jenkins执行shell脚本,根据镜像启动容器
上面的问题是安装docker和安装jenkins的服务器是同一个服务器,或者这样:
在服务器上安装好jenkins
程序员把代码提交到远程 git 仓库,jenkins可以自动从git仓库拉取代码到本地
jenkins安装好maven和jdk,然后执行 package 对代码进行打包如:app.jar
jenkins执行事先准备好的Dockerfile脚本构建docker镜像
jenkins把docker镜像推送到镜像仓库
安装了k8s的服务器,从docker镜像仓库中拉取镜像然后启动容器
2.安装jenkins
准备jenkins映射的目录
#创建jenkins文件映射目录 mkdir /var/jenkins_home #给目录设置权限 chmod 777 /var/jenkins_home
执行下面命令启动jenkins容器
docker run --privileged -d --name jenkins -p 9999:8080 -p 8888:8888 -p 50000:50000 \ -v /var/jenkins_home:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $(which docker):/bin/docker jenkins/jenkins:latest-jdk17
-d : 后台运行
-p 8088:8080 : 将容器的8080端口映射到宿主的8088端口
-v /var/jenkins_home:/var/jenkins_home : 将容器中/var/jenkins_home的目录挂载到宿主的/mnt/jenkins_home
-v $(which docker):/bin/docker : 将宿主的docker目录映射到容器内,以便在容器中能使用docker对应的命令完成自动化部署
上面的操作已经将docker相互映射,但在jenkins容器中直接执行docker的命令时,可能会报权限不足。这个问题是容器中的docker是通过docker.sock的方式与宿主的docker通信的,其对应的可执行用户为root。此时我们可以将 /var/run/docker.sock 的权限放开来解决此问题
chmod 777 /var/run/docker.sock
然后在linux机器的 /usr/local/src/jdk 目录安装好JDK, 以及在 /usr/local/src/maven 目录安装好maven 请注意版本
3.jenkins初始化
更改jenkins插件下载地址,因为默认是去国外网站下载插件比较慢,而且容易下载失败,我们修改插件下载地址为国内地址
cd /var/jenkins_home vi hudson.model.UpdateCenter.xml 修改地址为下面的地址 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
然后重启jenkins : docker restart jenkins
浏览器访问:http://服务IP:9999/ ,进入jenkins初始化页面
可以通过:docker logs jenkins 来查看密码 ,输入密码后,选择:安装推荐的插件
耐心等待安装完成进入下面界面,你可以创建一个新的管理员,或者使用admin账户继续
后面就一直下一步就可以了,安装完成后界面如下
4.安装插件
根据推荐安装好插件后,还需安装一个maven 插件,登录jenkins,找到插件管理
然后在可用插件一栏中,搜索:Maven Integration 插件进行安装
5.全局工具配置
接下来我们对maven做配置,找到 manager jenkins - tools
进去后,找到最下边的maven ,选择自动安装,如下
注意:如果采用jenkins自动安装方式可能会安装不上,我们可以自己解压一个maven到 -v 的目录中,然后设置好权限,比如:我上传了一个maven到linux中,然后他会自动同步到容器中去
然后设置权限
chmod -R 777 /var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/apache-maven-3.9.4
然后在全局工具设置出不要使用自动安装,而是指向上传的maven home.
然后保存退出即可
三.构建项目
1.项目导入插件
给要部署的项目安装好打包插件,并指定项目的名字如:
打包后项目名为: app.jar
<build> <finalName>app</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!--docker的maven插件,官网: https://github.com/spotify/docker‐maven‐plugin--\> </plugins> </build>
同时在项目根目录准备一个Dockerfile文件,内容如下
大概的意思是就是基于Dockerfile把项目打包成docker镜像,并随着容器启动自动启动项目
FROM meddream/jdk17:latest VOLUME /tmp ADD ./target/app.jar /app.jar ENV TZ=Asia/Shanghai EXPOSE 10010 #CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar ENTRYPOINT ["java", "-jar ", "/app.jar","--spring.profiles.active=prod"]
2.代码推送到远程
然后需要准备一个远程Git仓库,企业内部可能会选择搭建自己的Git私服,我这里就直接使用Gitee,把代码提送上去,如:
3.构建项目
回到jenkins的最外层 - 点击 新建 item
选择构建一个自由软件 - 指定构建的项目名 ,拉后确定
进去之后,找到 源码管理 - 指定你的代码仓库地址 ,以及添加账号
填好之后往下滚动,找到构建环境 - 选择调用顶层Maven目标
然后指定maven版本和目标: clean install -Dmaven.test.skip=true 该命令是对项目进行打包
点击保存退出,然后点击立即构建 - 查看构建日志
日志如下 - jenkins从尝试安装maven,然后从git下载代码后,进行 : clean install -Dmaven.test.skip=true 命令执行
4.启动项目容器
启动项目的原理是通过Dockerfile构建项目镜像,并自动启动容器 ,因为我们项目和jenkins在同一台服务器,所以我们用shell脚本运行项目,原理既是通过dockerfile 打包镜像,然后docker运行即可。接下来我们,修改jenkins任务配置 -
shell脚本如下:
注意: 这个 install 目录和构建jenins项目时取的名字保持一样
cd /var/jenkins_home/workspace/gateway/it-drive-service-gateway docker stop drive-gateway || true docker rm drive-gateway || true docker rmi drive-gateway || true docker build -t drive-gateway . docker run -id -p 10010:10010 --name drive-gateway drive-gateway:latest
解释:
/var/jenkins_home/workspace/gateway/it-drive-service-gateway :是jenkins拉取的代码目录
当执行jenins项目构建,jenkins会执行install把我们的代码打包为jar
然后执行上面脚本,脚本通过docker file 来构建镜像并启动容器
然后执行构建,效果如下
然后回到docker,执行:docker ps 查看容器
为了方便理解,下面整理了一个流程图
程序员吧IDEA的代码推送到GIT远程仓库
Jenkins通过Git客户端从Git仓库中拉取最新的代码
Jenkins执行maven命令打包项目:clean install
Jenkins执行脚本,cd到代码目录,执行docker build,根据Dockerfile 构建镜像
执行脚本 docker run 启动容器