feat: 三种部署方式全部验证通过

方案1: docker-compose 双容器(原有,不变)
方案2: 二进制部署(go:embed 前端嵌入)
  - 修复 SPA fallback(c.FileFromFS 301 → c.Data 直接返回)
  - 二进制 22MB,内存 21.5MB
  - 支持全部 CLI 参数(--db-host --redis-host --port 等)
方案3: K8s 部署(hostNetwork + 外部 MySQL/Redis)
  - devops 声明空间
  - embed 单容器 Deployment + NodePort Service
  - 健康检查改为 /version(/health 尚未实现)
  - hostNetwork 解决 K8s pod 网络到外部 MySQL 的连通性

新增: Dockerfile.embed, docker-compose.embed.yml, deploy/binary/
This commit is contained in:
attacker committed 2026-06-21 15:03:17 +08:00
1 parent 4631b02f13
commit 2a0521340f
15 files changed
+734 -488

No files matched your search

+79 -86
View File
@@ -2,6 +2,8 @@
AIOps 平台在 Kubernetes 上的部署清单(Go/Gin 后端 + go:embed 前端 + MySQL 8.0 + Redis 7)。
**单容器架构**:前端通过 `go:embed` 嵌入后端二进制,一个容器同时服务 API + WebSocket + SPA 静态资源,端口统一 8080。
所有资源部署在 **`devops`** 命名空间。
## 目录结构
@@ -9,150 +11,141 @@ AIOps 平台在 Kubernetes 上的部署清单(Go/Gin 后端 + go:embed 前端
| 文件 | 说明 |
|------|------|
| `namespace.yaml` | `devops` 命名空间 |
| `configmap.yaml` | 后端 `config.yaml`(ConfigMap)+ MySQL/JWT 密码(Secret) |
| `mysql.yaml` | MySQL 8.0 StatefulSet + Headless/ClusterIP Service + 8Gi 持久卷 |
| `redis.yaml` | Redis 7 StatefulSet + Headless/ClusterIP Service + 2Gi 持久卷 |
| `backend.yaml` | 后端 Deployment(端口 8080=API/WS,80=embed 前端)+ ClusterIP Service |
| `ingress.yaml` | Ingress:`/api`、`/ws` → 8080;`/` → 80 |
| `secret.yaml` | MySQL/JWT 密码(Secret) |
| `configmap.yaml` | 后端 `config.yaml`(ConfigMap) |
| `mysql.yaml` | MySQL 8.0 StatefulSet + Headless Service + 10Gi 持久卷 |
| `redis.yaml` | Redis 7 StatefulSet + Headless Service + 2Gi 持久卷 |
| `deployment.yaml` | AIOps Deployment(embed 单端口 8080)+ NodePort Service (30080) |
| `ingress.yaml` | Ingress:所有流量 → aiops:8080(含 WebSocket 支持) |
## 架构与端口
## 架构
```
┌──────────────── Ingress (nginx) ────────────────┐
/api, /ws ──▶│ │──▶ aiops-backend:8080 (API + WebSocket)
/ ──▶│ │──▶ aiops-backend:80 (go:embed 前端)
└──────────────────────────────────────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
aiops-backend aiops-backend
│ (DB_HOST=mysql) │ (REDIS_HOST=redis)
▼ ▼
MySQL 8.0 (StatefulSet) Redis 7 (StatefulSet)
aiops / aiops_pass_2026 无密码, db 0
数据库 aiops, 8Gi PV 2Gi PV
NodePort:30080 / Ingress
│
▼
┌─── aiops (Deployment) ───┐
│ 单端口 8080: │
│ • API (/api/*) │
│ • WebSocket (/ws/*) │
│ • 前端 SPA (go:embed) │
└───────────┬───────────────┘
│
┌──────────────┼──────────────┐
▼ ▼
MySQL 8.0 Redis 7
(StatefulSet) (StatefulSet)
mysql:3306 redis:6379
10Gi PV 2Gi PV
```
- **8080**:API + WebSocket
- **80**:前端(go:embed 嵌入后端二进制,由后端进程提供静态资源)
- 配置文件 `config.yaml` 中 DB/Redis 连接均以环境变量 `${VAR}` 占位,由 Deployment 的 `env` 注入;密码走 Secret。
## 快速部署
## 前置条件
### 方式一:run.sh 一键部署(推荐)
1. 一个可用的 Kubernetes 集群(≥ 1.22)。
2. 已安装 **nginx Ingress Controller**。
3. 集群具备可用的 **StorageClass**(MySQL/Redis 的 `volumeClaimTemplates` 依赖动态卷供应)。
- minikube / kind 自带默认 StorageClass(如 `standard`)。
- 如需指定,取消各 StatefulSet 中 `storageClassName` 的注释。
4. 后端镜像 `aiops-backend:latest` 已构建并推送到集群可访问的镜像仓库(或本地 `kind load docker-image` / `minikube image load`)。
```bash
# 构建镜像 + 部署全部资源
./run.sh k8s deploy
## 部署步骤
# 查看状态
./run.sh k8s status
按顺序 apply(资源间存在依赖:Secret → 数据库 → 后端 → Ingress):
# 查看日志
./run.sh k8s logs
# 更新(重新构建镜像 + 滚动更新)
./run.sh k8s upgrade
# 清理
./run.sh k8s delete
```
### 方式二:手动 kubectl
```bash
cd deploy/k8s
# 1. 命名空间(必须最先)
# 1. 全量部署(文件按序: namespace → secret → configmap → mysql → redis → deployment)
kubectl apply -f namespace.yaml
# 2. 配置 + 密码(ConfigMap / Secret)
kubectl apply -f secret.yaml
kubectl apply -f configmap.yaml
# 3. MySQL(启动后自动建库 aiops 与用户 aiops)
kubectl apply -f mysql.yaml
# 4. Redis
kubectl apply -f redis.yaml
# 5. 等待数据库就绪
# 2. 等待数据库就绪
kubectl -n devops rollout status statefulset/mysql
kubectl -n devops rollout status statefulset/redis
# 6. 后端
kubectl apply -f backend.yaml
kubectl -n devops rollout status deployment/aiops-backend
# 3. 构建镜像(在本地)
cd ../..
docker build -f Dockerfile.embed -t aiops:embed .
# 7. Ingress(部署前修改 host 与 ingressClassName)
# 4. 部署应用
kubectl apply -f deployment.yaml
kubectl -n devops rollout status deployment/aiops
# 5. Ingress(按需修改 host)
kubectl apply -f ingress.yaml
```
一键全量部署(文件名按字典序,namespace 会最先应用):
```bash
kubectl apply -f deploy/k8s/
```
## 访问
- 将 Ingress 中的 `host`(默认 `aiops.local`)解析到 Ingress Controller 的入口 IP:
```bash
echo "<INGRESS_IP> aiops.local" | sudo tee -a /etc/hosts
```
- 浏览器打开 `http://aiops.local` 即前端;API 在 `http://aiops.local/api`。
```bash
# NodePort 方式
curl http://<NODE_IP>:30080/health
# 或配置 Ingress host
echo "<INGRESS_IP> aiops.local" | sudo tee -a /etc/hosts
# 浏览器: http://aiops.local
```
## 常用运维命令
```bash
# 查看所有资源
kubectl -n devops get all,configmap,secret,ingress,pvc
kubectl -n devops get all,pvc,configmap,secret
# 查看后端日志
kubectl -n devops logs -f deployment/aiops-backend
# 查看应用日志
kubectl -n devops logs -f deployment/aiops
# 进入应用容器
kubectl -n devops exec -it deployment/aiops -- bash
# 进入 MySQL
kubectl -n devops exec -it mysql-0 -- mysql -uaiops -paiops_pass_2026 aiops
# 进入 Redis
kubectl -n devops exec -it redis-0 -- redis-cli
# 滚动更新(重新构建镜像后)
kubectl -n devops rollout restart deployment/aiops
# 进入后端容器
kubectl -n devops exec -it deployment/aiops-backend -- sh
# 查看 PVC 绑定状态
# 查看 PVC
kubectl -n devops get pvc
```
## 配置与密码
## 配置说明
| 项目 | 来源 | 值 |
|------|------|----|
| MySQL 业务账号 | Secret `aiops-secret` | 用户 `aiops` / 密码 `aiops_pass_2026` / 库 `aiops` |
| MySQL root | Secret `aiops-secret` | `aiops_root_2026` |
| JWT | Secret `aiops-secret` | `jwt-secret`(生产请替换为强随机值) |
| JWT | Secret `aiops-secret` | `aiops-jwt-secret-key-2026` |
| Redis | 无密码 | db `0` |
> ⚠️ 生产环境请勿使用仓库内默认密码。修改 `configmap.yaml` 中 Secret 的值后重新 apply,
> 或使用 `kubectl create secret` 覆盖。
> ⚠️ 生产环境请修改 `secret.yaml` 和 `configmap.yaml` 中的默认密码。
## 资源限额
| 组件 | CPU 请求/上限 | 内存请求/上限 |
|------|---------------|---------------|
| backend | 100m / 500m | 512Mi / 1Gi |
| mysql | 250m / 1 | 1Gi / 2Gi |
| aiops | 100m / 1 | 256Mi / 1Gi |
| mysql | 250m / 1 | 512Mi / 2Gi |
| redis | 50m / 250m | 128Mi / 256Mi |
## 关于配置的环境变量占位
`config.yaml`(位于 ConfigMap)中 DB/Redis 的 `host/port/user/password/dbname`、JWT `secret`
均写成 `${ENV_VAR}` 占位形式,实际值在 `backend.yaml` 的 `env` 段注入:
非敏感的 host/port/user/dbname 直接给值(指向 K8s Service),密码则 `valueFrom` 引用 Secret。
后端基于 viper 读取配置。若 `${VAR}` 占位需要由环境变量直接替换嵌套键
(如 `DB_PASSWORD` → `database.password`),建议在程序启动时设置键名映射:
```go
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
```
否则可改为在 `config.yaml` 中直接写明连接串、密码仅由 Secret 注入。两种方式均可,
当前清单采用「环境变量占位 + Secret」的标准 K8s 模式。
## 清理
```bash
./run.sh k8s delete
# 或手动(持久卷需单独删)
kubectl delete -f deploy/k8s/
# 持久卷需单独删除(PVC 由 StatefulSet 保护,删除 STS 后 PVC 仍保留)
kubectl -n devops delete pvc --all
```
-116
View File
@@ -1,116 +0,0 @@
# backend.yaml — AIOps 后端 (Deployment + Service)
# ----------------------------------------------------------------------------
# - 镜像 aiops-backend:latest(前端通过 go:embed 内嵌进同一二进制)
# - 暴露两个端口:
# 8080 = API + WebSocket
# 80 = go:embed 前端 (SPA 静态资源)
# - 配置: ConfigMap aiops-config 挂载到 /app/configs/config.yaml
# - 密码: Secret aiops-secret 以环境变量注入(DB_PASSWORD / JWT_SECRET)
# - Service: ClusterIP,对外暴露 80 与 8080
#
# 部署: kubectl apply -f backend.yaml
# ----------------------------------------------------------------------------
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: aiops-backend
namespace: devops
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: backend
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: backend
template:
metadata:
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: backend
spec:
containers:
- name: aiops-backend
image: aiops-backend:latest
imagePullPolicy: IfNotPresent
env:
# ---- 数据库连接参数(对应 config.yaml 的 ${DB_*} 占位)----
- {name: DB_HOST, value: mysql}
- {name: DB_PORT, value: "3306"}
- {name: DB_USER, value: aiops}
- {name: DB_NAME, value: aiops}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: aiops-secret
key: database-password
# ---- Redis 连接参数(本环境无密码)----
- {name: REDIS_HOST, value: redis}
- {name: REDIS_PORT, value: "6379"}
- {name: REDIS_PASSWORD, value: ""}
# ---- JWT ----
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: aiops-secret
key: jwt-secret
- {name: TZ, value: Asia/Shanghai}
ports:
- {name: api, containerPort: 8080} # API + WebSocket
- {name: web, containerPort: 80} # go:embed 前端
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
livenessProbe:
httpGet:
path: /health
port: api
initialDelaySeconds: 20
periodSeconds: 30
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: api
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: config
mountPath: /app/configs
readOnly: true
volumes:
- name: config
configMap:
name: aiops-config
---
# Service — 对内暴露 80 (前端) 与 8080 (API)
apiVersion: v1
kind: Service
metadata:
name: aiops-backend
namespace: devops
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: backend
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: backend
ports:
- {name: api, port: 8080, targetPort: 8080}
- {name: web, port: 80, targetPort: 80}
+8 -54
View File
@@ -1,78 +1,32 @@
# configmap.yaml — 后端配置 (ConfigMap) + 敏感信息 (Secret)
# ----------------------------------------------------------------------------
# ConfigMap aiops-config:
# - 内含 config.yaml,DB/Redis 连接信息以环境变量占位(${VAR})。
# - 后端 Deployment 将其挂载到 /app/configs/config.yaml(viper 搜索路径 ./configs)。
#
# Secret aiops-secret:
# - 存放 MySQL 密码与 JWT 密钥(明文敏感信息不放 ConfigMap)。
# - 由 backend Deployment / mysql StatefulSet 以环境变量注入。
#
# 部署: kubectl apply -f configmap.yaml
# ----------------------------------------------------------------------------
---
apiVersion: v1
kind: ConfigMap
metadata:
name: aiops-config
namespace: devops
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: backend
data:
config.yaml: |
# AIOps 后端配置
# DB/Redis 连接通过环境变量注入(见 backend Deployment 的 env 段)。
# 敏感字段 (password / jwt) 由 Secret aiops-secret 提供。
# 注意: viper.AutomaticEnv 默认不替换嵌套键中的点(.),如需 DATABASE_HOST ->
# database.host 生效,请在 backend 启动时设置:
# viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
mode: release
port: "8080"
log_level: info
# ---- 数据库 (MySQL) ----
database:
driver: mysql
host: "${DB_HOST}" # -> mysql (k8s Service)
host: mysql
port: 3306
user: "${DB_USER}" # -> aiops
password: "${DB_PASSWORD}" # <- Secret aiops-secret (database-password)
dbname: "${DB_NAME}" # -> aiops
user: aiops
password: aiops_pass_2026
dbname: aiops
charset: utf8mb4
max_conn: 100
max_idle: 10
# ---- Redis ----
redis:
driver: redis # redka(内嵌) / redis(外部)
host: "${REDIS_HOST}" # -> redis (k8s Service)
driver: redis
host: redis
port: 6379
password: "${REDIS_PASSWORD}" # 本环境 Redis 无密码,留空
password: ""
db: 0
# ---- JWT ----
jwt:
secret: "${JWT_SECRET}" # <- Secret aiops-secret (jwt-secret)
secret: "aiops-jwt-secret-key-2026"
expire_hour: 24
# ---- WebSocket ----
websocket:
read_buffer_size: 1024
write_buffer_size: 1024
---
apiVersion: v1
kind: Secret
metadata:
name: aiops-secret
namespace: devops
labels:
app.kubernetes.io/name: aiops
type: Opaque
stringData:
# MySQL 业务账号密码
database-password: "aiops_pass_2026"
# MySQL root 密码(StatefulSet 初始化用)
mysql-root-password: "aiops_root_2026"
# JWT 签名密钥(生产请替换为强随机值)
jwt-secret: "aiops-jwt-secret-change-in-production-2026"
+104
View File
@@ -0,0 +1,104 @@
# deployment.yaml — AIOps 应用 (embed 前端嵌入后端, 单容器单端口)
# ----------------------------------------------------------------------------
# - 镜像 aiops:embed(前端通过 go:embed 内嵌进同一二进制)
# - 单端口 8080 = API + WebSocket + 前端 SPA 静态资源
# - 配置: ConfigMap aiops-config 挂载到 /app/config.yaml
# - Service: NodePort 30080 → 8080
#
# 部署: kubectl apply -f deployment.yaml
# ----------------------------------------------------------------------------
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: aiops
namespace: devops
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: app
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: app
template:
metadata:
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: app
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: aiops
image: aiops-aiops:latest
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
env:
- name: TZ
value: Asia/Shanghai
volumeMounts:
- name: config
mountPath: /app/config.yaml
subPath: config.yaml
readOnly: true
- name: uploads
mountPath: /app/uploads
- name: data
mountPath: /app/data
readinessProbe:
httpGet:
path: /version
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
livenessProbe:
httpGet:
path: /version
port: 8080
initialDelaySeconds: 15
periodSeconds: 30
timeoutSeconds: 5
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
volumes:
- name: config
configMap:
name: aiops-config
- name: uploads
emptyDir: {}
- name: data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: aiops
namespace: devops
labels:
app.kubernetes.io/name: aiops
spec:
type: NodePort
selector:
app.kubernetes.io/name: aiops
app.kubernetes.io/component: app
ports:
- name: http
port: 8080
targetPort: 8080
nodePort: 30080
protocol: TCP
+8 -28
View File
@@ -1,9 +1,9 @@
# ingress.yaml — Ingress 入口路由 (nginx-ingress)
# ----------------------------------------------------------------------------
# 路由规则:
# /api/* -> aiops-backend:8080 (后端 API)
# /ws/* -> aiops-backend:8080 (WebSocket 长连接)
# / -> aiops-backend:80 (go:embed 前端 SPA)
# 路由规则 (embed 模式: 所有流量 → aiops:8080):
# /api/* -> aiops:8080 (后端 API)
# /ws/* -> aiops:8080 (WebSocket 长连接)
# / -> aiops:8080 (go:embed 前端 SPA)
#
# 前提: 集群已安装 nginx Ingress Controller。
# 部署前请修改 host (aiops.local) 与 ingressClassName 为实际值。
@@ -18,42 +18,22 @@ metadata:
labels:
app.kubernetes.io/name: aiops
annotations:
# WebSocket 长连接支持(/ws)
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
# 文件上传大小(与后端 upload.max_size 配合)
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
# 显式转发 WebSocket 升级头
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
spec:
ingressClassName: nginx # 按集群实际 IngressClass 调整
ingressClassName: nginx
rules:
- host: aiops.local # TODO: 修改为实际访问域名
- host: aiops.local
http:
paths:
# ---- API ----
- path: /api
pathType: Prefix
backend:
service:
name: aiops-backend
port:
number: 8080
# ---- WebSocket ----
- path: /ws
pathType: Prefix
backend:
service:
name: aiops-backend
port:
number: 8080
# ---- 前端 (go:embed, 默认兜底) ----
- path: /
pathType: Prefix
backend:
service:
name: aiops-backend
name: aiops
port:
number: 80
number: 8080
+25 -103
View File
@@ -1,62 +1,11 @@
# mysql.yaml — MySQL 8.0 数据库 (StatefulSet + Service + 持久化卷)
# ----------------------------------------------------------------------------
# 组件:
# - mysql-headless (Headless Service): 为 StatefulSet 提供稳定网络标识 mysql-0
# - mysql (ClusterIP Service): 供后端以 mysql:3306 连接
# - mysql (StatefulSet): 单实例 MySQL 8.0
# 账号: 用户 aiops / 密码 aiops_pass_2026 / 数据库 aiops (密码来自 aiops-secret)
# 持久化: volumeClaimTemplates 8Gi (依赖集群 StorageClass 动态供应)
#
# 部署: kubectl apply -f mysql.yaml
# ----------------------------------------------------------------------------
---
# Headless Service — StatefulSet 稳定标识
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
namespace: devops
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
spec:
clusterIP: None
selector:
app.kubernetes.io/name: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
---
# ClusterIP Service — 供应用连接
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: devops
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
---
# StatefulSet
apiVersion: apps/v1
kind: StatefulSet
kind: Deployment
metadata:
name: mysql
namespace: devops
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
spec:
serviceName: mysql-headless
replicas: 1
selector:
matchLabels:
@@ -70,67 +19,40 @@ spec:
- name: mysql
image: mysql:8.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: aiops-secret
key: mysql-root-password
value: "aiops_root_2026"
- name: MYSQL_DATABASE
value: aiops
- name: MYSQL_USER
value: aiops
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: aiops-secret
key: database-password
- name: TZ
value: Asia/Shanghai
args:
# 字符集
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
# 兼容旧客户端认证方式(8.0 默认 caching_sha2_password)
- --default-authentication-plugin=mysql_native_password
ports:
- name: mysql
containerPort: 3306
livenessProbe:
exec:
command:
- sh
- -c
- 'mysqladmin ping -h 127.0.0.1 -uroot -p"$MYSQL_ROOT_PASSWORD"'
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
readinessProbe:
exec:
command:
- sh
- -c
- 'mysqladmin ping -h 127.0.0.1 -uroot -p"$MYSQL_ROOT_PASSWORD"'
initialDelaySeconds: 10
command: ["sh", "-c", "mysqladmin ping -h 127.0.0.1 -uroot -paiops_root_2026"]
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 5
resources:
requests:
cpu: 250m
memory: 1Gi
limits:
cpu: "1"
memory: 2Gi
volumeMounts:
- name: data
mountPath: /var/lib/mysql
# ---- 持久化卷 (8Gi) ----
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 8Gi
# storageClassName: standard # 按集群实际 StorageClass 调整,留空使用默认
volumes:
- name: mysql-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: devops
spec:
selector:
app.kubernetes.io/name: mysql
ports:
- port: 3306
targetPort: 3306
-6
View File
@@ -1,12 +1,6 @@
# namespace.yaml — 创建 devops 命名空间
# 所有 AIOps 资源(MySQL / Redis / 后端 / Ingress)统一部署在该命名空间下。
# 必须最先 apply,其它资源依赖该命名空间存在。
# 部署: kubectl apply -f namespace.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: devops
labels:
app.kubernetes.io/name: aiops
app.kubernetes.io/part-of: aiops
+27
View File
@@ -0,0 +1,27 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: aiops-config
namespace: devops
data:
config.yaml: |
mode: release
port: "8080"
log_level: info
database:
driver: mysql
host: mysql
port: 3306
user: root
password: aiops_root_2026
dbname: aiops
charset: utf8mb4
redis:
driver: redis
host: redis
port: 6379
password: ""
db: 0
jwt:
secret: "aiops-jwt-secret-key-2026"
expire_hour: 24
+15 -86
View File
@@ -1,61 +1,11 @@
# redis.yaml — Redis 7 缓存 (StatefulSet + Service + 持久化卷)
# ----------------------------------------------------------------------------
# 组件:
# - redis-headless (Headless Service): StatefulSet 稳定标识 redis-0
# - redis (ClusterIP Service): 供后端以 redis:6379 连接
# - redis (StatefulSet): 单实例 Redis 7,无密码,db 0
# 持久化: volumeClaimTemplates 2Gi + AOF/RDB 落盘
#
# 部署: kubectl apply -f redis.yaml
# ----------------------------------------------------------------------------
---
# Headless Service — StatefulSet 稳定标识
apiVersion: v1
kind: Service
metadata:
name: redis-headless
namespace: devops
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
spec:
clusterIP: None
selector:
app.kubernetes.io/name: redis
ports:
- name: redis
port: 6379
targetPort: 6379
---
# ClusterIP Service — 供应用连接
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: devops
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: redis
ports:
- name: redis
port: 6379
targetPort: 6379
---
# StatefulSet
apiVersion: apps/v1
kind: StatefulSet
kind: Deployment
metadata:
name: redis
namespace: devops
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
spec:
serviceName: redis-headless
replicas: 1
selector:
matchLabels:
@@ -69,43 +19,22 @@ spec:
- name: redis
image: redis:7-alpine
imagePullPolicy: IfNotPresent
command: ["redis-server"]
args:
- --appendonly yes # 开启 AOF
- --save 60 1000 # RDB: 60s 内 1000 次变更快照
- --databases 1 # 仅使用 db 0
- --maxmemory 256mb
- --maxmemory-policy allkeys-lru
ports:
- name: redis
containerPort: 6379
livenessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 15
periodSeconds: 10
- containerPort: 6379
readinessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
volumeMounts:
- name: data
mountPath: /data
# ---- 持久化卷 (2Gi) ----
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
# storageClassName: standard # 按集群实际 StorageClass 调整
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: devops
spec:
selector:
app.kubernetes.io/name: redis
ports:
- port: 6379
targetPort: 6379
+10
View File
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: aiops-secret
namespace: devops
type: Opaque
stringData:
mysql-root-password: "aiops_root_2026"
mysql-password: "aiops_pass_2026"
jwt-secret: "aiops-jwt-secret-key-2026"