前后端分离项目:微人事(SpringBoot+Vue)
源码GitHub:https://github.com/lenve/vhr
克隆Gitee:https://gitee.com/duolili/vhr
部署方式1:多个代码仓库
前后端分离部署,前端nginx,后端jar,均使用单独的代码库
准备
环境
jenkins 2.387.1
git 1.8.3.1
node 14.0.0(更高版本构建报错)
maven 3.9.1
k8s 1.26.0(containerd)
harbor 2.2.2
代码库
基于 https://gitee.com/duolili/vhr ,拆分成两个代码库,运行2个微服务:
- 前端:https://gitee.com/duolili/vhr-ui.git --master分支
- 后端:https://gitee.com/duolili/vhr-service.git --master分支
中间件
名称 | IP:PORT | 用户名 | 密码 | 备注 |
---|---|---|---|---|
MySQL(5.7.38) | 192.168.1.156:13306 | root | CloudEasy2020 | 新建空库:vhr |
Redis(6.7.2单机) | 192.168.1.156:16379 | 123456 | ||
RabbitMQ(3.8.11) | 192.168.1.156:15672 192.168.1.156:5672 | admin | CloudEasy2020 |
k8s
[root@master ~]# kubectl create ns test
[root@master ~]# kubectl create secret -n test docker-registry myregistrykey --docker-server=192.168.1.23:80 --docker-username=admin --docker-password=Harbor12345
代码库改造–后端
将源代码库中的 vhr 目录分离出来,新代码库命名:vhr-service
新库删除 mailserver 目录(用于新员工邮件通知,暂不使用),修改 pom.xml 文件,注释 mailserver jar
新库目录结构如下
├── Dockerfile
├── master-k8s
│ ├── Jenkinsfile
│ └── k8s.yaml
├── pom.xml
├── vhr.iml
└── vhrserver
├── pom.xml
├── vhr-mapper
│ ├── pom.xml
│ ├── src
│ │ └── ...
│ └── vhr-mapper.iml
├── vhr-model
│ ├── pom.xml
│ ├── src
│ │ └── ...
│ └── vhr-model.iml
├── vhrserver.iml
├── vhr-service
│ ├── pom.xml
│ ├── src
│ │ └── ...
│ └── vhr-service.iml
└── vhr-web
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └──...
│ │ └── resources
│ │ ├── application.yml
│ │ ├──...
│ └── test
│ └── ...
└── vhr-web.iml
修改文件
修改中间件连接信息 vhrserver/vhr-web/src/main/resources/application.yml
新增文件
- Dockerfile
#FROM java:openjdk-8
FROM 192.168.1.23:80/test/java:openjdk-8
ENV TZ=Asia/Shanghai
VOLUME /tmp
EXPOSE 8081
ENV JAVA_OPTS=$JAVA_OPTS
WORKDIR /home/apps/
ADD vhrserver/vhr-web/target/vhr-web-0.0.1-SNAPSHOT.jar .
ENTRYPOINT ["sh","-c","java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom,-Djava.awt.headless=true,-agentlib:jdwp=transport=dt_socket,address=0:8000,server=y,suspend=n -jar /home/apps/vhr-web-0.0.1-SNAPSHOT.jar"]
- master-k8s/Jenkinsfile
pipeline {
agent any
parameters {
string(name: "branch", defaultValue: "master", description: "code branch")
choice(name: 'module',choices: ['vhrservice'], description: 'module_name')
}
stages{
stage('setting env') {
agent any
options {
skipDefaultCheckout(true)
}
steps {
script {
env.NAMESPACE = "test"
env.PROJECT = "test"
env.IMAGE_NAME = "192.168.1.23:80/$PROJECT/$module:build-$BUILD_NUMBER"
}
}
}
stage('get code'){
steps{
git branch: '${branch}', credentialsId: '209653a1-f5b9-4214-bac8-a927c8b36060', url: 'https://gitee.com/duolili/vhr-service.git'
}
}
stage('vhrservice jar build'){
when {
environment name: 'module', value: 'vhrservice'
}
steps {
sh "mvn clean install"
//sh "mvn deploy -Dmaven.test.skip=true -U -e -X -B"
}
}
stage('vhrservice image build'){
when {
environment name: 'module', value: 'vhrservice'
}
steps{
script {
def imageName = docker.build("$IMAGE_NAME")
docker.withRegistry('http://192.168.1.23:80/','5ed303ec-6229-488d-aa73-847e1bb8ee6c'){
imageName.push()
}
sh "/bin/docker rmi ${IMAGE_NAME}"
}
}
}
stage('vhrservice deploy k8s'){
when {
environment name: 'module', value: 'vhrservice'
}
steps{
script {
sh "sed -i 's/<BUILD_TAG>/${BUILD_NUMBER}/g' master-k8s/k8s.yaml"
sh "/home/jenkins/bin/kubectl apply -f master-k8s/k8s.yaml -n ${NAMESPACE} --kubeconfig /home/jenkins/.kube/config --record"
}
}
}
}
}
- master-k8s/k8s.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vhrservice
labels:
k8s-app: vhrservice
spec:
replicas: 1
revisionHistoryLimit: 3
#滚动升级时70s后认为该pod就绪
minReadySeconds: 70
strategy:
rollingUpdate:
#滚动升级时会先启动1个pod
maxSurge: 1
#滚动升级时允许的最大Unavailable的pod个数
maxUnavailable: 1
selector:
matchLabels:
k8s-app: vhrservice
template:
metadata:
labels:
k8s-app: vhrservice
spec:
containers:
- name: vhrservice
image: 192.168.1.23:80/test/vhrservice:build-<BUILD_TAG>
#resources:
# need more cpu upon initialization, therefore burstable class
#limits:
# memory: 4096Mi
# cpu: 2000m
#requests:
# cpu: 1000m
# memory: 2048Mi
ports:
#容器的端口
- containerPort: 8081
name: vhrservice
protocol: TCP
readinessProbe:
tcpSocket:
port: 8081
initialDelaySeconds: 120
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8081
initialDelaySeconds: 360
periodSeconds: 20
imagePullSecrets:
- name: myregistrykey
---
apiVersion: v1
kind: Service
metadata:
name: vhrservice
labels:
k8s-app: vhrservice
spec:
ports:
#集群IP的端口
- port: 8081
name: vhrservice
protocol: TCP
#容器的端口
targetPort: 8081
selector:
k8s-app: vhrservice
jenkins流水线–后端
效果展示
代码库改造–前端
将源代码库中的 vuehr 目录分离出来,新代码库命名:vhr-ui
新库目录结构如下
├── babel.config.js
├── build.sh
├── default.conf
├── dev-k8s
│ ├── Jenkinsfile
│ └── k8s.yaml
├── Dockerfile
├── package.json
├── package-lock.json
├── public
│ ├── ...
├── README.md
├── ...
└── vue.config.js
新增文件
- default.conf
gzip on; #开启gzip
gzip_min_length 1k; #低于1kb的资源不压缩
gzip_comp_level 5; #压缩级别【1-9】,越大压缩率越高,同时消耗cpu资源也越多,建议设置在4左右。
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css; #需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片,下面会讲为什么。
gzip_disable "MSIE [1-6]\."; #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_vary on; #是否添加“Vary: Accept-Encoding”响应头
upstream javaboy.org {
server vhrservice:8081;
}
server {
listen 80;
server_name 127.0.0.1;
location / {
proxy_pass http://javaboy.org;
proxy_redirect default;
}
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff|html) {
# 所有静态文件直接读取硬盘
root /usr/share/nginx/html/;
expires 30d; #缓存30天
}
ssl_protocols TLSv1.2;
error_page 405 =200 http://$host$request_uri;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- Dockerfile
#设置基础镜像
FROM nginx
#WORKDIR /home/apps/
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
#将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
COPY dist/ /usr/share/nginx/html/
#ADD ca/ /etc/nginx/ca/
#删除nginx 默认配置
RUN rm /etc/nginx/conf.d/default.conf
#添加自己的配置 default.conf 在下面
ADD default.conf /etc/nginx/conf.d/
#使用自定义nginx.conf配置端口和监听
#COPY nginx.conf /etc/nginx/nginx.conf
RUN ln -sf /dev/stdout /var/log/nginx/broker.access.log \
&& ln -sf /dev/stderr /var/log/nginx/broker.error.log
#EXPOSE 8088
CMD ["nginx","-g","daemon off;"]
- dev-k8s/Jenkinsfile
pipeline {
agent any
parameters {
string(name: "branch", defaultValue: "master", description: "code branch")
choice(name: 'module',choices: ['vhrui'], description: 'module_name')
}
stages{
stage('setting env') {
agent any
options {
skipDefaultCheckout(true)
}
steps {
script {
env.NAMESPACE = "test"
env.PROJECT = "test"
env.IMAGE_NAME = "192.168.1.23:80/$PROJECT/$module:build-$BUILD_NUMBER"
}
}
}
stage('get code'){
steps{
git branch: '${branch}', credentialsId: '209653a1-f5b9-4214-bac8-a927c8b36060', url: 'https://gitee.com/duolili/vhr-ui.git'
}
}
stage('vhrui npm build'){
when {
environment name: 'module', value: 'vhrui'
}
steps {
sh "/usr/local/node14/bin/npm install"
sh "/usr/local/node14/bin/npm run build"
}
}
stage('vhrui image build'){
when {
environment name: 'module', value: 'vhrui'
}
steps{
script {
def imageName = docker.build("$IMAGE_NAME")
docker.withRegistry('http://192.168.1.23:80/','5ed303ec-6229-488d-aa73-847e1bb8ee6c'){
imageName.push()
}
sh "/bin/docker rmi ${IMAGE_NAME}"
}
}
}
stage('adminui deploy k8s'){
when {
environment name: 'module', value: 'vhrui'
}
steps{
script {
sh "sed -i 's/<BUILD_TAG>/${BUILD_NUMBER}/g' dev-k8s/k8s.yaml"
sh "/home/jenkins/bin/kubectl apply -f dev-k8s/k8s.yaml -n ${NAMESPACE} --kubeconfig /home/jenkins/.kube/config --record"
}
}
}
}
}
- dev-k8s/k8s.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vhrui
labels:
k8s-app: vhrui
spec:
replicas: 1
revisionHistoryLimit: 3
#滚动升级时70s后认为该pod就绪
minReadySeconds: 70
strategy:
rollingUpdate:
#滚动升级时会先启动1个pod
maxSurge: 1
#滚动升级时允许的最大Unavailable的pod个数
maxUnavailable: 1
selector:
matchLabels:
k8s-app: vhrui
template:
metadata:
labels:
k8s-app: vhrui
spec:
containers:
- name: vhrui
image: 192.168.1.23:80/test/vhrui:build-<BUILD_TAG>
#resources:
# need more cpu upon initialization, therefore burstable class
#limits:
# memory: 4096Mi
# cpu: 2000m
#requests:
# cpu: 1000m
# memory: 2048Mi
ports:
#容器的端口
- containerPort: 80
name: vhrui
protocol: TCP
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 120
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 360
periodSeconds: 20
imagePullSecrets:
- name: myregistrykey
---
apiVersion: v1
kind: Service
metadata:
name: vhrui
labels:
k8s-app: vhrui
spec:
ports:
#集群IP的端口
- port: 80
name: vhrui
protocol: TCP
#容器的端口
targetPort: 80
selector:
k8s-app: vhrui
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: vhrui-http
spec:
entryPoints:
- web
routes:
- match: Host(`vhrui.test.com`) && PathPrefix(`/`)
kind: Rule
services:
- name: vhrui
port: 80
jenkins流水线–前端
效果展示
web访问
部署方式2:一个代码库
使用同一个代码库,分别部署前后端项目
代码库
https://gitee.com/duolili/vhr.git – dev分支
流水线–后端
流水线–前端