一、DevOps 简介

​ DevOps 是一系列做法和工具,可以使 IT 和软件开发团队之间的流程实现自动化。其中,随着敏捷软件开发日趋流行,持续集成 (CI)持续交付 (CD) 已经成为该领域一个理想的解决方案。在 CI/CD 工作流中,每次集成都通过自动化构建来验证,包括编码、发布和测试,从而帮助开发者提前发现集成错误,团队也可以快速、安全、可靠地将内部软件交付到生产环境。

image-20230202174809339image-20230202174846573

二、尚医通项目上云

1、项目架构

image-20230202175005056

Text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
yygh-parent
|---common //通用模块
|---hospital-manage //医院后台 [9999]
|---model //数据模型
|---server-gateway //网关 [80]
|---service //微服务层
|-------service-cmn //公共服务 [8202]
|-------service-hosp //医院数据服务 [8201]
|-------service-order //预约下单服务 [8206]
|-------service-oss //对象存储服务 [8205]
|-------service-sms //短信服务 [8204]
|-------service-statistics //统计服务 [8208]
|-------service-task //定时服务 [8207]
|-------service-user //会员服务 [8203]


====================================================================

yygh-admin //医院管理后台 [9528]
yygh-site //挂号平台 [3000]

2、中间件

中间件
Nacos
MySQL
Redis
Sentinel
MongoDB
RabbitMQ
ElasticSearch

3、流水线

3.1 项目地址

3.2 创建 devops 工程

image-20230202175605675

注意:如果创建项目后健康状态为异常,异常错误也跟如下一样

image-20230202175852347

image-20230202175841326

解决方式:重新创建一个用户,分配到该项目就能正常显示状态为正常了。

3.3 创建流水线模板

image-20230202180417764

image-20230202180438751

3.4 流水线编辑步骤

第一步:拉取代码

image-20230202182225818

添加步骤

image-20230202182312749

image-20230202182343078

image-20230202182419565

点击嵌套步骤:

image-20230202182510470

image-20230202182602389

image-20230202182821439

  • 创建凭证

image-20230202182723127

点击嵌套步骤:

image-20230202182947638

image-20230202183005317

效果:

image-20230202183700127

第二步:项目编译

image-20230202200125604

1
mvn clean package -Dmaven.test.skip=true

注意:这个地方需要去配置 maven 镜像,不然在编译的时候会特别慢,把镜像改为阿里云镜像

  • 使用 admin 登陆 ks

  • 进入集群管理

  • 进入配置中心

  • 找到配置

    • ks-devops-agen

      image-20230202200510816

    • 修改这个配置。加入 maven 阿里云镜像加速地址

    •   <mirrors>
            <id>alimaven</id>
            <mirrorOf>central</mirrorOf>
            <name>aliyun maven</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </mirrors>
      
      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

      - ![image-20230202200723110](https://oss.imoyt.top/img/image-20230202200723110.png)

      > **第三步**: 构建镜像

      ​ 这里需要并发构建,所以直接在文件里面修改

      ![image-20230202204903818](https://oss.imoyt.top/img/image-20230202204903818.png)

      ```dockerfile
      stage('default-2') {
      parallel {
      stage('构建hospital-manage镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls hospital-manage/target'
      sh 'docker build -t hospital-manage:latest -f hospital-manage/Dockerfile ./hospital-manage/'
      }

      }
      }

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

      }
      }

      stage('构建service-cmn镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-cmn/target'
      sh 'docker build -t service-cmn:latest -f service/service-cmn/Dockerfile ./service/service-cmn/'
      }

      }
      }

      stage('构建service-hosp镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-hosp/target'
      sh 'docker build -t service-hosp:latest -f service/service-hosp/Dockerfile ./service/service-hosp/'
      }

      }
      }

      stage('构建service-order镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-order/target'
      sh 'docker build -t service-order:latest -f service/service-order/Dockerfile ./service/service-order/'
      }

      }
      }

      stage('构建service-oss镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-oss/target'
      sh 'docker build -t service-oss:latest -f service/service-oss/Dockerfile ./service/service-oss/'
      }

      }
      }

      stage('构建service-sms镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-sms/target'
      sh 'docker build -t service-sms:latest -f service/service-sms/Dockerfile ./service/service-sms/'
      }

      }
      }

      stage('构建service-statistics镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-statistics/target'
      sh 'docker build -t service-statistics:latest -f service/service-statistics/Dockerfile ./service/service-statistics/'
      }

      }
      }

      stage('构建service-task镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-task/target'
      sh 'docker build -t service-task:latest -f service/service-task/Dockerfile ./service/service-task/'
      }

      }
      }

      stage('构建service-user镜像') {
      agent none
      steps {
      container('maven') {
      sh 'ls service/service-user/target'
      sh 'docker build -t service-user:latest -f service/service-user/Dockerfile ./service/service-user/'
      }

      }
      }

      }
      }

image-20230202205030283

第四步: 推送镜像

image-20230202204903818

这里需要新建一个凭证:

image-20230202213614037

image-20230202213442194

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
  stage('default-3') {
parallel {
stage('推送hospital-manage镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送server-gateway镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag server-gateway:latest $REGISTRY/$DOCKERHUB_NAMESPACE/server-gateway:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/server-gateway:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-cmn镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-cmn:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-cmn:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-cmn:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-hosp镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-hosp:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-hosp:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-hosp:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-order镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-order:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-order:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-order:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-oss镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-oss:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-oss:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-oss:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-sms镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-sms:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-sms:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-sms:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-statistics镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-statistics:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-statistics:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-statistics:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-task镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-task:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-task:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-task:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

stage('推送service-user镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-user:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-user:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-user:SNAPSHOT-$BUILD_NUMBER'
}

}

}
}

}
}

environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITHUB_CREDENTIAL_ID = 'github-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'
DOCKERHUB_NAMESPACE = 'oyt_his'
GITHUB_ACCOUNT = 'kubesphere'
APP_NAME = 'devops-java-sample'
ALIYUNHUB_NAMESPACE = 'oyt_his'
}

image-20230202213808350

第五步:部署到 dev 环境

这里需要准备两个凭证:

  • 流水线凭证

image-20230202223645319

image-20230202223701167

image-20230202223752376

  • 流水线凭证(阿里云容器账号)

    image-20230202224155306

    image-20230202224250503

  • 在项目里面(ruoyi,不是流水线项目),找到配置–密钥,配置一个阿里云的访问账号密码

image-20230202224404116

image-20230202224452932

image-20230202224548634

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
stage('default-4') {
parallel {
stage('hospital-manage - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'hospital-manage/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('server-gateway - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'server-gateway/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-cmn - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-cmn/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-hosp - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-hosp/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-order - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-order/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-oss - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-oss/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-sms - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-sms/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-statistics - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-statistics/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-task - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-task/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

stage('service-user - 部署到dev环境') {
agent none
steps {
kubernetesDeploy(configs: 'service/service-user/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}

}
}

image-20230203000337190

第六步:发送确认邮件

image-20230203000137741

image-20230203000150944

1
2
3
$BUILD_NUMBER-构建结果

构建成功了 $BUILD_NUMBER
  • 邮件发送需要用 admin 账户登录,去平台管理里面配置 应用负载 ==》 工作负载

image-20230203001619538

image-20230203001950620