Files
opsx 9dcb39e971 feat(k8s): install.sh 三级部署预检——kubectl 缺失/连不上集群时给出可执行的具体修法
用户反馈:部署时报错只说「未找到 kubectl,请先安装」「kubectl 无法连接集群,
请检查 kubeconfig」,对新人等于没说 —— 不知道是没装工具、网络不通、凭据过期
还是 RBAC 没权限,也不知道下一步查什么。

原实现只有两行:
    command -v kubectl || die "未找到 kubectl,请先安装"
    kubectl version --request-timeout=5s || die "kubectl 无法连接集群,请检查 kubeconfig"

改为三级预检 + 一级软检查:

【0.1 kubectl 是否存在】
  按 CentOS/TencentOS、Ubuntu/Debian、macOS 分别给安装命令;
  额外给「机器没有外网」的替代路径(控制台下载 / 内网跳板机 / 只 scp 二进制)。

【0.2 kubeconfig 文件是否存在】← 新增,堵一个误判
  KUBECONFIG 指向不存在的文件时,kubectl 会忽略它并退回默认规则,
  最终报出 "Authentication required" / "connection refused" 这类误导性错误,
  让人白查凭据和网络。现在单独判一次,直接给出查找路径 + 各云控制台下载入口。
  支持 KUBECONFIG 用 : 分隔多路径,任一存在即通过。

【0.3 能否连上 API Server】按错误类型分类,各给专属修法
  · context 不存在      → get-contexts / use-context / 重新下载
  · 401 认证失败        → 云厂商 token 有效期几小时,重新下载;自建查客户端证书
  · 403 RBAC 拒绝       → auth whoami / auth can-i --list,列出部署所需的具体资源
  · x509 证书问题       → 确认证书过期;可信内网可临时 insecure-skip-tls-verify
  · 网络不通            → curl -k <API>/version、VPN/专线、安全组放行 6443、换跳板机
  · 其他                → 原样打印 kubectl 错误 + 通用排查清单

【0.4 部署权限软检查】auth can-i 非 yes 时只告警不阻断
  (首次部署时目标命名空间可能还不存在,硬拦会误伤正常流程)

失败时统一打印环境信息(kubeconfig 路径 / context / API Server / 当前用户),
一眼看出连的是哪个集群。连接超时可用 KUBECTL_TIMEOUT=15s 放宽(默认 8s)。

README 同步新增「前置条件」章节:预检项对照表 + 错误分类表 + 失败输出示例。

=== 验证 ===
从真实 install.sh 抽出预检段,用假 kubectl 精确模拟 8 种场景(两个脚本各跑一遍):
  A 没有 kubectl            → 退出 1,打印各系统安装命令 ✅
  B API Server 超时         → 退出 1,提示 VPN/专线/安全组 ✅
  C 没有 context            → 退出 1,提示 get-contexts/use-context ✅
  D 401 凭据过期            → 退出 1,提示重新下载 kubeconfig ✅
  E 403 权限不足            → 退出 1,列出所需资源权限 ✅
  F x509 证书过期           → 退出 1,提示证书/insecure 排障 ✅
  G 正常环境(真实集群)     → 通过预检,退出 0 ✅
  H kubeconfig 文件不存在   → 退出 1,提示下载位置(不误报成 401)✅
  结果:阻断 7/7、正常通过 1/1;bash -n 语法检查通过

⚠️ 踩坑记录:kubeconfig 多路径判断最初写成
     while IFS= read -r _p; do ...; done < <(printf "%s" "$PATHS" | tr ":" "\n")
   printf 输出没有结尾换行 → read 带着数据返回非 0(EOF)→ 循环体一次都不执行,
   导致所有场景都误报「找不到 kubeconfig」。改用 IFS=":" + for 拆分。
2026-10-28 07:25:16 +00:00
..

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 <ns> 非 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 <ns>,列出部署所需的具体资源权限
x509 / certificate / tls: 证书过期或域名不匹配 确认 API Server 证书;可信内网可临时 --insecure-skip-tls-verify 排障
connection refused / no such host / context deadline exceeded / i/o timeout 网络不通 ①curl -k <API>/version ②内网地址需 VPN/专线 ③安全组放行 6443 ④查集群状态 ⑤换成跳板机试

失败时的完整输出形如:

❌ 连不上集群 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 <API Server>/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 定制诊断。幂等:重复执行不覆盖密钥、不重建数据卷。

# 默认(镜像 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)

# 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: 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 用);不用该功能可忽略,无需外置依赖

升级 / 卸载

# 升级:换镜像 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 一起删,谨慎