3.1 創(chuàng)建 DevOps 工程
- 創(chuàng)建 DevOps 項(xiàng)目

image-20220502182538146.png
- 創(chuàng)建流水線

image-20220502183924129.png
3.2 構(gòu)建后端項(xiàng)目-step1 拉取代碼
- 添加憑證,并指定 GitHub 的項(xiàng)目 url 和分支

image-20220502184059726.png
- 完成 step1 的流水線節(jié)點(diǎn)

image-20220502184134163.png
3.2 構(gòu)建后端項(xiàng)目-step2 項(xiàng)目構(gòu)建
- 修改maven的鏡像倉(cāng)庫(kù),改為從阿里云鏡像倉(cāng)庫(kù)拉取依賴
- 登陸 admin 賬號(hào),找到 maven 的配置文件

image-20220502184359901.png
- 加入阿里云的鏡像配置
<mirror>
<id>nexus-aliyun</id>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

image-20220502184608668.png
- 使用 maven 命令編譯項(xiàng)目代碼

image-20220502184959327.png
3.3 構(gòu)建后端項(xiàng)目-step3 構(gòu)建鏡像
- 執(zhí)行 docker 的鏡像構(gòu)建命令,為每個(gè)微服務(wù)進(jìn)行鏡像打包

image-20220502191423187.png
- 并行開展鏡像構(gòu)建

image-20220502192834677.png
3.4 構(gòu)建后端項(xiàng)目-step4 推送鏡像
- 創(chuàng)建阿里云鏡像倉(cāng)庫(kù)的訪問憑證

image-20220502193622860.png
- 修改 Jenkinsfile 的環(huán)境變量

image-20220502194409945.png
- 推送鏡像,需要指定阿里云憑證,登陸阿里云,執(zhí)行打標(biāo)簽?zāi)_本以及執(zhí)行推送腳本

image-20220502195526695.png
- 其他微服務(wù)同樣的方式,并行執(zhí)行

image-20220502195938068.png
3.5 構(gòu)建后端項(xiàng)目-step5 部署鏡像
- 創(chuàng)建 kubeconfig 的訪問憑證,用于在 work 節(jié)點(diǎn)可以執(zhí)行 kubectl 命令執(zhí)行配置文件

image-20220502201208125.png
- 在項(xiàng)目管理中配置阿里云鏡像地址的訪問憑證,用于向私有倉(cāng)庫(kù)拉取鏡像使用

image-20220502201635680.png
- 執(zhí)行部署,通過命令指定運(yùn)行部署的 deploy.yaml 文件

image-20220503150527003.png
- 其他微服務(wù)同樣的方式,并行執(zhí)行

image-20220503150539074.png
3.6 構(gòu)建后端項(xiàng)目-step6 郵件通知
- 登陸 admin 賬號(hào),添加郵件配置

image-20220502211154428.png

image-20220502211206801.png
- 修改 DevOps,集成郵件功能。使用 admin 賬號(hào)登陸,修改 devops-jenkins yaml文件

image-20220503095626321.png

image-20220503100827627.png
- 添加發(fā)送郵件的節(jié)點(diǎn)

