1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
pipeline {
options {
gitLabConnection('gitlab')
gitlabBuilds(builds: ['拉取代码', '打包与检测代码', '制作镜像', '更新编排文件'])
}
environment {
PROJECT = '项目名'
BRANCH_NAME = '环境名(命名空间名)'
HARBOR_NAMESPACE = 'docker仓库凭据名称'
GIT_ID = 'git凭据名称'
GIT_URL = "https://git.xxx.com/${APP_NAME}.git(git的url)"
REGISTRY = '镜像仓库地址'
CHART_NAME = 'helm包名字'
DN = 'ingress一级域名'
SONARURL = "sonarqube地址"
SONARTOKEN = "sonarqube密钥"
STATUS_URL = "http://xx.cn//${BUILD_NUMBER}/status(Jenkins状态地址"
ARGO_URL = "https://git.xx.com/ops/argo.git(argo仓库地址)"
}
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
imagePullSecrets:
- name: docker-registry
hostAliases:
- ip: 11.0.98.50 #sonarqube ip
hostnames:
- sonar.rx.cn #sonarqube域名
containers:
- name: maven
image: harbor.rx.cn:80/rongxin/jenkins-slave:maven3-jdk-8-alpine
command: [\'cat\']
tty: true
volumeMounts:
- mountPath: /etc/localtime
name: agent-time
- mountPath: /usr/share/maven/conf/settings.xml
name: ks-devops-agent
readOnly: true
subPath: settings.xml
- mountPath: /root/.kube/config
name: kubeconfig
readOnly: true
subPath: config
- mountPath: /var/run/docker.sock
name: dockersock
readOnly: true
- mountPath: /etc/docker/daemon.json
name: dockerdaemon
readOnly: true
- mountPath: /opt/mvn_date/
name: agent-mvn-data
- mountPath: /root/.git-credentials
name: gitconfig
subPath: .git-credentials
- mountPath: /root/.gitconfig
name: gitconfig
subPath: .gitconfig
volumes:
- name: gitconfig
configMap:
name: gitlab
- name: kubeconfig
configMap:
name: kubeconfig
- name: ks-devops-agent
configMap:
name: ks-devops-agent
- name: agent-time
hostPath:
path: /etc/localtime
- name: dockersock
hostPath:
path: /var/run/docker.sock
- name: dockerdaemon
hostPath:
path: /etc/docker/daemon.json
- name: agent-mvn-data
persistentVolumeClaim:
claimName: ks-devops-agent-pvc
'''
}

}
stages {
stage('拉取代码') {
steps {
container('maven') {
updateGitlabCommitStatus name: '拉取代码', state: 'running'
git(credentialsId: "${GIT_ID}", url: "$GIT_URL", branch: "${BRANCH_NAME}", changelog: true, poll: false)
updateGitlabCommitStatus name: '拉取代码', state: 'success'
}
}
post {
failure {
updateGitlabCommitStatus name: '拉取代码', state: 'failed'
dingtalk (
robot: 'f28cdaa9-5379-470e-b715-7f126afbac34',
type: 'MARKDOWN',
title: 'xx项目',
text: [
'### xx项目${APP_NAME}拉取代码失败',
'[查看部署详情](${STATUS_URL})'
],
at: [
'13311528203'
]
)
}
}
}
stage('打包与检测代码') {
steps {
container('maven') {
updateGitlabCommitStatus name: '打包与检测代码', state: 'running'
sh '''
mvn clean package -U -Dmaven.test.skip=true sonar:sonar \
-Dsonar.projectKey=$APP_NAME-start \
-Dsonar.host.url=$SONARURL \
-Dsonar.analysis.branch=$BRANCH_NAME \
-Dsonar.login=$SONARTOKEN
'''
updateGitlabCommitStatus name: '打包与检测代码', state: 'success'
}
}
post {
failure {
updateGitlabCommitStatus name: '打包与检测代码', state: 'failed'
dingtalk (
robot: 'f28cdaa9-5379-470e-b715-7f126afbac34',
type: 'MARKDOWN',
title: 'xx项目',
text: [
'### xx项目${APP_NAME}打包与检测代码失败',
'[查看部署详情](${STATUS_URL})'
],
at: [
'13311528203'
]
)
}
}
}
stage('制作镜像') {
steps {
container('maven') {
updateGitlabCommitStatus name: '制作镜像', state: 'running'
withCredentials([usernamePassword(credentialsId : "${HARBOR_NAMESPACE}" ,passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USER' ,)]) {
sh '''
cat > Dockerfile << EOF
# 使用镜像
FROM harbor.rx.cn:80/rongxin/basic:java8
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
# 拷贝程序
ADD target/*.jar /var/app/
# 配置jvm
ENV JVM_PARAMS="-Xmx4096m -Xms4096m -Xmn1536m -Xss256k -XX:+UseConcMarkSweepGC -XX:+UseCompressedClassPointers -XX:+PrintGCDetails -XX:+PrintGC -XX:+PrintGCTimeStamps -Xloggc:/var/app/logs/$APPLICATION_NAME/gc/gc.log -verbose:gc"
#开放端口
EXPOSE 8080
EXPOSE 5000
ENTRYPOINT ["/sbin/tini","--"]
# 配置功能,不需要的删除就行
# JAVA_DEBUG_PROT,远程debug
# JAVA_AGENT,SkyWalking客户端
CMD java -jar -Dspring.profiles.active=\\$SPRING_PROFILES_ACTIVE \\$JVM_PARAMS \\$JAVA_START \\$JAVA_AGENT /var/app/*.jar
EOF
helm repo add --username $DOCKER_USER --password $DOCKER_PASSWORD prod-java8 http://harbor.rx.cn:80/chartrepo/rongxin
'''
}
withCredentials([usernamePassword(credentialsId : "aliyunas" ,passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USER' ,)]) {
sh '''
echo $DOCKER_PASSWORD | docker login ${REGISTRY} -u $DOCKER_USER --password-stdin
docker build --no-cache -t ${REGISTRY}/${PROJECT}/${APP_NAME}:${BRANCH_NAME}-1.${BUILD_NUMBER} .
docker push ${REGISTRY}/${PROJECT}/${APP_NAME}:${BRANCH_NAME}-1.${BUILD_NUMBER}
rm -rf *
'''
}
updateGitlabCommitStatus name: '制作镜像', state: 'success'
}
}
post {
failure {
updateGitlabCommitStatus name: '制作镜像', state: 'failed'
}
}
}
stage('更新编排文件') {
steps {
container('maven') {
updateGitlabCommitStatus name: '更新编排文件', state: 'running'
git(credentialsId: "${GIT_ID}", url: "${ARGO_URL}", branch: "${BRANCH_NAME}", changelog: true, poll: false)
sh '''
helm install ${APP_NAME} --version 0.0.1 prod-java8/prod-java8 -n ${PROJECT}-${BRANCH_NAME} --dry-run | sed -n "/serviceaccount.yaml/,/secretName: rongxin-cert/p" > ${PROJECT}/${APP_NAME}.yaml
git add .
git commit -m "更新项目:${PROJECT},服务:${APP_NAME},版本:${BUILD_NUMBER}"
git push -f -u origin ${BRANCH_NAME}
'''
updateGitlabCommitStatus name: '更新编排文件', state: 'success'
}
}
post {
failure {
updateGitlabCommitStatus name: '更新编排文件', state: 'failed'
}
success {
dingtalk (
robot: 'f28cdaa9-5379-470e-b715-7f126afbac34',
type: 'ACTION_CARD',
title: 'xx项目',
text: [
"### [xx项目${APP_NAME}更新编排文件成功,请在规定时间内负责人更新生产环境](${STATUS_URL}) ",
'---',
"- 任务:[${currentBuild.displayName}](${STATUS_URL})",
'- 状态:<font color=#00CD00 >成功</font>',
"- 持续时间:${currentBuild.durationString}".split("and counting")[0],
"> 更新内容: <br />- $changeString",
],
at: [
'@电话'
]
)
}
}
}
}
}
@NonCPS
def getChangeString() {
MAX_MSG_LEN = 100
def changeString = ""

echo "Gathering SCM changes"
def changeLogSets = currentBuild.changeSets
for (int i = 0; i < changeLogSets.size(); i++) {
def entries = changeLogSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
truncated_msg = entry.msg.take(MAX_MSG_LEN)
changeString += " - ${truncated_msg} [${entry.author}]\n"
}
}
if (!changeString) {
changeString = " - No new changes"
}
return changeString
}