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 拆分。
This commit is contained in:
opsx committed 2026-10-28 07:25:16 +00:00
1 parent 0c57e18f19
commit 9dcb39e971
2 files changed
+212 -2

No files matched your search

+46
View File
@@ -13,6 +13,52 @@
| `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 ④查集群状态 ⑤换成跳板机试 |
失败时的完整输出形如:
```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 <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 / 自建)
+166 -2
View File
@@ -43,9 +43,173 @@ done
# ============================================================================
# 0) 前置检查
#
# 分三级:kubectl 是否存在 → 能否连上集群 → 有没有部署权限。
# 设计原则:每级失败都要说清「是哪一类问题 + 下一步具体做什么」。
# 只丢一句「请检查 kubeconfig」等于没说 —— 新人根本不知道该查什么,
# 也不知道是没装工具、网络不通、凭据过期、还是 RBAC 没权限。
# ============================================================================
command -v kubectl >/dev/null 2>&1 || die "未找到 kubectl,请先安装"
kubectl version --request-timeout=5s >/dev/null 2>&1 || die "kubectl 无法连接集群,请检查 kubeconfig"
KUBECTL_TIMEOUT="${KUBECTL_TIMEOUT:-8s}"
# 当前 context / server / user:失败时一起打印,一眼看出连的是哪个集群
k8s_env_info() {
local ctx server user kc
ctx=$(kubectl config current-context 2>/dev/null || echo "(无)")
server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null || true)
user=$(kubectl config view --minify -o jsonpath='{.users[0].name}' 2>/dev/null || true)
kc="${KUBECONFIG:-$HOME/.kube/config}"
printf ' kubeconfig : %s\n' "$kc" >&2
printf ' 当前 context : %s\n' "$ctx" >&2
printf ' API Server : %s\n' "${server:-(未知)}" >&2
printf ' 当前用户 : %s\n' "${user:-(未知)}" >&2
}
# 统一失败出口:一句话结论 + 环境信息 + 可执行的处理步骤
k8s_die() {
printf '\n\033[1;31m❌ %s\033[0m\n\n' "$1" >&2
k8s_env_info
printf '\n%b\n\n' "$2" >&2
exit 1
}
# ── 0.1 kubectl 是否存在 ──────────────────────────────────────────────
if ! command -v kubectl >/dev/null 2>&1; then
printf '\n\033[1;31m❌ 找不到 kubectl 命令\033[0m\n\n' >&2
cat >&2 <<'KUBECTL_INSTALL_HELP'
本脚本通过 kubectl 操作 K8s 集群,需要先安装这个命令行工具。
── 安装方式 ───────────────────────────────────────────────────────
通用 Linux(官方二进制,最省事):
curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
CentOS / TencentOS / RHEL : sudo yum install -y kubectl
Ubuntu / Debian : sudo apt-get update && sudo apt-get install -y kubectl
macOS : brew install kubectl
── 装完自检 ───────────────────────────────────────────────────────
kubectl version --client
── 这台机器没有外网怎么办 ─────────────────────────────────────────
· 云控制台「集群 → 连接信息」一般可直接下载 kubectl 与 kubeconfig
· 或者在内网跳板机 / 能访问集群的机器上执行本脚本
· 只需把 kubectl 二进制 scp 过来即可,不依赖 Docker / Jenkins
KUBECTL_INSTALL_HELP
exit 1
fi
# ── 0.2 kubeconfig 文件是否存在 ────────────────────────────────────────
# 必须先单独判一次:KUBECONFIG 指向不存在的文件时,kubectl 会忽略它并
# 退回默认规则,最终报出的往往是 "Authentication required"/"connection refused"
# 这类**误导性**错误,让人以为是凭据或网络问题,实际只是配置没放对位置。
_KC_PATHS="${KUBECONFIG:-$HOME/.kube/config}"
# KUBECONFIG 允许用 ':' 分隔多个路径,任意一个存在即算通过。
# 注意不要写成 while read 循环:printf 输出没有结尾换行时,read 会
# 带着数据返回非 0(EOF),`while read` 的循环体一次都不会执行 —— 踩过。
_kc_found=0
_OLD_IFS="${IFS}"
IFS=':'
for _p in ${_KC_PATHS}; do
if [ -n "${_p}" ] && [ -f "${_p}" ]; then
_kc_found=1
break
fi
done
IFS="${_OLD_IFS}"
if [ "${_kc_found}" -eq 0 ]; then
k8s_die "找不到 kubeconfig 文件(不知道该连哪个集群)" \
" 查找位置: ${_KC_PATHS}
(KUBECONFIG 环境变量未设置时,默认只找 ~/.kube/config)
── 怎么修 ─────────────────────────────────────────────────────────
1) 从云控制台下载 kubeconfig:
腾讯云 TKE : 集群 → 基本信息 → 连接信息 → 下载 kubeconfig
阿里云 ACK : 集群 → 集群信息 → 连接信息 → 复制/下载 kubeconfig
AWS EKS : aws eks update-kubeconfig --name <集群名> --region <区域>
2) 放到默认位置(推荐):
mkdir -p ~/.kube && mv <下载的文件> ~/.kube/config && chmod 600 ~/.kube/config
3) 或者用环境变量指向任意路径:
export KUBECONFIG=/path/to/kubeconfig
4) 确认生效: kubectl config get-contexts
5) 重新执行本脚本"
fi
# ── 0.3 能否连上集群(探测一次,按错误类型分别给建议)────────────────
if ! PROBE_OUT="$(kubectl version --request-timeout="${KUBECTL_TIMEOUT}" 2>&1)"; then
case "${PROBE_OUT}" in
*"does not exist"*|*"no context exists"*|*"current-context is not set"*|*"context was not found"*)
k8s_die "kubeconfig 里没有可用的 context(集群配置不对)" \
" ── 怎么修 ─────────────────────────────────────────────────────────
1) 确认 kubeconfig 在哪: echo \$KUBECONFIG ls -l ~/.kube/config
2) 看有哪些 context: kubectl config get-contexts
3) 切到正确的那一个: kubectl config use-context <名字>
4) 完全没有配置就下载: 腾讯云 → 集群 → 基本信息 → 连接信息 → 下载 kubeconfig
放到 ~/.kube/config,或 export KUBECONFIG=/path/to/config
5) 重新执行本脚本" ;;
*"Unauthorized"*|*"Authentication required"*|*"credentials"*|*"invalid bearer token"*)
k8s_die "集群认证失败(凭据无效或已过期)" \
" ── 怎么修 ─────────────────────────────────────────────────────────
· 云厂商 kubeconfig 里一般是**临时 token**,有效期几小时,过期就 401
→ 回控制台重新下载 kubeconfig,覆盖 ~/.kube/config
· 自建集群看客户端证书是否过期:
kubectl config view --minify --raw | grep client-certificate-data
· 验证当前身份: kubectl auth whoami (旧版用 kubectl get ns 试)" ;;
*"Forbidden"*|*"(403)"*)
k8s_die "已经连上集群,但当前账号没有权限(RBAC 拒绝)" \
" ── 怎么修 ─────────────────────────────────────────────────────────
· 确认身份: kubectl auth whoami
· 看能干什么: kubectl auth can-i --list -n ${NS}
· 部署本平台需要在 ${NS} 命名空间具备:
deployments.apps / services / persistentvolumeclaims / configmaps / secrets 的 create、get
若该命名空间还不存在,还需要集群级 create namespaces
· 找集群管理员绑定具备上述权限的 Role,或直接用管理员 kubeconfig 执行本脚本" ;;
*"x509"*|*"certificate"*|*"tls:"*|*"TLS"*)
k8s_die "集群证书校验失败(证书过期 / 域名不匹配 / 自签证书)" \
" ── 怎么修 ─────────────────────────────────────────────────────────
· 云托管集群极少出现,多见于自建集群;先确认 API Server 证书是否过期
· 可信内网内临时跳过校验(仅用于排障,不要长期使用):
kubectl --insecure-skip-tls-verify=true get ns
· 检查 kubeconfig 里 server 的地址/域名是否在证书 SAN 内" ;;
*"connection refused"*|*"no such host"*|*"i/o timeout"*|*"context deadline exceeded"*|*"network is unreachable"*|*"Unable to connect to the server"*|*"timeout"*)
k8s_die "连不上集群 API Server(网络不通)" \
" 实际报错: $(printf '%s' "${PROBE_OUT}" | tail -1)
── 按顺序排查 ───────────────────────────────────────────────────────
1) 地址对不对?用上面打印的 API Server 测一下:
curl -k --max-time 5 <API Server>/version
2) 要不要 VPN / 专线?云上 API Server 常是**内网地址**(10.x / 172.16~31.x / 192.168.x),
本机不在同一 VPC 时,必须先连 VPN、走专线,或把本机 IP 加进安全组白名单
3) 安全组 / 防火墙:云厂商默认只放行运维网段访问 6443 端口
4) 集群本身是否正常:控制台看集群状态是否「运行中」
5) 换台机器试:在能访问集群的跳板机上执行本脚本,可排除本机网络问题" ;;
*)
k8s_die "kubectl 无法连接集群" \
" 实际报错:
$(printf '%s\n' "${PROBE_OUT}" | sed 's/^/ /')
── 通用排查 ─────────────────────────────────────────────────────────
· kubectl config get-contexts # 当前用的是哪个 context
· kubectl cluster-info # API Server 是否可达
· echo \$KUBECONFIG # 确认读到的是哪个 kubeconfig
· 容器/精简镜像里执行时,注意镜像内可能没有 ca-certificates 与 kubectl" ;;
esac
fi
# ── 0.4 部署权限预检(只告警,不阻断)────────────────────────────────
# 说明:第一次部署时目标命名空间可能还不存在,can-i 对命名空间级资源会返回 no,
# 为避免误拦正常流程这里只提示;真正的拒绝会在 apply 阶段以 Forbidden 暴露。
if [ "$(kubectl auth can-i create deployments.apps -n "${NS}" --request-timeout="${KUBECTL_TIMEOUT}" 2>/dev/null || echo unknown)" != "yes" ]; then
warn "当前账号在命名空间 ${NS} 未确认具备部署权限(kubectl auth can-i 非 yes)"
warn "若随后 apply 报 Forbidden:请改用管理员 kubeconfig,或让管理员绑定 Role 后再执行"
fi
# ============================================================================
# 0.1) 云平台识别(信息展示 + 失败诊断用)