如何使用 jenkins 将 spring 引导 jar 文件部署到 EC2?

How to deploy spring boot jar file to EC2 using jenkins?

我正在尝试将 spring 启动应用程序部署到 AWS EC2 实例。我看过很多博客和教程,完全解释了部署过程,这是可以理解的。我正在努力如何在 jenkins 中进行持续部署或交付,其中 spring 引导应用程序名称或 jar 文件名称随时间更改的主要功能。

我的管道

  pipeline {
    agent any

    tools{
       maven 'localmaven' 
    }
    stages {
        stage('Build') { 
            steps {
               sh 'mvn clean package' 
            }
            post {
               success {
                    echo 'Now Archiving...'
                    archiveArtifacts artifacts: '**/target/*.jar'
                   }
              } 
          }


    stage('Deliver') {
        steps {
             sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu'
             sh "sshpass -p password ssh -o StrictHostKeyChecking=no -i /var/lib/jenkins/secrets/mykey ubuntu@00.00.00.00 '/home/ubuntu/start.sh'"
        }
    }
}

}

服务器启动、停止和重启在shell脚本中处理。

我的start.sh

#!/bin/bash
nohup java -jar /home/ubuntu/aws-0.0.1-SNAPSHOT.jar > /home/ubuntu/log.txt 2>&1 &
echo $! > /home/ubuntu/pid.file

这完美地启动了我的服务器并且工作正常..

目前我的疑问是 start.sh 我使用相同的 jar 文件名所以它工作正常但在生产中版本更改 jar 文件名也改变了如何处理这种情况。 帮助我了解那个过程。我在哪里可以得到完整的想法和一切 提前致谢

我会说使用 build.finalName 将最终工件的名称保留为常量名称,并提供将构建版本保留在构建内部某处的规定。

据我所知,您使用 spring 引导,您可以使用 spring-boot-maven-pluginbuild-info 目标来保存构建的版本信息部分,如下所示。

  <build>
    <finalName>your-artifact-name</finalName>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>build-info</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

并通过执行器端点访问 Maven 构建信息 http://localhost:8080/actuator/info

或者,您可以通过使用以下命令查看 jar 文件来获取保存在 classpath:META-INF/build-info.properties 中的版本信息。

$> unzip -qc your-artifact-name.jar META-INF/build-info.properties
#Properties
#Fri May 04 17:43:06 IST 2018
build.time=2018-05-04T12\:13\:06.225Z
build.artifact=your-artifact-name
build.group=com.example
build.name=your-artifact-name
build.version=1.0.0.SNAPSHOT

这样即使文件被意外重命名,构建版本也不会改变。

您可以将文件名作为参数传递给 shell 脚本,即像这样修改 shell 脚本:

#!/bin/bash
nohup java -jar /home/ubuntu/ > /home/ubuntu/log.txt 2>&1 &
echo $! > /home/ubuntu/pid.file

然后您需要根据构建版本确定要使用的正确文件名,并将其作为参数传递给交付阶段的脚本。

您可以在执行 scp 时重命名文件

scp filename username@remote.host.net.:filenewname

你的情况是这样的

sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu:aws-0.0.1-SNAPSHOT.jar'

以上代码采用 jenkins 创建的任何构建版本,并在复制时将其重命名为 "aws-0.0.1-SNAPSHOT.jar",因此您不必修改 start.sh

P.S 通常,当您部署最终构建 (JAR) 时,请确保仅将 jar 名称添加为文件名的描述,而不是“-0.0.1-SNAPSHOT”

希望对您有所帮助:)

我必须说,您应该将工件的版本维护为非生产和生产部署的标准流程。通常在非产品环境中,您可以计划 SNAPSHOT 版本,在生产环境中,您应该选择 RELEASE 版本,可以使用 mvn release prepare release perform 使用 maven-release-plugin。它将为下一个后续版本提升您的 pom 版本。您可以将工件存储到 AWS S3 或 Artifactory 或 Nexus(以实现高可用性),例如您在此处引用的 ubuntu 机器。

现在我建议你应该添加一个名为 stage('Release') 的阶段,你应该使用 maven-release-plugin 来发布版本和将其存储到单独的路径,如

ubuntu@00.00.00.00:/home/ubuntu/RELEASE/${version}

并且根据你的阶段('Build')应该复制到另一个路径,如

ubuntu@00.00.00.00:/home/ubuntu/SNAPSHOT/${version}

您可以根据 Jenkins 管道的条件输入参数执行阶段“Release”和“Prod-Deliver”。 在您的情况下,这将是一个平滑 CICD 的可能解决方案。

   pipeline {
    agent any

    tools{
       maven 'localmaven' 
    }
    stages {
        stage('Build') { 
            steps {
               sh 'mvn clean install' 
            }
            post {
               success {
                    echo 'Now Archiving...'
                   }
              } 
          }

        stage('Release') { 
            steps {
               sh 'elease:prepare release:perform' 
            }
            post {
               success {
                    ////
                   }
              } 
          }

      stage('NonProd-Deliver') {
          steps {
               /*
               You can extract the version from pom.xml,replace you project location in jenkins workspace in the below command
               */
               sh 'version=$(echo -e 'setns x=http://maven.apache.org/POM/4.0.0\ncat /x:project/x:version/text()' | xmllint --shell ${YOUR_PROJECT_LOCATION}/pom.xml | grep -v /)'
               sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu/SNAPSHOT/${version}'
               sh "sshpass -p password ssh -o StrictHostKeyChecking=no -i /var/lib/jenkins/secrets/mykey ubuntu@00.00.00.00 '/home/ubuntu/start.sh nonprod $version'"
          }
      }

       stage('Prod-Deliver') {
        steps {
              /*
               For production release you should pass the version as a parameter to your jenkins pipeline which is going to be in production
               */
             sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu/RELEASE/${version} '
             sh "sshpass -p password ssh -o StrictHostKeyChecking=no -i /var/lib/jenkins/secrets/mykey ubuntu@00.00.00.00 '/home/ubuntu/start.sh prod ${version}'"
        }
    }

}
}

您必须在脚本文件中添加条件,如下所示

#!/bin/bash
release_type=
version=
if [[ ${release_type} == "prod" ]]; then
  # non snapshot release to production env
  nohup java -jar /home/ubuntu/RELEASE/${version}/aws-0.0.1.jar > /home/ubuntu/log.txt 2>&1 & 
else
  # snapshot release to non production env
  nohup java -jar /home/ubuntu/SNAPSHOT/${version}/aws-0.0.1-SNAPSHOT.jar > /home/ubuntu/log.txt 2>&1 &
fi
echo $! > /home/ubuntu/pid.file