逃脱只会部署集群系列 —— jenkins实现Spring Boot项目构建

目录

一、创建Spring Boot项目

1、创建一个hello word项目

2、编写功能代码

​二、什么是maven

1、maven仓库的构建顺序

2、mvn生命周期

三、tools镜像集成maven

1、获取tools镜像源码

2、tools镜像添加maven配置

四、Springboot服务镜像制作

五、接入CICD流程

六、jenkins配置流水线

1、更新Jenkins中的jnlp-slave-pod模板镜像

2、配置jenkins流水线任务

3、提交代码自动构建cicd 

​ 七、镜像以及源码


        之前有利用一个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部署的容器是否正常

 七、镜像以及源码

tools源码:tools: jenkins调用kubernetes动态生成slave部署https://blog.csdn.net/weixin_39855998/article/details/122051850?spm=1001.2014.3001.5501https://gitee.com/wanghongruihaha/tools.git

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

猜你喜欢

转载自blog.csdn.net/weixin_39855998/article/details/122354473