image-20220503101252417.png
3.7 構(gòu)建前端項(xiàng)目
與后端類似
3.8 附錄
- 后端 Jenkinsfile.yaml 文件
pipeline {
agent {
node {
label 'maven'
}
}
stages {
stage('代碼克隆') {
agent none
steps {
container('maven') {
git(url: 'https://gitee.com/yaokuku123/RuoYi-Cloud.git', credentialsId: 'github-auth', branch: 'master', changelog: true, poll: false)
sh 'ls -l'
}
}
}
stage('項(xiàng)目編譯') {
agent none
steps {
container('maven') {
sh 'mvn clean package -Dmaven.test.skip=true'
}
}
}
stage('default-2') {
parallel {
stage('構(gòu)建鏡像') {
agent none
steps {
container('maven') {
sh 'docker build -t ruoyi-auth:latest -f ruoyi-auth/Dockerfile ./ruoyi-auth/'
}
}
}
stage('構(gòu)建鏡像2') {
agent none
steps {
container('maven') {
sh 'docker build -t ruoyi-gateway:latest -f ruoyi-gateway/Dockerfile ./ruoyi-gateway/'
}
}
}
stage('構(gòu)建鏡像3') {
agent none
steps {
container('maven') {
sh 'docker build -t ruoyi-file:latest -f ruoyi-modules/ruoyi-file/Dockerfile ./ruoyi-modules/ruoyi-file/'
}
}
}
stage('構(gòu)建鏡像4') {
agent none
steps {
container('maven') {
sh 'docker build -t ruoyi-job:latest -f ruoyi-modules/ruoyi-job/Dockerfile ./ruoyi-modules/ruoyi-job/'
}
}
}
stage('構(gòu)建鏡像5') {
agent none
steps {
container('maven') {
sh 'docker build -t ruoyi-system:latest -f ruoyi-modules/ruoyi-system/Dockerfile ./ruoyi-modules/ruoyi-system/'
}
}
}
stage('構(gòu)建鏡像6') {
agent none
steps {
container('maven') {
sh 'docker build -t ruoyi-monitor:latest -f ruoyi-visual/ruoyi-monitor/Dockerfile ./ruoyi-visual/ruoyi-monitor/'
}
}
}
}
}
stage('default-3') {
parallel {
stage('鏡像推送') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-auth:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-auth:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-auth:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('鏡像推送2') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-gateway:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-gateway:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-gateway:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('鏡像推送3') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-file:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-file:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-file:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('鏡像推送4') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-job:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-job:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-job:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('鏡像推送5') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-system:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-system:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-system:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('鏡像推送6') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-monitor:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-monitor:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-monitor:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
}
}
stage('default-4') {
parallel {
stage('鏡像部署') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-auth/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
stage('鏡像部署2') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-gateway/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
stage('鏡像部署3') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-modules/ruoyi-file/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
stage('鏡像部署4') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-modules/ruoyi-job/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
stage('鏡像部署5') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-modules/ruoyi-system/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
stage('鏡像部署6') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-visual/ruoyi-monitor/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
}
}
stage('部署完成') {
agent none
steps {
mail(to: 'yorick_jun@163.com', subject: 'Deploy Success', body: 'KubeSphere Deploy Ruoyi $BUILD_NUMBER Success!!')
}
}
}
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITHUB_CREDENTIAL_ID = 'github-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'registry.cn-beijing.aliyuncs.com'
DOCKERHUB_NAMESPACE = 'yqj_ruoyi'
GITHUB_ACCOUNT = 'kubesphere'
APP_NAME = 'devops-java-sample'
}
parameters {
string(name: 'TAG_NAME', defaultValue: '', description: '')
}
}
- 后端 deploy.yaml 文件
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ruoyi-auth
name: ruoyi-auth
namespace: ruoyi #一定要寫名稱空間
spec:
progressDeadlineSeconds: 600
replicas: 1
selector:
matchLabels:
app: ruoyi-auth
strategy:
rollingUpdate:
maxSurge: 50%
maxUnavailable: 50%
type: RollingUpdate
template:
metadata:
labels:
app: ruoyi-auth
spec:
imagePullSecrets:
- name: aliyun-docker-hub #提前在項(xiàng)目下配置訪問阿里云的賬號(hào)密碼
containers:
- image: $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-auth:SNAPSHOT-$BUILD_NUMBER
imagePullPolicy: Always
name: app
ports:
- containerPort: 8080
protocol: TCP
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
labels:
app: ruoyi-auth
name: ruoyi-auth
namespace: ruoyi
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: ruoyi-auth
sessionAffinity: None
type: ClusterIP
- 前端 Jenkinsfile.yaml 文件
pipeline {
agent {
node {
label 'nodejs'
}
}
stages {
stage('拉取代碼') {
steps {
container('nodejs') {
git(url: ' https://gitee.com/yaokuku123/RuoYi-Cloud.git', credentialsId: 'github-auth', branch: 'master', changelog: true, poll: false)
sh 'ls -l'
}
}
}
stage('項(xiàng)目編譯') {
agent none
steps {
container('nodejs') {
sh 'cd ruoyi-ui && npm install --registry=https://registry.npm.taobao.org && npm run build:prod && ls -l && mkdir -p docker/html/dist && cp -r dist docker/html && ls -l docker/html/dist'
}
}
}
stage('構(gòu)建鏡像') {
agent none
steps {
container('nodejs') {
sh 'cd ruoyi-ui/docker && docker build -t ruoyi-ui:latest -f dockerfile .'
}
}
}
stage('推送鏡像') {
agent none
steps {
container('nodejs') {
withCredentials([usernamePassword(credentialsId : 'aliyun-auth' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) {
sh 'echo $DOCKER_PWD_VAR | docker login $REGISTRY --username=$DOCKER_USER_VAR --password-stdin'
sh 'docker tag ruoyi-ui:latest $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-ui:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-ui:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('部署鏡像') {
agent none
steps {
container('nodejs') {
withCredentials([kubeconfigFile(credentialsId : 'demo-kubeconfig' ,variable : 'KUBECONFIG' ,)]) {
sh 'envsubst < ruoyi-ui/deploy/deploy.yaml | kubectl apply -f -'
}
}
}
}
stage('部署完成') {
agent none
steps {
mail(to: 'yorick_jun@163.com', subject: 'Ruoyi Ui Success', body: "Ruoyi UI Success $BUILD_NUMBER")
}
}
}
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITHUB_CREDENTIAL_ID = 'github-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'registry.cn-beijing.aliyuncs.com'
DOCKERHUB_NAMESPACE = 'yqj_ruoyi'
GITHUB_ACCOUNT = 'kubesphere'
APP_NAME = 'devops-java-sample'
}
parameters {
string(name: 'TAG_NAME', defaultValue: '', description: '')
}
}
- 前端 deploy.yaml 文件
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ruoyi-ui
name: ruoyi-ui
namespace: ruoyi #一定要寫名稱空間
spec:
progressDeadlineSeconds: 600
replicas: 1
selector:
matchLabels:
app: ruoyi-ui
strategy:
rollingUpdate:
maxSurge: 50%
maxUnavailable: 50%
type: RollingUpdate
template:
metadata:
labels:
app: ruoyi-ui
spec:
imagePullSecrets:
- name: aliyun-docker-hub #提前在項(xiàng)目下配置訪問阿里云的賬號(hào)密碼
containers:
- image: $REGISTRY/$DOCKERHUB_NAMESPACE/ruoyi-ui:SNAPSHOT-$BUILD_NUMBER
imagePullPolicy: Always
name: app
ports:
- containerPort: 80
protocol: TCP
resources:
limits:
cpu: 300m
memory: 600Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
labels:
app: ruoyi-ui
name: ruoyi-ui
namespace: ruoyi
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 32248
selector:
app: ruoyi-ui
sessionAffinity: None
type: NodePort
- 前端 nginx 配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name _;
location / {
root /home/ruoyi/projects/ruoyi-ui;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ruoyi-gateway.ruoyi:8080/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}# requirepass 123456