# opsxsql 部署到 Kubernetes ## 文件 | 文件 | 说明 | |---|---| | `install.sh` | **一键部署**(推荐):云探测/SC 探测/本地 PV 兜底/密钥/清单渲染/失败诊断 | | `namespace.yaml` | `opsxsql` 命名空间 | | `pvc.yaml` | 数据卷(默认 10Gi,集群默认 StorageClass) | | `deployment.yaml` | 平台本体,**单副本 + Recreate** | | `service.yaml` | ClusterIP `opsxsql:80` | | `service-nodeport.yaml` | 可选 NodePort 入口(`:30900`) | | `ingress.yaml` | 可选,通用 nginx Ingress | | `examples/` | 跨云模板:阿里 ALB / 腾讯 qcloud Ingress、Secret 模板 | ## 前置条件(`install.sh` 会自动检查,不通过直接给出具体修法) 脚本启动时做**三级预检 + 一级软检查**,任何一级不通过都会立即退出并打印「是哪一类问题、 下一步做什么」,不会跑到一半才报错: | 预检项 | 不通过时的提示内容 | |--------|-------------------| | **kubectl 是否安装** | 按 CentOS/TencentOS、Ubuntu/Debian、macOS 分别给安装命令;并给出「机器没有外网」时的替代方案(控制台下载 / 内网跳板机执行 / 只 scp 二进制) | | **kubeconfig 是否存在** | 打印实际查找路径(`$KUBECONFIG` 或 `~/.kube/config`),给出腾讯云 TKE / 阿里云 ACK / AWS EKS 各自下载 kubeconfig 的入口,以及 `chmod 600` 建议 | | **能否连上 API Server** | **按错误类型分类**(见下表),不是笼统一句「请检查 kubeconfig」 | | **部署权限(软检查)** | `kubectl auth can-i create deployments.apps -n ` 非 `yes` 时告警,提示绑定 Role 或改用管理员 kubeconfig;**不阻断**,避免首次部署时命名空间尚未创建导致误拦 | ### 连不上集群时的分类提示 | 实际错误 | 脚本的判断 | 给出的处理方向 | |---------|-----------|---------------| | `current-context is not set` / `context does not exist` | kubeconfig 没有可用 context | `kubectl config get-contexts` → `use-context` → 重新下载 kubeconfig | | `Unauthorized` / `Authentication required` | 认证失败(云厂商 token 几小时就过期) | 回控制台重新下载 kubeconfig;自建集群查客户端证书 | | `Forbidden` / `403` | 已连上集群但 RBAC 拒绝 | `kubectl auth whoami`、`auth can-i --list -n `,列出部署所需的具体资源权限 | | `x509` / `certificate` / `tls:` | 证书过期或域名不匹配 | 确认 API Server 证书;可信内网可临时 `--insecure-skip-tls-verify` 排障 | | `connection refused` / `no such host` / `context deadline exceeded` / `i/o timeout` | 网络不通 | ①`curl -k /version` ②**内网地址需 VPN/专线** ③安全组放行 6443 ④查集群状态 ⑤换成跳板机试 | 失败时的完整输出形如: ```text ❌ 连不上集群 API Server(网络不通) kubeconfig : /root/.kube/config 当前 context : tke-pre API Server : https://172.19.16.13:443 当前用户 : admin 实际报错: Unable to connect to the server: context deadline exceeded (...) ── 按顺序排查 ─────────────────────────────────────────────────────── 1) 地址对不对?用上面打印的 API Server 测一下: curl -k --max-time 5 /version 2) 要不要 VPN / 专线?云上 API Server 常是内网地址(10.x / 172.16~31.x / 192.168.x)... 3) 安全组 / 防火墙:云厂商默认只放行运维网段访问 6443 端口 4) 集群本身是否正常:控制台看集群状态是否「运行中」 5) 换台机器试:在能访问集群的跳板机上执行本脚本,可排除本机网络问题 ``` > 预检只读不写、耗时 < 1 秒。API Server 连接超时可用 `KUBECTL_TIMEOUT=15s` 放宽(默认 8s)。 ## 一键部署(自动跨云适配) `install.sh` 自动探测云平台(阿里 ACK / 腾讯 TKE / AWS EKS / 华为 CCE / GCP GKE / Azure AKS / K3s / 自建) 与 StorageClass(显式指定 > default 注解 > 唯一 SC);**自建集群无 SC 时自动创建零依赖的节点本地 PV** (hostPath + nodeAffinity 锁节点 + Retain,无需 local-path-provisioner 镜像);部署失败时按云平台给出 镜像仓库/SC 定制诊断。幂等:重复执行不覆盖密钥、不重建数据卷。 ```bash # 默认(镜像 opsxsql:latest) bash kubernetes/install.sh # 指定镜像 + NodePort 入口 IMAGE=registry.example.com/opsxsql:v1.0.0 bash kubernetes/install.sh --nodeport # 指定镜像 + 通用 nginx Ingress 域名(其他云模板见 examples/) IMAGE=registry.example.com/opsxsql:v1.1.0 bash kubernetes/install.sh --ingress opsxsql.example.com # 自定义命名空间 / 卷大小 / 手动指定 StorageClass / 强制本地存储 NS=sql-audit PVC_SIZE=20Gi bash kubernetes/install.sh STORAGE_CLASS=alicloud-disk-essd bash kubernetes/install.sh LOCAL_STORAGE=force NODE_NAME=node1 bash kubernetes/install.sh # 数据固定 node1:/var/lib/opsxsql-data ``` | 环境变量 | 默认 | 说明 | |---|---|---| | `IMAGE` | `opsxsql:latest` | 镜像(构建:仓库根 `docker compose build` 或 `docker build .`) | | `NS` | `opsxsql` | 命名空间 | | `STORAGE_CLASS` | 自动探测 | 指定 StorageClass | | `PVC_SIZE` | `10Gi` | 数据卷容量 | | `WITH_NODEPORT` / `--nodeport` | `0` | 附带 NodePort `:30900` 入口 | | `LOCAL_STORAGE` | `auto` | 无 SC 时:`auto` 自动建本地 PV / `off` 仅提示 / `force` 强制本地 | | `NODE_NAME` / `PV_PATH` | 自动 / `/var/lib/opsxsql-data` | 本地存储落点 | ## 分步部署(等价于 install.sh) ```bash # 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 已内置该约束)。 - 备份(冷备一条命令): ```bash 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): ```yaml apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshot metadata: name: opsxsql-data-20261026 namespace: sql 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 用);不用该功能可忽略,无需外置依赖 | ## 升级 / 卸载 ```bash # 升级:换镜像 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 一起删,谨慎 ```