课程目录(第 27 章 / 共 33 章)
课程/平台化与规模化

多集群与访问管理:kubeconfig、上下文与服务账号

27 章 / 共 33·20 分钟·进阶多集群kubeconfigServiceAccount权限

集群从一套变成多套之后,最危险的不再是「不会用 kubectl」,而是「连错集群、发错凭证」——这一章讲清 kubeconfig 的结构与合并规则、上下文的正确用法,以及怎么给同事和 CI 发一份最小权限的凭证。

学完这一章,你将能够

  • 拆解 kubeconfig 的 clusters / users / contexts / current-context 四段,说清每段回答什么问题
  • 会用 KUBECONFIG 多文件合并与 --kubeconfig / --context 覆盖,并随时确认「我现在连的是哪套集群」
  • 对比客户端证书、token、OIDC、exec 插件四种认证方式的适用场景与轮转难度
  • 用 kubectl create token 拼出一份只有某个 ServiceAccount 权限的 kubeconfig,并用 kubectl auth can-i 验证

一套集群不够用的时候

前面十几章里你的世界只有一套集群,所有团队、所有环境都靠 Namespace 隔开——这在小规模下够用,因为第 12 章 命名空间与 RBAC 已经把「逻辑隔离」做得很好了。

但隔离是有层次的。Namespace 隔离的是对象的名字和权限,它隔离不了控制面本身:CRD 的版本、Ingress 控制器、CNI 插件、apiserver 参数都是集群级的,某个命名空间里的实验把 etcd 写爆或把 CRD 升坏,其他命名空间会一起受影响。所以「要不要多集群」不是偏好问题,而是隔离级别问题。

触发条件为什么 Namespace 不够
环境隔离(dev / staging / prod)集群级组件(CRD、Ingress、CNI)需要在不同环境跑不同版本
控制爆炸半径控制面故障、etcd 打满、一次失败的 CRD 升级会波及全部命名空间
多租户 / 多客户客户要求硬隔离,甚至要求独立控制面与独立升级窗口
地域与合规数据不能出境、需要就近接入,必须物理上落在不同地域
灰度与迁移换 CNI、升级大版本、搬机房时,新旧两套要并行跑一段时间
多集群从来不是目标,你要的是那个隔离级别。代价是把问题从「隔离」换成「混乱」:
新增问题具体表现
配置漂移同一个应用在两套集群里的镜像版本、参数、副本数慢慢就不一致了
凭证管理每套集群一套 CA、一套 kubeconfig,证书轮转次数翻倍
观测割裂指标、日志、告警散在多个集群,故障时第一步先要确认「是哪套」
网络互通跨集群的 Service 不能直接解析,Pod 网段还可能重叠
运维成本每套集群的控制面、etcd 备份、升级窗口都要有人负责

kubeconfig 的四段结构

kubeconfig 是 kubectl 的配置文件,默认在 ~/.kube/config。它只回答四个问题,而且把这四个问题拆成了四段——新手容易把它当成一坨黑盒,其实拆开看非常简单

yaml
apiVersion: v1
kind: Config
clusters: # ① 去哪:集群地址与 CA
  - name: prod
    cluster:
      server: https://10.0.0.100:6443
      certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
users: # ② 我是谁:凭证
  - name: prod-ci
    user:
      token: eyJhbGciOiJSUzI1NiIsImtpZCI6...
contexts: # ③ 把 ① ② 绑起来,再补一个默认命名空间
  - name: prod-ci
    context:
      cluster: prod
      user: prod-ci
      namespace: demo
current-context: prod-ci # ④ 现在用哪个 context

关键是理解 clusters 和 users 是「零件」,context 才是「组合」

回答的问题关键子字段
clusters连哪台 apiserver、怎么校验它的身份servercertificate-authority-datacertificate-authority(文件路径)
users我是谁、用什么凭证client-certificate-data + client-key-datatokenexec 插件
contexts用哪个集群 + 哪个身份 + 默认哪个命名空间clusterusernamespace
current-context不额外指定时默认用哪个 context只有一个值

这套设计的好处是组合自由:同一个 prod 集群可以同时有「我的证书 context」「CI 的 SA token context」「只读排查 context」;同一个身份也能访问多套集群。所以别按「一台集群一份配置」理解,要按「一个身份 + 一套集群 = 一个 context」理解。

