kubernetes部署python项目
# 部署前准备
部署的项目地址:https://github.com/opsre/version_manager
# 1. 修改密码(02-secret.yaml)
生产环境务必替换默认密码,或使用 Sealed Secrets / External Secrets 等方案管理。
# 2. 初始化 SQL(如需要)
如果项目需要初始化数据库表结构,将 version_test.sql 导入
# 3. TLS 证书
创建名为 version-manager-tls 的 Secret,包含 TLS 证书和私钥:
使用 cert-manager(推荐):
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: version-manager-tls
namespace: version-manager
spec:
secretName: version-manager-tls
issuerRef:
name: letsencrypt-prod # 替换为你的 Issuer
kind: ClusterIssuer
dnsNames:
- version-manager.example.com
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
手动创建自签证书:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=version-manager.example.com"
kubectl create secret tls version-manager-tls \
--cert=tls.crt --key=tls.key \
-n version-manager
1
2
3
4
5
6
7
2
3
4
5
6
7
# 4. 修改 Gateway 配置(07-gateway.yaml)
gatewayClassName:填写集群实际的 GatewayClass(如istio、eg)hostnames:改为实际域名
# 5. CORS 配置(01-configmap.yaml)
将 CORS_ORIGINS 更新为前端实际访问地址,例如:
CORS_ORIGINS: "https://version-manager.example.com"
1
# 部署
# 1.文件结构介绍
00-namespace.yaml # Namespace
01-configmap.yaml # 应用配置
02-secret.yaml # 敏感信息(密码)
04-vsftpd.yaml # vsftpd PVC + Deployment + Service(LoadBalancer)
05-backend.yaml # 后端 Deployment + Service
06-frontend.yaml # 前端 Deployment + Service
07-gateway.yaml # Gateway + HTTPRoute(Kubernetes Gateway API)
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2. 文件内容
[root@k8s-master01 version_manager]# cat 00-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: version-manager
[root@k8s-master01 version_manager]# cat 01-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: version-manager-config
namespace: version-manager
data:
DB_HOST: "192.168.51.51"
DB_PORT: "13306"
DB_NAME: "version_test"
DB_USERNAME: "devops"
FTP_HOST: "vsftpd"
FTP_PORT: "21"
FTP_USERNAME: "team01"
FTP_DIRECTORY: "file"
# 根据实际域名修改,逗号分隔多个来源
CORS_ORIGINS: "http://localhost:5173,http://127.0.0.1:5173,https://version-manager.zzppjj.top,https://192.168.51.110:443"
[root@k8s-master01 version_manager]# cat 02-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: version-manager-secret
namespace: version-manager
type: Opaque
stringData:
DB_PASSWORD: "Admin123456" # 生产环境请修改
MYSQL_ROOT_PASSWORD: "2023W#@qGhsd" # 生产环境请修改
FTP_PASSWORD: "ftp_password" # 生产环境请修改
[root@k8s-master01 version_manager]# cat 04-vsftpd.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ftp-data-pvc
namespace: version-manager
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: "nfs-version" # 按需指定 StorageClass
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vsftpd
namespace: version-manager
labels:
app: vsftpd
spec:
replicas: 1
selector:
matchLabels:
app: vsftpd
strategy:
type: Recreate
template:
metadata:
labels:
app: vsftpd
spec:
containers:
- name: vsftpd
image: docker.cnb.cool/zzppjj/docker-images/vsftpd:latest
ports:
- containerPort: 20
name: ftp-data
- containerPort: 21
name: ftp-ctrl
- containerPort: 21100
name: pasv-0
- containerPort: 21101
name: pasv-1
- containerPort: 21102
name: pasv-2
- containerPort: 21103
name: pasv-3
- containerPort: 21104
name: pasv-4
- containerPort: 21105
name: pasv-5
- containerPort: 21106
name: pasv-6
- containerPort: 21107
name: pasv-7
- containerPort: 21108
name: pasv-8
- containerPort: 21109
name: pasv-9
- containerPort: 21110
name: pasv-10
env:
- name: FTP_USER
valueFrom:
configMapKeyRef:
name: version-manager-config
key: FTP_USERNAME
- name: FTP_PASS
valueFrom:
secretKeyRef:
name: version-manager-secret
key: FTP_PASSWORD
volumeMounts:
- name: ftp-data
mountPath: /home/vsftpd
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
volumes:
- name: ftp-data
persistentVolumeClaim:
claimName: ftp-data-pvc
---
# vsftpd 需要 LoadBalancer 暴露端口(FTP 协议不适合经过 HTTP Gateway 路由)
# 如果集群没有 LoadBalancer,可改为 NodePort
apiVersion: v1
kind: Service
metadata:
name: vsftpd
namespace: version-manager
labels:
app: vsftpd
spec:
selector:
app: vsftpd
type: LoadBalancer # FTP 控制+数据端口需要 L4 直通,不走 HTTPRoute
ports:
- name: ftp-ctrl
port: 21
targetPort: 21
- name: ftp-data
port: 20
targetPort: 20
- name: pasv-21100
port: 21100
targetPort: 21100
- name: pasv-21101
port: 21101
targetPort: 21101
- name: pasv-21102
port: 21102
targetPort: 21102
- name: pasv-21103
port: 21103
targetPort: 21103
- name: pasv-21104
port: 21104
targetPort: 21104
- name: pasv-21105
port: 21105
targetPort: 21105
- name: pasv-21106
port: 21106
targetPort: 21106
- name: pasv-21107
port: 21107
targetPort: 21107
- name: pasv-21108
port: 21108
targetPort: 21108
- name: pasv-21109
port: 21109
targetPort: 21109
- name: pasv-21110
port: 21110
targetPort: 21110
[root@k8s-master01 version_manager]# cat 05-backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: version-manager
labels:
app: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: docker.cnb.cool/zzppjj/docker-images/version_manager:v1
ports:
- containerPort: 5000
envFrom:
- configMapRef:
name: version-manager-config
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: version-manager-secret
key: DB_PASSWORD
- name: FTP_PASSWORD
valueFrom:
secretKeyRef:
name: version-manager-secret
key: FTP_PASSWORD
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
readinessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 15
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 30
periodSeconds: 15
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: version-manager
labels:
app: backend
spec:
selector:
app: backend
ports:
- port: 5000
targetPort: 5000
type: ClusterIP
[root@k8s-master01 version_manager]# cat 06-frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: version-manager
labels:
app: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: docker.cnb.cool/zzppjj/docker-images/version_manager_ui:v1
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 15
---
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: version-manager
labels:
app: frontend
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
type: ClusterIP
[root@k8s-master01 version_manager]# cat 07-gateway.yaml
# -------------------------------------------------------
# Gateway (Kubernetes Gateway API)
# 前提:集群已安装 GatewayClass,如 Istio / Envoy Gateway
# 若使用 Istio,gatewayClassName 填 "istio"
# 若使用 Envoy Gateway,填 "eg" 或按实际情况填写
# -------------------------------------------------------
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: version-manager-gateway
namespace: version-manager
spec:
gatewayClassName: istio # ← 按实际 GatewayClass 修改
listeners:
- name: http
protocol: HTTP
port: 80
# 自动重定向到 HTTPS,由下方 HTTPRoute 处理
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: version-manager-tls # ← Secret 名称,见下方说明
kind: Secret
allowedRoutes:
namespaces:
from: Same
---
# -------------------------------------------------------
# HTTP → HTTPS 重定向
# -------------------------------------------------------
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-to-https-redirect
namespace: version-manager
spec:
parentRefs:
- name: version-manager-gateway
sectionName: http
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
# -------------------------------------------------------
# HTTPS 路由:前端(/) + 后端 API(/api/)
# 修改 hostnames 为实际域名
# -------------------------------------------------------
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: version-manager-route
namespace: version-manager
spec:
parentRefs:
- name: version-manager-gateway
sectionName: https
hostnames:
- "version-manager.zzppjj.top" # ← 修改为实际域名
rules:
# 后端 API 路由(优先匹配,放前面)
- matches:
- path:
type: PathPrefix
value: /api/
backendRefs:
- name: backend
port: 5000
# 前端路由(兜底)
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend
port: 80
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# FTP 说明
vsftpd 使用 LoadBalancer 类型的 Service(FTP 协议为 TCP,无法通过 HTTP Gateway 路由)。
若集群无 LoadBalancer(如裸金属),可改为 NodePort,或使用 MetalLB。
vsftpd 被动模式端口范围为 21100–21110,需要确保防火墙/安全组放行这些端口。
# 后端健康检查
05-backend.yaml 中配置了 /health 健康检查端点。如果该项目没有此端点,请将 readinessProbe / livenessProbe 改为 TCP 检查:
readinessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 15
periodSeconds: 10
1
2
3
4
5
2
3
4
5
上次更新: 2026/06/06, 13:06:51
|