k8s
springboot
jenkins
dockerfile-maven-plugin
pipline
maven
<plugin>
<groupId>com.spotifygroupId>
<artifactId>dockerfile-maven-pluginartifactId>
<version>1.3.6version>
<configuration>
<repository>demo/spring-boot-demorepository>
<tag>0.0.1tag>
<buildArgs>
<ZIP_FILE>target/${project.build.finalName}.jarZIP_FILE>
buildArgs>
configuration>
plugin>
说明:
repository 指定docker镜像的repo名称
tag 指定镜像的tag
buildArgs 指定Docerfile中使用的变量
更多的参数设置可以进入到xml的说明文档中查看,例如
contextDirectory 可以指定Dockerfile的路径,默认Dockerfile文件必须与pom文件在同一路径下。
服务使用了 java-jboss-openjdk8-jdk 的镜像作为基础环境,其中可以使用脚本自动计算容器的内存限制,为服务分配合理的内存。
Dockerfile 内容如下
FROM docker.io/fabric8/java-jboss-openjdk8-jdk:latest
USER root
ARG ZIP_FILE
ADD ${ZIP_FILE} /deployments/demo/
ENV JAVA_APP_DIR=/deployments/demo
#设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
chown -R jboss:root /deployments/aistation
USER jboss
WORKDIR /deployments
CMD [ "/deployments/run-java.sh" ]
说明
${ZIP_FILE} 是由dockerfile-maven-plugin的插件配置中buildArgs属性指定的
文件内容如下
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: ${project.artifactId}
name: ${project.artifactId}
namespace: ${_server.k8s.namespace}
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: ${project.artifactId}
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
name: ${project.artifactId}
spec:
nodeSelector:
node-role.kubernetes.io/master: ""
nodeName: node2
containers:
- env:
- name: TZ
value: Asia/Shanghai
image: '${_server.image}'
imagePullPolicy: IfNotPresent
name: ${_server.k8s.namespace}
ports:
- containerPort: ${_server.port}
livenessProbe:
tcpSocket:
port: ${_server.port}
timeoutSeconds: 30
volumeMounts:
- mountPath: /logs #日志路径,需要根据实际的路径指定
name: logs
volumes:
- name: logs
hostPath:
path: /usr/data/eureka/logs/ #日志路径,需要根据实际的路径指定
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
说明
文件中类似 ${_server.port} 的参数需要在pom.xml文件中定义,并且指定引用资源。在pom.xml中需要如下声明
<resource>
<directory>./directory>
<includes>
<include>**/*.yamlinclude>
includes>
<filtering>truefiltering>
resource>
部分自定义参数
<profiles>
<profile>
<id>K8S-TESTid>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
<properties>
<_server.port>8761_server.port>
<_server.image>${docker.image.prefix}/${project.artifactId}:${project.version}_server.image>
<_server.k8s.namespace>自己定义命名空间_server.k8s.namespace>
properties>
profile>
profiles>
其中directory标签指定打包后文件的路径,是相对target/classes文件夹的,当指定./时,其所在路径如下
include标签指定yaml文件的路径,是相对当前pom.xml文件的。
apiVersion: v1
kind: Service
metadata:
name: ${project.artifactId}
namespace: ${_server.k8s.namespace}
spec:
ports:
- name: ${project.artifactId}
port: ${_server.port}
targetPort: ${_server.port}
protocol: TCP
selector:
name: ${project.artifactId}
配置及注意事项与deployment.yaml相同
执行
mvn clean install dockerfile:build -Dmaven.test.skip=true
在执行前需要设置DOCKER_HOST的环境变量,否则会有如下错误
Caused by: com.spotify.docker.client.exceptions.DockerException: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:2375 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect
在windows中可以在cmd命令中执行
set DOCKER_HOST=tcp://<localhost>:2375
localhost 为docker所在的ip,在此之前需要先开放docker的2375端口
勾选项目中使用参数,如果没有此选项,需要在jenkins的插件管理中加入相关插件
增加相关参数如下
部署过程需要ssh远程操作并发送文件,所以需要配置ssh凭据
pipeline {
agent any
environment {
# 环境变量,在此处声明之后,不需要再另外设置系统的环境变量
DOCKER_HOST = "$DOCKER_HOST"
}
tools {
# 需要再jenkins的工具管理中设置maven 工具,否则需要单独指定maven环境
maven 'MAVEN'
}
stages {
stage('GIT PULL') {
steps {
echo "获取git代码:$GIT 分支:env.BRANCH"
# 需要在jenkins的凭据管理中设置git凭据,复制凭据的ID到此处使用
git branch: "$BRANCH", credentialsId: 'e3d1aa4f-d756-4064-8e23-dc7a1f6b0e66', url: '$GIT'
}
}
stage('BUILD') {
steps {
echo "MAVEN BUILD $DOCKER_HOST"
sh "mvn clean install dockerfile:build"
}
}
stage ('SSH CONNECT') {
steps {
script {
stage ('SSH AUTH') {
def remote = [:]
remote.name = 'K8S-MASTER'
remote.host = "${TARGET_HOST}"
remote.user = "${TARGET_USER}"
remote.allowAnyHosts = true
# 此参数指定文件在目标机器上的路径
def remotePath = "/mnt/demo/"+"${PROJECT_NAME}/"+"${PROFILE}"
withCredentials([sshUserPrivateKey(credentialsId: '192.168.100.57', keyFileVariable: 'identity', passphraseVariable: '', usernameVariable: 'userName')]) {
# 这两个参数是与上一行中定义的参数名对应,不要随意改动
remote.user = userName
remote.identityFile = identity
stage("SSH PUT FILE") {
sshCommand remote: remote, command: "mkdir -p ${remotePath}"
sshCommand remote: remote, command: "rm -rf ${remotePath}/*"
sshPut remote: remote, from: 'target/classes/k8s-deployment.yaml', into: "${remotePath}/"
sshPut remote: remote, from: 'target/classes/k8s-service.yaml', into: "${remotePath}/"
}
stage("BUILD DEPLOYMENT"){
sshCommand remote: remote, command: "kubectl apply -f ${remotePath}/k8s-deployment.yaml"
}
stage("BUILD SERVICE"){
sshCommand remote: remote, command: "kubectl apply -f ${remotePath}/k8s-service.yaml"
}
}
}
}
}
}
}
}