text
  KUBECONFIG=~/.kube/configs/dev.yaml:~/.kube/configs/prod.yaml
        │  kubectl 按顺序合并,同名键以「第一个文件」为准

  ┌─ ① clusters(去哪)    dev → https://dev:6443, prod → https://prod:6443
  ├─ ② users(我是谁)     dev-admin → 证书, prod-ci → SA token / exec 插件
  ├─ ③ contexts          prod-ci = cluster prod + user prod-ci + ns demo
  └─ ④ current-context   prod-ci    ←「现在连谁」由这一行决定
        │  kubectl get pods   或   kubectl --context=prod get pods

  context "prod" ─┬─ cluster prod ─► https://prod:6443 ─► apiserver
                  └─ user prod-ci ─► token / 证书 / exec 插件

别用 insecure-skip-tls-verify 蒙混过关

insecure-skip-tls-verify: true 会跳过 apiserver 证书校验,中间人可以冒充你的集群。它只适合临时排查,任何长期使用的 kubeconfig 都必须带正确的 CA。

KUBECONFIG:多文件合并与优先级

真实工作里你不会把所有集群塞进一个 ~/.kube/config——那样任何一次误操作都可能波及全局。推荐一套集群一个文件,用环境变量拼起来:

bash
mkdir -p ~/.kube/configs
cp ~/Downloads/dev-kubeconfig.yaml  ~/.kube/configs/dev.yaml
cp ~/Downloads/prod-kubeconfig.yaml ~/.kube/configs/prod.yaml
# 冒号分隔,顺序即优先级
export KUBECONFIG="$HOME/.kube/configs/dev.yaml:$HOME/.kube/configs/prod.yaml"

