03-kubesphere流水线搭建
前言
及时清醒,事事甘心
9.流水线
参考:https://gitee.com/tanqidi/gulimall
9.1第一步gitee拉取代码
官方demo地址:https://github.com/kubesphere/devops-java-sample/blob/master/Jenkinsfile-online

选择peng-mall-devops,创建流水线

这里默认无需修改,点击创建

选择新建的流水线peng-mall-cicd,选择编辑流水线

选择自定义流水线

选择node,选择maven

添加步骤

新建码云凭证,我已经创建过了,自己输入自己的账号即可

添加步骤完成

选择编辑Jenkinsfile,查看代码
pipeline {
agent {
node {
label 'maven'
}
}
stages {
stage('拉取代码') {
agent none
steps {
dir('code/peng-mall-parent') {
git(url: 'https://gitee.com/xxxxx/peng-mall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)
}
}
}
}
}

我这里因为项目代码有几层其他的目录,所以加了dir('code/peng-mall-parent'){}命令,代表拉取code/peng-mall-parent目录下的代码,没有别的目录层级的话删除即可

选择活动,选择运行,我这里已经运行成功了

点击运行记录进去,可以查看日志

9.2第一步-参数化构建&环境变量
9.2.1参数化构建
选择编辑Jenkinsfile,添加版本号参数,默认为v0.0Beta
parameters {
string(name: 'PROJECT_VERSION', defaultValue: 'v0.0Beta', description: '')
}

选择编辑流水线,选择添加步骤,选择shell,然后把PROJECT_VERSION参数输出
echo $PROJECT_VERSION

选择编辑操作、编辑配置、添加参数、选项参数,添加PROJECT_NAME参数,他的值是
gulimall-gateway
gulimall-auth-service
gulimall-cart
gulimall-coupon
gulimall-member
gulimall-order
gulimall-product
gulimall-search
gulimall-seckill
gulimall-third-party
gulimall-ware

代码

parameters {
string(name: 'PROJECT_VERSION', defaultValue: '1.0.0', description: '请输入版本号')
choice(name: 'PROJECT_NAME', choices: ['gulimall-gateway', 'gulimall-auth-service', 'gulimall-cart', 'gulimall-coupon', 'gulimall-member', 'gulimall-order', 'gulimall-product', 'gulimall-search', 'gulimall-seckill', 'gulimall-third-party', 'gulimall-ware'], description: '请选择服务名称')
}
选择运行

查看日志,变量已经成功输出

9.2.2环境变量
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sona-qube'
}

9.3第二步-Sonar代码质量分析
官方demo全局配置文件:https://github.com/kubesphere/devops-java-sample/blob/master/configuration/settings.xml

完整配置见9.4
9.4第二步-Sonar代码质量分析&调试完成
9.4.1错误记录
参考:https://www.jianshu.com/p/bed574ae9ccc

查看jenkin配置的sona的token是够正确
# curl -u YOUR_SONAR_TOKEN: "http://SONARQUBE_HOST/api/projects/search"
curl -u b36a45e8c313beb1c99b9924082deed039bf1861: "http://192.168.188.181:32467/api/projects/search"
查看sona服务
kubectl get pod -n kubesphere-devops-system
查看jenkins地址:http://192.168.188.181:30180/sonarqube-webhook/
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/sonarqube-webhook/
查看sonaqube地址:http://192.168.188.181:30180
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services sonarqube-sonarqube)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT

Checking status of SonarQube task 'AZJJSjLVHdLHyflgZstE' on server 'sonar' java.lang.IllegalStateException: Unable to parse response from http://192.168.188.181:32467//api/ce/task?id=AZJJSjLVHdLHyflgZstE:
请求http://192.168.188.181:32467//api/ce/task?id=AZJJSjLVHdLHyflgZstE返回的是个html,不是json结果,是我jenkins地址配置错误,多个'/'

9.4.2配置
pom.xml的sona配置
https://github.com/kubesphere/devops-java-sample/blob/master/pom.xml
<sonar.jacoco.reportPaths>${PWD}/./target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.groovy.binaries>target/classes</sonar.groovy.binaries>

