目录
1、更新Jenkins中的jnlp-slave-pod模板镜像
之前有利用一个python项目myblog部署jenkins流水线,并通过jenkinslibrary进行模块化构建,本次创建一个java项目spring-boot,主要是熟悉下maven的构建方法以及library模版的应用
主要包括springboot项目创建、maven基本概念、tools镜像集成maven、jenkins调用k8s自动部署springboot项目等。本地 git pull 项目,修改代码提交,jenkins自动扫描分支有更新,调用k8s集群构建动态slave,k8s部署tools:v4容器进行流水线任务构建。
一、创建Spring Boot项目
1、创建一个hello word项目
下载IDEA软件,配置jdk环境
通过File > New > Project,新建工程,选择Spring Initializr
配置Project Metadata:
配置Dependencies依赖包:
选择:Web分类中的Spring web和Template Engines中的Thymeleaf
配置maven settings.xml:
默认使用IDE自带的maven,换成自己下载的,下载地址:
链接: 百度网盘 请输入提取码 提取码: 3gva
解压后放到D:\software\apache-maven-3.6.3
,修改D:\software\apache-maven-3.6.3\conf\settings.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>D:\opt\maven-repo</localRepository>
<pluginGroups>
</pluginGroups>
<proxies>
</proxies>
<servers>
</servers>
<mirrors>
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
</settings>
替换springboot版本为2.3.5.RELEASE
2、编写功能代码
创建controller包及HelloController.java
文件
package com.rui.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(String name) {
return "Hello, " + name;
}
@RequestMapping("/")
public ModelAndView index(ModelAndView mv) {
mv.setViewName("index");
mv.addObject("requestname", "This is index");
return mv;
}
@RequestMapping("/rightaway")
public ModelAndView returnRightAway(ModelAndView mv) {
mv.setViewName("index");
mv.addObject("requestname","This request is RightawayApi");
return mv;
}
@RequestMapping("/sleep")
public ModelAndView returnSleep(ModelAndView mv) throws InterruptedException {
Thread.sleep(2*1000);
mv.setViewName("index");
mv.addObject("requestname","This request is SleepApi"+",it will sleep 2s !");
return mv;
}
}
在resources/templates/
目录下新建index.html
<!DOCTYPE html>
<html>
<head>
<title>Devops</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div class="container">
<h3 th:text="${requestname}"></h3>
<a id="rightaway" href="#" th:href="@{/rightaway}" >立即返回</a>
<a id="sleep" href="#" th:href="@{/sleep}">延时返回</a>
</div>
</body>
</html>
保存并启动项目,在浏览器中访问localhost:8080/hello?name=haha
二、什么是maven
1、maven仓库的构建顺序
考虑一个常见的场景:以项目A为例,开发过程中,需要依赖B-2.0.jar的包,如果没有maven,那么正常做法是把B-2.0.jar拷贝到项目A中,但是如果B-2.0.jar还依赖C.jar,我们还需要去找到C.jar的包,因此,在开发阶段需要花费在项目依赖方面的精力会很大。
因此,开发人员需要找到一种方式,可以管理java包的依赖关系,并可以方便的引入到项目中。
maven如何工作
查看
pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
可以直接在项目中添加上dependency
,这样来指定项目的依赖包。
这样的话,使用maven的项目,只需要在自己的pom.xml中把所需的最直接的依赖包定义上,而不用关心这些被依赖的jar包自身是否还有别的依赖。剩下的都交给maven去搞定。
如何搞定?maven可以根据pom.xml中定义的依赖实现包的查找
去哪查找?maven仓库,存储jar包的地方。
当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:
1.1、本地仓库
-
Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。
-
运行 Maven 的时候,Maven 所需要的任何包都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的包。
-
默认情况下,不管Linux还是 Windows,每个用户在自己的用户目录下都有一个路径名为 .m2/respository/ 的仓库目录。
-
Maven 本地仓库默认被创建在 %USER_HOME% 目录下。要修改默认位置,在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>D:\opt\maven-repo</localRepository> </settings>
1.2、中央仓库
Maven 中央仓库是由 Maven 社区提供的仓库,中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。
中央仓库的关键概念:
-
这个仓库由 Maven 社区管理。
-
不需要配置,maven中集成了地址 http://repo1.maven.org/maven2
-
需要通过网络才能访问。
1.3、私服仓库
通常使用 sonatype Nexus来搭建私服仓库。搭建完成后,需要在 setting.xml中进行配置,比如:
<profile>
<id>localRepository</id>
<repositories>
<repository>
<id>myRepository</id>
<name>myRepository</name>
<url>http://127.0.0.1:8081/nexus/content/repositories/myRepository/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
1.4、阿里云maven
方便起见,我们直接使用国内ali提供的仓库,修改 maven 根目录下的 conf 文件夹中的 setting.xml 文件,在 mirrors 节点上,添加内容如下:
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
2、mvn生命周期
Maven有三套相互独立的生命周期,分别是clean、default和site。每个生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。
clean生命周期,清理项目
清理:mvn clean --删除target目录,也就是将class文件等删除
default生命周期,项目的构建等核心阶段
编译:mvn compile --src/main/java目录java源码编译生成class (target目录下)
测试:mvn test --src/test/java 执行目录下的测试用例
打包:mvn package --生成压缩文件:java项目#jar包;web项目#war包,也是放在target目录下
安装:mvn install --将压缩文件(jar或者war)上传到本地仓库
部署|发布:mvn deploy --将压缩文件上传私服
site生命周期,建立和发布项目站点
站点 : mvn site --生成项目站点文档
各个生命周期相互独立,一个生命周期的阶段前后依赖。 生命周期阶段需要绑定到某个插件的目标才能完成真正的工作,比如test阶段正是与maven-surefire-plugin的test目标相绑定了 。
举例如下:
mvn clean
调用clean生命周期的clean阶段
mvn test
调用default生命周期的test阶段,实际执行test以及之前所有阶段
mvn clean install
调用clean生命周期的clean阶段和default的install阶段,实际执行clean,install以及之前所有阶段
三、tools镜像集成maven
tools镜像用来k8s部署,生成jenkins-slave执行相关流水线任务,既然需要部署java项目,那就必须配置有maven命令。
1、获取tools镜像源码
tools: jenkins调用kubernetes动态生成slave部署https://blog.csdn.net/weixin_39855998/article/details/122051850?spm=1001.2014.3001.5501https://gitee.com/wanghongruihaha/tools.git 我们之前已经build过tools镜像,已实现python项目部署以及一些基础工具条件,再添加maven的配置即可。
2、tools镜像添加maven配置
-
为tools镜像集成mvn:
将本地的
apache-maven-3.6.3
放到tools
项目中,修改settings.xml
配置,此处存放maven下载的仓库包... <localRepository>/opt/maven-repo</localRepository> ...
然后修改Dockerfile,添加如下部分:
#-----------------安装 maven--------------------# COPY apache-maven-3.6.3 /usr/lib/apache-maven-3.6.3 RUN ln -s /usr/lib/apache-maven-3.6.3/bin/mvn /usr/local/bin/mvn && chmod +x /usr/local/bin/mvn ENV MAVEN_HOME=/usr/lib/apache-maven-3.6.3 #------------------------------------------------#
master节点拉取最新代码,构建最新的tools镜像
# k8s-master
$ git pull
$ docker build . -t 192.168.0.121:5000/myblog/tools:v4 -f Dockerfile
$ docker push 192.168.0.121:5000/myblog/tools:v4
四、Springboot服务镜像制作
通过mvn package
命令拿到服务的jar包后,我们可以使用如下命令启动服务:
$ java -jar demo-0.0.1-SNAPSHOT.jar
修改pom.xml配置默认jar包名字:
<groupId>com.rui</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<finalName>${project.artifactId}</finalName><!--打jar包去掉版本号--><build />
因此,需要准备Dockerfile来构建镜像:
FROM openjdk:8-jdk-alpine COPY target/springboot-demo.jar app.jar CMD [ "sh", "-c", "java -jar /app.jar" ]
执行镜像构建,验证服务启动是否正常:
$ docker build . -t springboot-demo:v1 -f Dockerfile $ docker run -d --name springboot-demo -p 8080:8080 springboot-demo:v1 $ curl localhost:8080
五、接入CICD流程
之前已经实现了shared-library,并且把python项目接入到了CICD 流程中。因此,可以直接使用已有的流程,把spring boot项目接入进去。
-
Jenkinsfile
-
deploy/deployment.yaml
-
deploy/service.yaml
-
deploy/ingress.yaml
Jenkinsfile
@Library('rui-devops') _
pipeline {
agent { label 'jnlp-slave'}
options {
timeout(time: 20, unit: 'MINUTES')
gitLabConnection('gitlab')
}
environment {
IMAGE_REPO = "192.168.0.121:5000/myblog/springboot-demo"
IMAGE_CREDENTIAL = "credential-registry"
DINGTALK_CREDS = credentials('dingTalk')
PROJECT = "springboot-demo"
}
stages {
stage('checkout') {
steps {
container('tools') {
checkout scm
}
}
}
stage('mvn-package') {
steps {
container('tools') {
script{
sh 'mvn clean package'
}
}
}
}
stage('docker-image') {
steps {
container('tools') {
script{
devops.docker(
"${IMAGE_REPO}",
"${GIT_COMMIT}",
IMAGE_CREDENTIAL
).build().push()
}
}
}
}
stage('deploy') {
steps {
container('tools') {
script{
devops.deploy("deploy",true,"deploy/deployment.yaml").start()
}
}
}
}
}
post {
success {
script{
devops.dingsuccess()
}
}
failure {
script{
devops.dingfaile()
}
}
}
}
deploy/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-demo
namespace: dev
spec:
replicas: 1
selector:
matchLabels:
app: springboot-demo
template:
metadata:
labels:
app: springboot-demo
spec:
containers:
- name: springboot-demo
image: {{IMAGE_URL}}
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
resources:
requests:
memory: 100Mi
cpu: 50m
limits:
memory: 2000Mi
cpu: 100m
livenessProbe:
httpGet:
path: /
port: 8080
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 15
timeoutSeconds: 3
readinessProbe:
httpGet:
path: /
port: 8080
scheme: HTTP
initialDelaySeconds: 120
timeoutSeconds: 2
periodSeconds: 15
deploy/service.yaml
apiVersion: v1
kind: Service
metadata:
name: springboot-demo
namespace: dev
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: springboot-demo
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
deploy/ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: springboot-demo
namespace: dev
spec:
rules:
- host: boot.rui.com
http:
paths:
- backend:
serviceName: springboot-demo
servicePort: 8080
path: /
status:
loadBalancer: {}
目录结构如下:
[root@k8s-master springboot-demo]# ll
总用量 12
drwxr-xr-x 2 root root 66 1月 6 22:15 deploy
-rw-r--r-- 1 root root 107 1月 5 23:24 Dockerfile
-rw-r--r-- 1 root root 1688 1月 6 21:26 Jenkinsfile
-rw-r--r-- 1 root root 1687 1月 6 22:10 pom.xml
drwxr-xr-x 4 root root 28 1月 5 22:51 src
drwxr-xr-x 2 root root 6 1月 6 22:05 target
六、jenkins配置流水线
1、更新Jenkins中的jnlp-slave-pod模板镜像
更新tools镜像版本为我们部署的包含maven命令的镜像
由于镜像中maven的目录是/opt/maven-repo
,而slave-pod是执行完任务后会销毁,因此需要将maven的数据目录挂载出来,不然每次构建都会重新拉取所有依赖的jar包:
2、配置jenkins流水线任务
配置多分支流水线,类似之前myblog项目配置的即可
3、提交代码自动构建cicd
本地 git pull 项目,修改代码提交,jenkins自动扫描分支有更新,调用k8s集群构建动态slave,k8s部署jenkins/inbound-agent:4.3-4和tools:v4容器进行流水线任务构建。
本地hosts配置域名解析,测试cicd部署的容器是否正常
七、镜像以及源码
springboot源码:
https://gitee.com/wanghongruihaha/springboot-demo.githttps://gitee.com/wanghongruihaha/springboot-demo.git
springboot镜像:
docker pull registry.cn-hangzhou.aliyuncs.com/devlop01/spring-boot:v1