合并规则只有一条要记:同名键以第一个文件里的值为准。上面的顺序下,如果两份文件里都有叫 prod 的 cluster,dev.yaml 里那份会赢——这也是「连不上集群」这类怪问题的常见根源。优先级从高到低是:

  1. 命令行 --kubeconfig=/path/to/config(只读这一个文件,忽略 KUBECONFIG
  2. 环境变量 KUBECONFIG(冒号分隔,按顺序合并)
  3. 默认的 ~/.kube/config
bash
kubectl config view --minify          # 只看当前 context 用到的部分
kubectl config view --flatten         # 看多文件合并后的最终结果
kubectl config view --raw             # 未脱敏(会暴露 token 与私钥,别外传)

KUBECONFIG 写错了不会报错

如果 KUBECONFIG 指向的文件不存在,kubectl 不会提示文件缺失,只会表现为「current-context 没设置」。所以配置「像没生效」时,先 echo $KUBECONFIG 确认路径,再 kubectl config view --flatten 看内容。

上下文实操:切换、改默认命名空间、重命名

日常最高频的三个动作是切 context、改当前 context 的默认命名空间、给 context 起个看得懂的名字。

动手:把「我现在连的是谁」搞清楚

先看有哪些上下文(* 是当前使用的),再切换、设默认命名空间、改名:

bash
kubectl config get-contexts
kubectl config use-context prod
kubectl config set-context --current --namespace=demo
kubectl config rename-context prod prod-bj   # 改名不影响连接信息

再用三条命令交叉确认,避免「以为在 dev,其实在 prod」;最后试一次临时指定,不改动任何配置文件:

bash
kubectl config current-context
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
kubectl config view --minify -o jsonpath='{..namespace}{"\n"}'
kubectl --context=prod-bj -n kube-system get pods

三条输出应该互相自洽:上下文名字、apiserver 地址、默认命名空间都对得上。

只读查询建议永远显式带 --context-n,尤其是脚本里——上下文是全局状态,脚本一旦依赖它,就会在别人的机器上做出你没预期的事。再加一道人眼防线,让提示符把当前 context 显示出来:

bash
# 一行版(bash,放进 ~/.bashrc)
PS1='[$(kubectl config current-context 2>/dev/null)] \W $ '
# 更完整的选择是 kube-ps1(macOS: brew install kube-ps1;Linux 直接下载脚本)
source "$(brew --prefix)/opt/kube-ps1/share/kube-ps1.sh"
PS1='[\u@\h \W $(kube_ps1)]\$ '
KUBE_PS1_SYMBOL_ENABLE=false

一行版每次出提示符都会调一次 kubectl,配置多或网络不通时会有轻微卡顿。核心价值只有一个:prompt 里写着 prod 的时候,你会本能地多看一眼

认证方式对比:证书、token、OIDC、exec 插件

kubeconfig 的 users 段决定「你是谁」,凭证有四种常见形态。选型的核心不是哪个更先进,而是轮转难度——凭证发出去,你多久能收回。

方式kubeconfig 里的写法适用场景轮转难度
客户端证书client-certificate-data + client-key-data集群组件(kubelet、controller-manager)、运维人员长期使用难:kubeadm 默认有效期 1 年,且 Kubernetes 没有按证书吊销的机制
静态 tokentoken: <一长串>临时排查、老版本遗留的 SA 长期凭据中:换掉 Secret 或删除即可,但长期凭据容易被复制外泄
短期 tokentoken: <kubectl create token 的输出>给人和 CI 发最小权限凭证易:默认 1 小时,可 --duration 指定,过期自动失效
OIDCuser.execkubectl oidc-login get-token企业 SSO(Keycloak、Azure AD、Okta 等)易:走 IdP 登录,token 短期,员工离职即失效
exec 插件user.exec 调云厂商 CLI(如 aws eks get-token托管集群易:由云 SDK 自动刷新

OIDC 与 exec 插件在配置上是一回事,都写在 user.exec 里,由 kubectl 在每次请求前调用外部命令换 token:

yaml
users:
  - name: cloud-oidc
    user:
      exec:
        apiVersion: client.authentication.k8s.io/v1
        command: kubectl
        args: [oidc-login, get-token, --oidc-client-id=kubernetes]
        interactiveMode: IfAvailable

具体插件与参数取决于你的 IdP 与集群发行版。给「人」发凭证的长期答案是 OIDC/SSO,给「机器」发凭证的答案是短期 SA token,证书尽量留给集群组件自己用。

ServiceAccount 与 kubeconfig 的关系

ServiceAccount(SA)本来是给 Pod 用的身份,它同样可以给人和流水线用:把 kubeconfig 的 user 段填成一份 SA 短期 token,这份配置的全部权限就被 SA 绑定的 Role 限制住了。

动手:发一份只能操作 demo 命名空间的凭证

第一步,建 SA,并把内置 edit ClusterRole 绑定到 demo 命名空间(只读场景换成 view):

bash
kubectl create namespace demo
kubectl -n demo create serviceaccount ci-deploy
kubectl -n demo create rolebinding ci-deploy-edit \
  --clusterrole=edit --serviceaccount=demo:ci-deploy

第二步,签一份 24 小时 token(默认 1 小时,最短 10 分钟,上限由 apiserver 的 --service-account-max-token-expiration 决定):

bash
TOKEN=$(kubectl -n demo create token ci-deploy --duration=24h)

第三步,用三个 set-* 子命令拼出一份全新的、独立的 kubeconfig 文件:

bash
kubectl --kubeconfig=./demo-ci.kubeconfig config set-cluster prod \
  --server=https://10.0.0.100:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
kubectl --kubeconfig=./demo-ci.kubeconfig config set-credentials ci-deploy --token="$TOKEN"
kubectl --kubeconfig=./demo-ci.kubeconfig config set-context demo-ci \
  --cluster=prod --user=ci-deploy --namespace=demo
kubectl --kubeconfig=./demo-ci.kubeconfig config use-context demo-ci

/etc/kubernetes/pki/ca.crt 是 kubeadm 集群控制面节点上的默认 CA 路径;如果手头只有一份 kubeconfig,可以 kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 -d > ca.crt 取出 CA 再用它。

第四步,验证这份凭证的能力边界:

bash
KUBECONFIG=./demo-ci.kubeconfig kubectl auth can-i --list -n demo
# 应当被拒绝
KUBECONFIG=./demo-ci.kubeconfig kubectl auth can-i delete pods -n demo
KUBECONFIG=./demo-ci.kubeconfig kubectl auth can-i list nodes
# 管理员视角复核同一个身份
kubectl auth can-i --list -n demo --as=system:serviceaccount:demo:ci-deploy

can-i --list 会按资源列出允许的动作,被拒绝的条目输出 no。这份 demo-ci.kubeconfig没有你的管理员证书,只有一个 SA 的短期 token 和一份 CA——即使泄漏,攻击者也只能在 demo 里做 edit 允许的事,且 token 到期后自动失效。

为什么不要把集群 admin 证书发给同事

很多团队的默认操作是把 ~/.kube/config 复制给同事,那份配置里的身份通常叫 kubernetes-admin,绑定的是 cluster-admin

  • 权限没有边界:一条 kubectl delete namespace 就能删掉整个命名空间,甚至能改 RBAC 把自己变成永久管理员。
  • 无法按人吊销:Kubernetes 没有内置的证书吊销列表(CRL),证书签出去只能等到期或轮换整个 CA。
  • 审计失去意义:审计日志里所有操作都是 kubernetes-admin,出事时分不清是谁干的。
  • 复制成本为零:一份配置在群里传一圈,你根本不知道有多少份副本。

正确顺序是:人走 OIDC/SSO,机器走 SA 短期 token,证书留给集群组件。真需要临时给同事排查权限,用 --duration=1h 签一份,排查完让它自然过期。证书过期是同一类问题,kubeadm 集群一句话检查:

bash
sudo kubeadm certs check-expiration   # 列出各组件证书的到期时间

kubeadm 签发的客户端证书默认 1 年、CA 默认 10 年;续期与重启控制面组件的步骤取决于你的发行版与部署方式,托管集群一般不需要你操心。

多集群切换的工程化

手上有 3 套以上集群时,「切 context」本身就成了工程问题,第一步是建立目录约定:

text
~/.kube/
├── config                     # 本机默认,尽量保持最小
└── configs/
    ├── bj1-dev.yaml           # 命名:<地区机房>-<集群用途>.yaml
    ├── bj1-prod-ro.yaml       # 只读凭证单独一份,名字里写清 -ro
    └── zw1-prod.yaml
bash
export KUBECONFIG="$HOME/.kube/configs/bj1-dev.yaml:$HOME/.kube/configs/zw1-prod.yaml"
kx ctx bj1-prod     # kubie:每个 shell 独立上下文,提示符显示 [bj1-prod|default]

三条硬规矩:一集群一文件(合并顺序带来的歧义比省事更重要)、只读与可写凭证分文件(排查时用只读那份,delete 根本打不出去)、CI 用独立的最小权限 SA,token 由 secret 注入、现签现用。日常还可以给每套集群额外准备一份只读 kubeconfig(绑定内置 view ClusterRole),专供看板与临时排查。参考:reference/k8s-in-action/k8s/client.md

CI 里的典型写法是显式指定文件、不依赖全局状态,并在动手前先做权限预检:

bash
# token 由 CI 的 secret 注入环境变量,拼出只属于本次构建的配置
kubectl --kubeconfig=/tmp/ci.kubeconfig config set-cluster prod \
  --server=https://10.0.0.100:6443 --certificate-authority=/tmp/ci-ca.crt --embed-certs=true
kubectl --kubeconfig=/tmp/ci.kubeconfig config set-credentials ci-deploy --token="$KUBE_TOKEN"
kubectl --kubeconfig=/tmp/ci.kubeconfig config set-context ci \
  --cluster=prod --user=ci-deploy --namespace=demo
kubectl --kubeconfig=/tmp/ci.kubeconfig config use-context ci
# 预检:权限不对立刻失败,而不是 apply 到一半才报 403
kubectl --kubeconfig=/tmp/ci.kubeconfig auth can-i create deployment -n demo
kubectl --kubeconfig=/tmp/ci.kubeconfig apply -f deploy/

更进一步的方案是让 CI 通过云厂商的 workload identity 换取集群凭证(不需要长期 secret),是否支持取决于你的云与集群版本。部署链路的完整做法见 GitOps 持续交付:把 kubectl 直连换成 ArgoCD 之后,CI 甚至不需要持有任何集群凭证。

网络互通与数据面:先记住一句话

不同集群的 Pod 网段默认互不可达,DNS 也各自独立——不要把多套集群当成一套用。跨集群访问通常通过 Ingress/网关加显式 DNS 完成,而不是假装它们在同一个网络里;规划阶段唯一要做对的事是让各集群的 Pod/Service 网段互不重叠(和 集群部署 里的网段规划是同一件事)。真正意义上的「多集群 Service 发现」属于更高级主题,本站在规划中,具体实现取决于你的 CNI 与网关选型,本章不展开。

用 sa-management 集中管理人员凭证

给人和流水线发凭证时,最容易失控的是「SA 散落在各个业务命名空间、没人说得清谁有什么」。工程化做法是把权限主体和权限规则分开放:面向人员的 SA 统一建在一个专门的命名空间(例如 sa-management),而 Role / RoleBinding 仍然建在业务命名空间里——因为 Role 建在哪个命名空间,就只赋予那个命名空间的权限。

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bj1-harbor-developer
  namespace: sa-management
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: bj1-harbor-developer
  namespace: harbor
rules:
  - apiGroups: [""]                # core 组(APIVERSION 为 v1)用空字符串
    resources: ["pods", "services", "configmaps"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bj1-harbor-developer
  namespace: harbor
subjects:
  - kind: ServiceAccount
    name: bj1-harbor-developer
    namespace: sa-management
roleRef:
  kind: Role
  name: bj1-harbor-developer
  apiGroup: rbac.authorization.k8s.io

命名建议 <集群>-<团队或业务>-<角色>,一眼看出它给谁、给哪套集群、什么权限。两个易错点:apiGroups 对 core 组要写 "" 而不是 v1;用 kubectl api-resourcesNAMESPACED 列判断该用 Role 还是 ClusterRole——nodesstorageclassesnamespaces 这类集群级资源只能用 ClusterRole。通常还要给团队一份命名空间查看权限,否则 kubectx 这类插件列不出资源。参考:reference/k8s-in-action/k8s/sa-management/README.md

凭证轮转:谁持有、多久换、怎么吊销

发出去只是开始。给每类凭证定一个轮转节奏,比事后追查「谁还有权限」省事:

凭证类型有效期轮转动作吊销方式
短期 SA token1h(可 --duration 延长)重新 kubectl create token,旧的自然过期等过期,或删 SA / RoleBinding
长期 Secret token无期限定期重签并替换持有方删掉 Secret 后重建
客户端证书kubeadm 默认 1 年kubeadm certs renew 后重启控制面组件没有 CRL,只能等过期或轮换 CA
OIDC / SSO由 IdP 决定(通常数小时)IdP 自动刷新IdP 里禁用账号,立即生效

轮转清单要能回答四个问题:这份凭证现在在谁手里(人 / CI / 某个脚本)、权限边界是什么什么时候到期怎么在五分钟内吊销。前三项靠命名与集中管理解决,最后一项决定你能不能放心给「人」发短期 token 而不是长期证书。定期用 kubectl -n sa-management get sa 清点在用身份,再用 kubectl auth can-i --list -n harbor --as=system:serviceaccount:sa-management:bj1-harbor-developer 复核权限边界。

常见错误速查表

访问类问题的排查顺序很固定:先确认「我是谁」(认证),再确认「能不能」(授权),最后才怀疑网络。

现象原因怎么确认怎么办
error: You must be logged in to the serverkubeconfig 里没有可用凭证,或凭证已失效kubectl config view --minifyusers 段;kubectl auth whoami(1.27+ 可用)重新签 token / 重新登录,或换一份带凭证的 kubeconfig
明明想改 dev,结果动了 prod当前 context 指向了另一套集群,或 KUBECONFIG 顺序变了kubectl config current-contextkubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'切回正确 context;脚本一律显式 --context-n;提示符显示 context
401 Unauthorized,token 之前还好用短期 token 过期(默认 1 小时)重新 kubectl -n demo create token ci-deploy --duration=24h 后立刻恢复按需调长 --duration,或改用 exec 插件/OIDC 自动刷新
403 Forbidden,提示 cannot list resource "pods"SA 没有对应 Role 规则,或 RoleBinding 绑错命名空间/主体kubectl auth can-i --list -n <ns> --as=system:serviceaccount:<ns>:<sa>kubectl describe rolebinding <名字> -n <ns>补 Role 规则或修 subject;RBAC 改完立即生效,不用重签 token
改了 KUBECONFIG 却像没生效改在别的 shell、路径写错,或命令带了 --kubeconfig 覆盖echo $KUBECONFIGkubectl config view --flatten 对照 server重新 export 或写进 ~/.bashrc;注意 --kubeconfig 优先级最高
x509: certificate has expired or is not yet valid客户端证书过期,或节点时间偏差过大控制面节点上 sudo kubeadm certs check-expiration;同时看 date续期并重启控制面组件(取决于发行版);先修好时间同步

常见坑

  • 把 `~/.kube/config` 当成可以随便传的文件:里面通常是 cluster-admin,等于整个集群的钥匙。
  • 在脚本里依赖当前 context:上下文是全局可变状态,脚本必须显式 --context--kubeconfig
  • 长期使用静态 token:能不用就不用,短期 token 按需签发才是默认姿势。
  • `kubectl config view --raw` 随手贴出去:它会打印明文 token 与私钥。
  • 集群重建后忘了清旧 contextserver 地址已失效,报错却是「连不上」,容易误判成网络问题。
  • 多文件下的写操作use-contextrename-context 在多个 kubeconfig 同时生效时,改哪个文件取决于条目所在位置,行为容易出人意料,重要变更前先备份目录。

自测题

自测:为什么 context 里要同时引用 cluster 和 user?(点击展开答案)

因为「去哪」和「我是谁」是两个完全独立的维度,分开才能自由组合:同一个 prod 集群可以有「我的 OIDC 身份」「CI 的 SA token」「只读排查账号」多个 context,同一个身份也能指向 dev 和 prod 两套集群。如果 kubeconfig 把集群地址和凭证写死在一起,你就得为每种身份复制一份集群配置,改一次地址要改 N 处。current-context 只是记住你上次选了哪个组合。

自测:为什么发 SA token kubeconfig 比复制 admin 证书更安全?(点击展开答案)

四个理由各自独立成立。权限有边界:SA 只通过 RoleBinding 拿到某个命名空间里的权限,动不了集群级资源。有效期短:token 默认 1 小时,即使泄漏攻击窗口也很小。可撤销:删掉 SA 或 RoleBinding 后 token 立刻失效,而客户端证书没有吊销机制,签出去只能等到期或轮换 CA。可审计:审计日志里的身份是 system:serviceaccount:demo:ci-deploy,而不是所有操作都记成同一个 kubernetes-admin。证书唯一的优势是「不需要每次换取」,所以它更适合集群组件这种长期、固定的场景。

自测:为什么 CI 里不该用个人的 kubeconfig?(点击展开答案)

首先权限过大:个人配置往往是集群管理员,流水线被注入恶意代码就等于把整个集群交出去。其次它与人绑定:这个人换岗位、改密码、离职,流水线就断了,而且凭证无法按流水线粒度吊销。还有两个容易忽略的点:个人凭证无法审计到「是哪次构建做的变更」;kubeconfig 还经常被缓存进构建缓存或写进日志,泄漏面比想象中大。正确做法是每套集群一个专用 SA、最小权限、短时 token,并在流水线第一步用 kubectl auth can-i 做权限预检。

小结

  • 多集群不是目标,隔离级别才是;它换来硬隔离,也带来配置漂移、凭证翻倍、观测割裂和网络不通。
  • kubeconfig 分四段:clusters 回答「去哪」、users 回答「我是谁」、contexts 把两者绑起来再加默认命名空间、current-context 决定现在用哪个。
  • KUBECONFIG 用冒号分隔多个文件,同名键以第一个文件为准;优先级是 --kubeconfig > KUBECONFIG > ~/.kube/config
  • 切集群前先 kubectl config current-contextkubectl config view --minify,脚本里一律显式 --context-n,提示符显示 context 是一道廉价防线。
  • 人用 OIDC/SSO,机器用短期 SA token,证书留给集群组件;永远不要把 admin kubeconfig 发给同事

练习

  1. 在本地造两份 kubeconfig 文件,让它们包含同名的 cluster 但不同的 server,分别用 KUBECONFIG=a.yaml:b.yamlKUBECONFIG=b.yaml:a.yaml 执行 kubectl config view --flatten,验证「第一个文件优先」。
  2. demo 命名空间再建一个只读 SA(绑定内置 view ClusterRole),签一份 1 小时 token 拼成 kubeconfig,用 kubectl auth can-i --list -n demo 对比它和本章 ci-deploy 的权限差异。
  3. 想一下你手上的流水线:它现在用的是谁的凭证?要改成「专用 SA + 短时 token + 权限预检」,需要动哪几个地方?

本章解决的是「怎么安全地连上多套集群」。凭证之外,集群本身还有一堆需要按机器去调的东西——节点内核参数、DNS 缓存、设备发现,继续看下一章;权限规则写不明白就回看第 12 章 命名空间与 RBAC安全加固,凭证泄漏后的处置思路在排障手册