今天折腾两套独立 K8s 集群的跳板机权限管理,原本以为用原生的 kubectl config view --flatten 打平合并一下就行,结果连踩三个暗坑。记录一下排障过程。
环境说明:
两套独立部署的 K8s 集群(开发 10.20.30.128,生产 10.20.20.40)。跳板机需要通过 use-context 自由切换。
坑一:同名覆盖导致配置丢失
Kubeadm 或 Sealos 默认部署的集群,其 admin.conf 内部命名完全一致(集群名统一为 kubernetes,用户名为 kubernetes-admin)。
如果直接拿这两份原始配置执行 flatten 合并,后者的配置会直接覆盖前者,导致合并后的文件里只剩下一个集群的 IP 和证书。
解决办法:合并前对源文件进行内部对象重命名
切忌直接用 sed 盲替,因为 kubernetes-admin 包含了 kubernetes,替换顺序不对会导致名字变成畸形的 cluster-XXX-admin。正确的替换顺序如下:
# 1. 备份原文件
scp root@10.20.30.128:/etc/kubernetes/admin.conf ~/.kube/config-128-raw
scp root@10.20.20.40:/etc/kubernetes/admin.conf ~/.kube/config-40-raw
# 2. 严格按由长到短的顺序替换 128 集群
sed -e 's/kubernetes-admin@kubernetes/context-128/g' \
-e 's/kubernetes-admin/admin-128/g' \
-e 's/kubernetes/cluster-128/g' \
~/.kube/config-128-raw > ~/.kube/config-128
# 3. 替换 40 集群
sed -e 's/kubernetes-admin@kubernetes/context-40/g' \
-e 's/kubernetes-admin/admin-40/g' \
-e 's/kubernetes/cluster-40/g' \
~/.kube/config-40-raw > ~/.kube/config-40
# 4. 执行原生打平合并
export KUBECONFIG=~/.kube/config-128:~/.kube/config-40
kubectl config view --flatten > ~/.kube/config
坑二:Sealos 劫持 API 域名报 dial tcp no such host
合并完执行 kubectl get pods,直接报错:
couldn't get current server API group list: Get "https://apiserver.cluster.local:6443/api?timeout=32s": dial tcp: lookup apiserver.cluster.local on 223.5.5.5:53: no such host
原因:
Sealos 为了做高可用,会在 kubeconfig 里把 API Server 地址写死为假域名 apiserver.cluster.local,并依赖集群节点的 /etc/hosts 来解析。
在独立的跳板机上,本地没这个 hosts 映射,请求自然被打到了公网 DNS(223.5.5.5)从而解析失败。
解决办法:替换真实 IP
千万别在跳板机的 /etc/hosts 里配解析,因为你有两套集群,共用这一个假域名肯定会冲突。
正确的做法是打开最终的 ~/.kube/config,找到对应集群的 server: 字段,把 https://apiserver.cluster.local:6443 直接改成对应集群的真实 Master IP 或 VIP:
clusters:
- name: cluster-128
cluster:
server: https://10.20.30.128:6443 # 这里换成真实 IP
坑三:修改 config 后未生效
排障过程中发现一个诡异现象:修改了 ~/.kube/config 后依然报错,但单独修改原本的 config-40 却能立刻生效。
原因:
第一步合并操作时执行的 export KUBECONFIG=~/.kube/config-128:~/.kube/config-40 在当前终端依然生效。
在 K8s 的底层加载逻辑中,KUBECONFIG 环境变量的优先级绝对高于默认文件路径。此时 kubectl 动态读取的是这两个原始文件,完全无视了刚改好的 ~/.kube/config。
解决办法:
执行 unset KUBECONFIG 销毁临时环境变量,或者断开当前 SSH 会话重连即可。