再来看一下我们的微服务架构 , 每个组件都需要服务器去部署,加起来可能需要几十个甚至上百个服务器。这样的微服务项目在部署上会遇到什么问题?
问题:软件的迭代过程包括,设计,编码,编译,构建,测试,发布,运维等等流程,早期的软件开发模式为瀑布式开发,这种开发模式迭代更新太慢,每个环境都需要耗费大量人力和时间成本。往往很长时间才迭代一次。如今企业追求的都是敏捷开发:快速开发快速迭代,尽可能的缩短软件的开发生命周期。
DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件。
DevOps是一种方法或理念,它涵盖开发、测试、运维的整个过程。DevOps是提高软件开发、测试、运维、运营 等各部门的沟通与协作质量的方法和过程,DevOps强调软件开发人员与软件测试、软件运维、质量保障(QA)部 门之间有效的沟通与协作,强调通过自动化的方法去管理软件变更、软件集成,使软件从构建到测试、发布更加快 捷、可靠,最终按时交付软件。
DevOps是一套项目从开发到运维的解决方案,而不是具体的一个技术,DevOps需要整合一些列的技术来实现,比如:通过Git拉取代码,通过Mavn的命令进行项目的清理,编译,打包,测试等,通过Docker命令进行镜像构建…。
DevOps使用到的技术如:GitHub、Git/SVN、Docker、Jenkins、 Hudson、Ant/Maven/Gradle(编译,打包)、Selenium(自动化测试)、QUnit、JMeter(性能测试)等
下面普及2个概念
传统的瀑布式开发模型要求一个项目版本的所有功能都开发完成才会进行版本地迭代,这种开发模式不仅项目版本迭代速度慢,没法尽早的发现软件的质量问题,和持续的项目交付。
而敏捷开发最重要的目标是通过及早和持续不断地交付有价值的软件使客户满意;要达到这一目的就需要更高频率的版本迭代,包括:编译,打包,测试,运维。且应该自动化的完成,才有可能达到更快的软件开发生命周期。
敏捷与 DevOps 之间的主要区别在于:敏捷是关于如何开发和交付软件的哲学,而 DevOps 则描述了如何通过使用现代工具和自动化流程来持续部署代码。
云原生的定义最早也是由 Pivotal 公司的 Matt Stine 于 2013 年提出的,云原生是基于分布部署和统一运管的分布式云 [1] ,以容器、微服务、DevOps等技术为基础建立的一套云技术产品体系。 它具有:**DevOps、持续交付、微服务、容器、**等特点 。
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统做出频繁和可预测的重大变更。
Jenkins是一个开源的、可扩展的持续集成、交付、部署(软件/代码的编译、打包、部署)的基于web界面的平台。
起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不做解释)。
允许持续集成和持续交付项目,无论用的是什么平台,可以处理任何类型的构建或持续集成。
它可以在代码上传仓库(如github,gitee,gitlab)后,在jenkins(一个网站界面)中通过获取代码仓库中最新代码,进行自动化部署,而省去手动打包、上传服务器、部署这一系列步骤,非常方便。
Jenkins的特性
现在我们已经有docker的环境了,可以用来部署项目,现在我们只需要使用Jenkins实现一键部署即可,整体方案如下
上面的问题是安装docker和安装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
上面的操作已经将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 请注意版本
更改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账户继续
后面就一直下一步就可以了,安装完成后界面如下
根据推荐安装好插件后,还需安装一个maven 插件,登录jenkins,找到插件管理
然后在可用插件一栏中,搜索:Maven Integration 插件进行安装
接下来我们对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.
然后保存退出即可
给要部署的项目安装好打包插件,并指定项目的名字如:
<build>
<finalName>appfinalName>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
同时在项目根目录准备一个Dockerfile文件,内容如下
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"]
然后需要准备一个远程Git仓库,企业内部可能会选择搭建自己的Git私服,我这里就直接使用Gitee,把代码提送上去,如:
回到jenkins的最外层 - 点击 新建 item
选择构建一个自由软件 - 指定构建的项目名 ,拉后确定
进去之后,找到 源码管理 - 指定你的代码仓库地址 ,以及添加账号
填好之后往下滚动,找到构建环境 - 选择调用顶层Maven目标
然后指定maven版本和目标: clean install -Dmaven.test.skip=true 该命令是对项目进行打包
点击保存退出,然后点击立即构建 - 查看构建日志
日志如下 - jenkins从尝试安装maven,然后从git下载代码后,进行 : clean install -Dmaven.test.skip=true 命令执行
启动项目的原理是通过Dockerfile构建项目镜像,并自动启动容器 ,因为我们项目和jenkins在同一台服务器,所以我们用shell脚本运行项目,原理既是通过dockerfile 打包镜像,然后docker运行即可。接下来我们,修改jenkins任务配置 -
shell脚本如下:
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
解释:
然后执行构建,效果如下
然后回到docker,执行:docker ps 查看容器