还有下面打包的部分

下面是完整配置
Jenkinsfile
pipeline {
agent {
node {
label 'maven'
}
}
parameters {
string(name: 'PROJECT_VERSION', defaultValue: '1.0.0', description: '请输入版本号')
choice(name: 'PROJECT_NAME', choices: ['gulimall-cart', 'gulimall-coupon', 'gulimall-member'], description: '请选择服务名称')
}
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
}
stages {
stage('拉取代码') {
agent none
steps {
git(url: 'https://gitee.com/peng_p/peng-mall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)
dir('code/peng-mall-parent') {
sh 'echo 正在构建:$PROJECT_NAME 版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'
container('maven') {
sh "echo 当前目录:`pwd`"
sh 'ls -al `pwd`'
sh "mvn clean install -U -Dmaven.test.skip=true -e -X -gs `pwd`/mvn-settings.xml"
}
}
}
}
stage('SonarQube 分析') {
steps {
dir('code/peng-mall-parent') {
container('maven') {
withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {
withSonarQubeEnv("sonar") {
sh "echo 当前目录:`pwd`"
// sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"
sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.login=$SONAR_TOKEN"
}
}
}
}
}
}
stage('阈值判断') {
steps {
script {
timeout(time: 1, unit: "HOURS") {
def qualityGate = waitForQualityGate()
if (qualityGate.status != 'OK') {
error "SonarQube 检测不通过: ${qualityGate.status}"
}
}
}
}
}
}
}
mvn-settings.xml
<settings>
<mirrors>
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
</settings>
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<sonar.jacoco.reportPaths>${PWD}/./target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.groovy.binaries>target/classes</sonar.groovy.binaries>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>agent-for-ut</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>agent-for-it</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<!-- 跳过单元测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.6.0.1398</version>
</plugin>
</plugins>
</build>
总算成功了

代码质量

9.5第三步-构建&推送镜像
9.5.1错误记录
java:8环境无法拉取

可以使用openjdk:8-jdk-alpine版本的镜像
但在 openjdk:8-jdk-alpine 镜像中,默认没有安装 bash,只有 sh。因此,bash -c 'touch /app.jar' 这条命令会失败。
你可以将 Dockerfile 中的 RUN bash -c 'touch /app.jar' 替换为 RUN touch /app.jar,这样可以直接使用 sh 来执行。
这里测试我只改了gulimall-cart/Dockerfile,后面所有服务都需要修改
FROM openjdk:8-jdk-alpine
EXPOSE 8080
VOLUME /tmp
ADD target/*.jar /app.jar
# RUN bash -c 'touch /app.jar'
# 使用 sh 替代 bash
RUN touch /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar", "--spring.profiles.active=prod"]

无法将镜像上传到docker hub
因为国内docker老是被墙(docker hub也保留,后面有机会再调通),所以这次上传到阿里云,因为流程都是一样的,只是配置一下阿里云的凭证和相关命令
阿里云配置见9.5.2

9.5.2配置阿里云镜像仓库
参考:https://www.cnblogs.com/makalochen/p/14240796.html

官方地址:https://cr.console.aliyun.com/cn-shanghai/instance/repositories

创建本地仓库

本地仓库创建完成

我们需要留意docker login 、docker pull、docker push 三条命令
需要留意自己的请求地址、命名空间、仓库名称、账号名称

9.5.3流水线配置阿里云
创建阿里云账号凭证,需要输入自己阿里云的账号密码

在环境变量添加自己阿里云的相关参数,分别是凭证(配置阿里云的账号密码)、请求地址、命名空间、仓库名称、账号名称
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
ALIYUN_CREDENTIAL_ID = 'aliyun-id'
ALIYUN_URL = 'crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com'
ALIYUN_NAMESPACE = 'pengpeng-namespace'
ALIYUN_ACCOUNT = 'pengpengservice'
}

创建阿里云的步骤,login和push地址拼对即可,tag版本号可以小点
stage ('构建镜像-推送阿里云') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker tag $BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}

步骤都是成功状态

push完成

9.5.4配置docker-hub
地址:https://github.com/kubesphere/devops-java-sample/blob/master/Jenkinsfile-online

需要修改的地方

代码
stage ('构建镜像-推送镜像') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
sh 'ls -al `pwd`'
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$DOCKER_CREDENTIAL_ID", )]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
查看自己能否正常登录docker hub
因为老是登不上,所以选择了上传阿里云
echo "YOUR_PASSWORD" | docker login --username YOUR_USERNAME --password-stdin

9.6第四步-流水线编写完成
- 构建镜像 & 推送快照镜像
- 推送最新镜像
- 部署到开发集群环境
- 发布版本
stage ('构建镜像 & 推送快照镜像') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 快照镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
stage('推送最新镜像'){
steps{
dir('code/peng-mall-parent') {
container ('maven') {
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
}
}
}
}
stage('部署到开发集群环境') {
steps {
dir('code/peng-mall-parent') {
input(id: "deploy-to-prod-$PROJECT_NAME", message: "是否将 $PROJECT_NAME 部署到开发集群环境?")
kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
}
stage('发布版本'){
when{
expression{
return params.PROJECT_VERSION =~ /v.*/
}
}
steps {
container ('maven') {
input(id: 'release-image-with-tag', message: '是否发布当前版本?')
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID",
passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh 'git config --global user.email "pengpeng6135@163.com" '
sh 'git config --global user.name "peng" '
sh 'git tag -a $PROJECT_NAME-$PROJECT_VERSION -m "$PROJECT_VERSION" '
// https://gitee.com/peng_p/peng-mall.git
sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_NAME/peng-mall.git --tags --ipv4'
}
}
}
}
修改每个服务k8s配置的镜像地址

