- multi-stage root Dockerfile (opsx-loki pattern): frontend dist + go binary + gh-ost in one alpine image, non-root user, HEALTHCHECK, entrypoint warning for missing SECRET_KEY; gin now serves the SPA from DIST_DIR (asset/db-logos/favicon passthrough, /api returns JSON 404, SPA fallback to index.html) - one origin, no CORS surface - docker-compose.yml rewritten: single service, named data volume, no-new-privileges + cap_drop ALL, /health healthcheck, resource limits, log rotation; SECRET_KEY required (openssl rand -hex 32), JWT_SECRET optional (auto-generated and persisted in prod) - kubernetes/: install.sh one-command deploy (idempotent secret reuse, --nodeport/--ingress flags, rollout wait, backup tips) plus namespace/secret/pvc/deployment(single replica + Recreate, probes, resource limits, non-root)/service/nodeport/ingress manifests and README (sqlite single-writer constraints, snapshot backup) - docs: README quick-start now has 3 deployment paths; ARCHITECTURE ch.14 expanded single-image runtime verified locally (SPA/assets/api/login coexist on :9002); full image build left to server (docker hub unreachable from this machine)
3.4 KiB
3.4 KiB
opsxsql 部署到 Kubernetes
文件
| 文件 | 说明 |
|---|---|
install.sh |
一键部署(推荐):建命名空间/生成密钥/应用全部清单/等待就绪 |
namespace.yaml |
opsxsql 命名空间 |
secret.example.yaml |
密钥模板(建议用 kubectl create secret,install.sh 已自动处理) |
pvc.yaml |
数据卷(默认 10Gi,集群默认 StorageClass) |
deployment.yaml |
平台本体,单副本 + Recreate |
service.yaml |
ClusterIP opsxsql:80 |
service-nodeport.yaml |
可选 NodePort 入口(:30900) |
ingress.yaml |
可选,按集群 ingressClass 调整 |
一键部署
# 默认(镜像 opsxsql:latest,需先 build&push 或 node 可用)
bash kubernetes/install.sh
# 指定镜像 + NodePort 入口
IMAGE=registry.example.com/opsxsql:v1.0.0 bash kubernetes/install.sh --nodeport
# 指定镜像 + Ingress 域名
IMAGE=registry.example.com/opsxsql:v1.0.0 bash kubernetes/install.sh --ingress opsxsql.example.com
# 自定义命名空间 / 卷大小
NS=sql-audit PVC_SIZE=20Gi bash kubernetes/install.sh
分步部署(等价于 install.sh)
# 1) 密钥(只生成一次;SECRET_KEY 丢失会导致已加密的实例/LDAP 密码无法解密)
kubectl -n opsxsql create secret generic opsxsql-secrets \
--from-literal=SECRET_KEY="$(openssl rand -hex 32)" \
--from-literal=JWT_SECRET="$(openssl rand -hex 32)"
# 2) 清单(先把 deployment.yaml 里的 image 改成实际仓库地址)
kubectl apply -f kubernetes/namespace.yaml
kubectl apply -f kubernetes/pvc.yaml
kubectl apply -f kubernetes/deployment.yaml
kubectl apply -f kubernetes/service.yaml
# 3) 可选入口
kubectl apply -f kubernetes/service-nodeport.yaml # 或 ingress.yaml
持久化(重要)
/app/data挂 PVC,保存 SQLite 数据库与持久化 JWT 密钥。- 必须
replicas: 1+strategy: Recreate:SQLite 是单写者,滚动更新时两个 Pod 同时挂同一 RWO PVC 会互相覆盖(install.sh 已内置该约束)。 - 备份(冷备一条命令):
kubectl -n opsxsql exec deploy/opsxsql -- sqlite3 /app/data/sqlite3.db '.backup /app/data/backup-$(date +%F).db'
kubectl -n opsxsql cp deploy/opsxsql:/app/data/backup-$(date +%F).db ./backup.db
- 云盘快照走 CSI VolumeSnapshot(AWS EBS / 腾讯 CBS / 华为 EVS / 阿里 ESSD 同一套 API):
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: opsxsql-data-20261026
namespace: opsxsql
spec:
volumeSnapshotClassName: <集群的 snapshotClass>
source:
persistentVolumeClaimName: opsxsql-data
多云兼容
| 项 | 做法 |
|---|---|
| 存储类 | pvc.yaml 不写 storageClassName 用默认 SC;无默认 SC 时填云厂名(AWS gp3 / 腾讯 cbs / 华为 csi-disk / 阿里 alicloud-disk-essd) |
| 镜像仓库 | deployment.yaml 的 image 填目标云可拉的仓库(Harbor / ACR / TCR / SWR),或本仓库根 Dockerfile 自行构建 |
| gh-ost | 镜像内置(在线大表 DDL 用);不用该功能可忽略,无需外置依赖 |
升级 / 卸载
# 升级:换镜像 tag 重新 install(Recreate 策略自动重建,数据卷不动)
IMAGE=registry.example.com/opsxsql:v1.1.0 bash kubernetes/install.sh --nodeport
# 卸载(数据卷保留;需要连数据一起删加 --include-data)
kubectl -n opsxsql delete deploy,svc,ingress opsxsql opsxsql-nodeport 2>/dev/null
kubectl delete ns opsxsql # 会连 PVC 一起删,谨慎