Ruoyi DevOps 流水线方式搭建(KubeSphere)

3.1 创建 DevOps 工程

  1. 创建 DevOps 项目
image-20220502182538146.png
  1. 创建流水线
image-20220502183924129.png

3.2 构建后端项目-step1 拉取代码

  1. 添加凭证,并指定 GitHub 的项目 url 和分支
image-20220502184059726.png
  1. 完成 step1 的流水线节点
image-20220502184134163.png

3.2 构建后端项目-step2 项目构建

  1. 修改maven的镜像仓库,改为从阿里云镜像仓库拉取依赖
  • 登陆 admin 账号,找到 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
  1. 使用 maven 命令编译项目代码
image-20220502184959327.png

3.3 构建后端项目-step3 构建镜像

  1. 执行 docker 的镜像构建命令,为每个微服务进行镜像打包
image-20220502191423187.png
  1. 并行开展镜像构建
image-20220502192834677.png

3.4 构建后端项目-step4 推送镜像

  1. 创建阿里云镜像仓库的访问凭证
image-20220502193622860.png
  1. 修改 Jenkinsfile 的环境变量
image-20220502194409945.png
  1. 推送镜像,需要指定阿里云凭证,登陆阿里云,执行打标签脚本以及执行推送脚本
image-20220502195526695.png
  1. 其他微服务同样的方式,并行执行
image-20220502195938068.png

3.5 构建后端项目-step5 部署镜像

  1. 创建 kubeconfig 的访问凭证,用于在 work 节点可以执行 kubectl 命令执行配置文件
image-20220502201208125.png
  1. 在项目管理中配置阿里云镜像地址的访问凭证,用于向私有仓库拉取镜像使用
image-20220502201635680.png
  1. 执行部署,通过命令指定运行部署的 deploy.yaml 文件
image-20220503150527003.png
  1. 其他微服务同样的方式,并行执行
image-20220503150539074.png

3.6 构建后端项目-step6 邮件通知

  1. 登陆 admin 账号,添加邮件配置
image-20220502211154428.png
image-20220502211206801.png
  1. 修改 DevOps,集成邮件功能。使用 admin 账号登陆,修改 devops-jenkins yaml文件
image-20220503095626321.png
image-20220503100827627.png
  1. 添加发送邮件的节点
image-20220503101252417.png

3.7 构建前端项目

与后端类似

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('项目编译') {
      agent none
      steps {
        container('maven') {
          sh 'mvn clean package -Dmaven.test.skip=true'
        }

      }
    }

    stage('default-2') {
      parallel {
        stage('构建镜像') {
          agent none
          steps {
            container('maven') {
              sh 'docker build -t ruoyi-auth:latest -f ruoyi-auth/Dockerfile ./ruoyi-auth/'
            }

          }
        }

        stage('构建镜像2') {
          agent none
          steps {
            container('maven') {
              sh 'docker build -t ruoyi-gateway:latest -f ruoyi-gateway/Dockerfile ./ruoyi-gateway/'
            }

          }
        }

        stage('构建镜像3') {
          agent none
          steps {
            container('maven') {
              sh 'docker build -t ruoyi-file:latest -f ruoyi-modules/ruoyi-file/Dockerfile ./ruoyi-modules/ruoyi-file/'
            }

          }
        }

        stage('构建镜像4') {
          agent none
          steps {
            container('maven') {
              sh 'docker build -t ruoyi-job:latest -f ruoyi-modules/ruoyi-job/Dockerfile ./ruoyi-modules/ruoyi-job/'
            }

          }
        }

        stage('构建镜像5') {
          agent none
          steps {
            container('maven') {
              sh 'docker build -t ruoyi-system:latest -f ruoyi-modules/ruoyi-system/Dockerfile ./ruoyi-modules/ruoyi-system/'
            }

          }
        }

        stage('构建镜像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  #提前在项目下配置访问阿里云的账号密码
      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('项目编译') {
      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('构建镜像') {
      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  #提前在项目下配置访问阿里云的账号密码
      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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容