9.7部署-移植数据库
创建mysql8的工作负载

选择指定工作负载吗,选择mysql8,暴露3302端口

选择外网访问,选择NodePort,选择开启会话保持

使用数据库连接工具,连接mysql8-node-port

把之前的数据全部导出来

新建数据库

把所有数据到入到k8s的数据库里

9.8流水线细节优化&解决OOM
重新创建一个流水线
peng-mall-jenkinsfile-cicd

选择代码仓库,这里选择Git

高级设置
如何Jenkinsfile不在根目录,可以指定位置
code/peng-mall-parent/Jenkinsfile

如果一开始运行没有选择分支、版本、项目名称,可以刷新,或者停止运行重新运行,要不然Jenkinsfile获取不到PROJECT_NAME项目名称

在Jenkinsfile中配置所有服务,数组第一个就是默认值
parameters {
choice(name: 'PROJECT_NAME', choices: ['gulimall-gateway', 'gulimall-auth-service', 'gulimall-cart', 'gulimall-coupon', 'gulimall-member', 'gulimall-order', 'gulimall-product', 'gulimall-search', 'gulimall-seckill', 'gulimall-third-party', 'gulimall-ware'], description: '请选择服务名称')
}

需要配置gulimall-gateway的镜像地址和端口
镜像地址是阿里云镜像地址,KubeSphere 的端口号范围是 30000 到 32767

容器OOMKilled,说明容器部署异常,内存溢出
原因:jvm启动的时候,分配内存过大,而k8s里面部署的限制是500Mi【xx-deploy.yaml】,导致内存溢出直接将pod给杀
解决:构建docker镜像的时候,约束微服务jvm最大占用内存
配置gulimall-gateway的Dockerfile

除了gulimall-gateway网关服务,剩下的服务都在service文件夹里面,所以这里加了一个判断

k8s配置这里也需要根据服务判断路径

9.9流水线部署所有微服务
完整Jenkinsfile
pipeline {
agent {
node {
label 'maven'
}
}
parameters {
string(name: 'PROJECT_VERSION', defaultValue: '1.0', description: '请输入版本号')
choice(name: 'PROJECT_NAME', choices: ['gulimall-gateway', 'gulimall-auth-service', 'gulimall-cart', 'gulimall-coupon', 'gulimall-member', 'gulimall-order', 'gulimall-product', 'gulimall-search', 'gulimall-seckill', 'gulimall-third-party', 'gulimall-ware'], description: '请选择服务名称')
}
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'peng-mall-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
GITEE_NAME = 'peng_p'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
ALIYUN_CREDENTIAL_ID = 'aliyun-id'
ALIYUN_URL = 'crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com'
ALIYUN_NAMESPACE = 'pengpeng-namespace'
ALIYUN_ACCOUNT = 'pengpengservice'
}
stages {
stage('拉取代码') {
agent none
steps {
git(url: 'https://gitee.com/peng_p/peng-mall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)
dir('code/peng-mall-parent') {
sh 'echo 正在构建:$PROJECT_NAME 版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'
container('maven') {
sh "echo 当前目录:`pwd`"
sh 'ls -al `pwd`'
sh "mvn clean install -U -Dmaven.test.skip=true -e -X -gs `pwd`/mvn-settings.xml"
}
}
}
}
stage('SonarQube 分析') {
steps {
dir('code/peng-mall-parent') {
container('maven') {
withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {
withSonarQubeEnv("sonar") {
sh "echo 当前目录:`pwd`"
// sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"
sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.login=$SONAR_TOKEN"
}
}
}
}
}
}
stage('阈值判断') {
steps {
script {
timeout(time: 1, unit: "HOURS") {
def qualityGate = waitForQualityGate()
if (qualityGate.status != 'OK') {
error "SonarQube 检测不通过: ${qualityGate.status}"
}
}
}
}
}
//stage ('构建镜像-推送镜像') {
// steps {
// dir('code/peng-mall-parent') {
// container ('maven') {
// sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
// sh 'ls -al `pwd`'
// sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
//
// withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$DOCKER_CREDENTIAL_ID", )]) {
// sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
// sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
// }
// }
// }
// }
//}
stage ('构建镜像 & 推送快照镜像') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
sh """
if [ "$PROJECT_NAME" = "gulimall-gateway" ]; then
cd $PROJECT_NAME && docker build -f Dockerfile -t "$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER" .
else
cd service/$PROJECT_NAME && docker build -f Dockerfile -t "$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER" .
fi
"""
// sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 快照镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
stage('推送最新镜像'){
steps{
dir('code/peng-mall-parent') {
container ('maven') {
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
}
}
}
}
stage('部署到开发集群环境') {
steps {
dir('code/peng-mall-parent') {
input(id: "deploy-to-prod-$PROJECT_NAME", message: "是否将 $PROJECT_NAME 部署到开发集群环境?")
// kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
script {
if (PROJECT_NAME == "gulimall-gateway") {
kubernetesDeploy(configs: "$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
} else {
kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
}
}
}
stage('发布版本'){
when{
expression{
return params.PROJECT_VERSION =~ /v.*/
}
}
steps {
container ('maven') {
input(id: 'release-image-with-tag', message: '是否发布当前版本?')
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID",
passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh 'git config --global user.email "pengpeng6135@163.com" '
sh 'git config --global user.name "peng" '
sh 'git tag -a $PROJECT_NAME-$PROJECT_VERSION -m "$PROJECT_VERSION" '
sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_NAME/peng-mall.git --tags --ipv4'
}
}
}
}
}
}
所有项目的Dockerfile是一样的
FROM openjdk:8-jdk-alpine
EXPOSE 8080
VOLUME /tmp
ADD target/*.jar /app.jar
# RUN bash -c 'touch /app.jar'
# 使用 sh 替代 bash
RUN touch /app.jar
ENTRYPOINT ["java", "-jar", "-Xms128m", "-Xmx300m", "/app.jar", "--spring.profiles.active=prod"]
【xx-deploy.yaml】需要修改镜像地址
镜像地址固定的,打包的时候就是发布最新的
$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest
端口号范围必须是 30000 到 32767,我这里都是31000-31019

创作不易,感谢支持。

9.2第一步-参数化构建&环境变量
浙公网安备 33010602011771号