Kubernetes 认证和授权

学习参考:API 访问控制

环境准备

 [root@master30 ~ 09:12:57]# kubectl create ns auth
 namespace/auth created
 [root@master30 ~ 09:29:45]# kubectl config set-context --current --namespace auth
 Context "cluster1-context" modified.
 ​

Kubernetes API 访问控制

学习参考:Kubernetes API 访问控制

当用户使用User服务账号访问Kubernetes API时,每个请求都会经过多阶段的访问控制之后才会被接受,包括身份认证、鉴权以及准入控制(Admission Control)。

如下图所示:

所有对集群的操作(敲 kubectl 命令、Pod 里的程序调用集群、外部管理工具)都必须经过 kube-apiserver。访问控制分三步,按顺序执行,一步过不去就直接拒绝,走不到下一步。

第一步:身份认证(验证你是谁)
作用

验证请求发起者的身份合法性,确认 “你是谁”。认证不通过直接返回 401 Unauthorized,认证通过后才会进入下一环节。

常用的认证方式
  1. 客户端证书认证 管理员用 kubectl 操作集群,默认就是这种方式。靠证书文件证明身份,API 服务器用集群根证书校验证书是否有效,从证书里读取用户名和用户组。

  2. ServiceAccount 令牌认证 专门给 Pod 里的程序用。每个命名空间都有默认的服务账号,Pod 启动时会自动把对应的令牌挂载到容器里,程序带这个令牌就能访问 API 服务器。

  3. Bearer Token 认证 请求头里带上一段 token 字符串来证明身份,多用于测试、节点接入或者第三方工具对接。

补充

Kubernetes 本身不维护用户账号表,所有身份都靠这些外部凭证来识别。

第二步:鉴权(验证你能不能做这件事)
作用

身份确认后,判断该身份是否有权限执行当前请求的操作(比如创建 Pod、删除 Deployment、查看 Secret)。无权限直接返回 403 Forbidden。

默认授权模式:RBAC

RBAC 是 Kubernetes 默认启用的标准授权模式,核心是角色定义权限、绑定关联身份,通过 4 个核心对象实现:

对象作用范围核心功能
Role单个命名空间定义该命名空间内的权限规则(可对哪些资源做哪些操作)
ClusterRole整个集群定义集群级权限规则(节点、全集群命名空间资源等)
RoleBinding单个命名空间将 Role 绑定到用户 / 用户组 / ServiceAccount,在指定命名空间生效
ClusterRoleBinding整个集群将 ClusterRole 绑定到身份主体,全集群范围内生效

最简逻辑示例: 定义一个 Role:允许在 default 命名空间查看 Pod 列表 创建一个 RoleBinding:把这个 Role 绑定给指定用户 最终效果:该用户只能在 default 命名空间执行 kubectl get pod,其他操作 / 其他命名空间均无权限

第三步:准入控制(验证操作内容合不合规)
作用

授权通过后、资源真正写入 etcd 之前的最后一道关卡,可以对请求的资源对象做修改或校验,不符合规则直接拒绝请求。 和前两层不同:准入控制不关心 “你是谁”,只关心 “你要创建 / 修改的内容合不合规”。

分两类
  1. 变更型准入 自动修改你提交的资源内容,补充默认配置。 比如自动给 Pod 补上默认的服务账号、自动给存储声明补上默认存储类、服务网格自动给 Pod 注入边车容器。

  2. 校验型准入 只做检查,不修改内容,不符合规则就驳回。 比如检查命名空间的总资源有没有超配额、检查 Pod 的安全配置是否符合要求、检查 Pod 申请的资源是否在允许的范围内。

补充

除了内置的检查规则,还可以通过准入 Webhook 部署自己写的程序,自定义业务检查规则。

完整流程总结

完整请求流转总结 1.请求到达 API Server,完成 TLS 握手,进入认证环节 2.认证模块识别出请求者的合法身份 3.授权模块根据身份和请求内容,校验操作权限 4.依次经过所有变更型准入控制器,修改资源对象 5.依次经过所有校验型准入控制器,验证资源合规性 6.全部校验通过,资源数据写入 etcd,API Server 返回成功响应

常见报错对应环节
  • 401 Unauthorized:认证失败,身份凭证无效或者没带凭证

  • 403 Forbidden:认证成功,但当前身份没有对应操作的权限

  • 创建 / 修改资源被拒,提示配额、安全相关内容:准入控制校验未通过

Kubernetes 审计(直白无比喻讲解)

更多信息请参考 审计

1. 审计是什么

kube-apiserver 会记录所有访问集群 API 的操作日志,这套完整记录机制就是审计。 所有操作按发生时间先后保存,形成完整操作流水记录。

2. 哪些行为会被记录

三类主体发起的 API 请求全部留存记录:

  1. 运维人员:kubectl、页面控制台、外部工具操作集群

  2. 集群内程序:Pod 里应用、metrics-server、控制器等调用 API

  3. 集群控制平面组件:kubelet、调度器、控制器管理器内部操作 API

3. 每条审计日志包含的核心信息

  • 操作发起者身份(用户 / 服务账号)

  • 执行动作:增、删、改、查、转发等

  • 操作资源类型:Pod、Deployment、Node、Secret 等

  • 操作对象名称、所属命名空间

  • 请求发起 IP、操作耗时、操作结果(成功 / 失败)

  • 修改前后资源内容(可选配置开启)

  • 操作发生时间

4. 审计的作用

  1. 安全追溯:出现误删、泄露 Secret、非法操作时,查到是谁、什么时候执行

  2. 故障排查:集群资源异常变更,定位触发操作来源

  3. 合规要求:企业等环境需要留存操作日志,满足安全核查

  4. 权限校验复盘:查看哪些账号频繁访问敏感资源

5. 补充关键点

  1. 审计只记录API 请求,不记录容器内部业务日志、节点系统日志;

  2. 可自定义审计策略:控制哪些操作记录、记录详细程度、日志保存位置(文件、后端服务);

  3. 审计独立于前面的认证、授权、准入控制:无论操作成功还是失败,只要发到 apiserver 的请求都会被记录。

Kubernetes认证管理

学习参考:认证

一、K8s 两类用户(核心区分)

1. 普通用户

K8s 本身不创建、不管理普通用户,没有对应的集群资源对象,也无法通过 K8s API 新增普通用户。

普通用户的身份依靠集群 CA 签名的合法证书认证,系统读取证书里的 CN(通用名称)字段作为用户名。认证通过后,再由 RBAC 权限体系判定该用户的操作权限。

适用场景:运维人员、外部人员操作集群。

2. 服务账号(ServiceAccount)

服务账号是K8s API 原生管理的用户对象,属于集群内部用户。

服务账号绑定固定命名空间,可由系统自动创建,也可手动通过 API 创建。每个服务账号对应一个 Secret 凭据,令牌会自动挂载到对应 Pod 中,供 Pod 内程序访问 K8s API 使用。

适用场景:集群内部 Pod、组件调用集群 API。

3. 匿名用户

所有没有携带合法认证信息、或认证失败未被拦截的 API 请求,都会被系统判定为匿名请求。

匿名用户固定身份:用户名 system:anonymous,用户组 system:unauthenticated。K8s 1.6 及以上版本默认开启匿名访问,需通过 RBAC 单独限制匿名权限。

二、身份认证核心规则

所有访问 K8s API 的请求,必须完成身份认证,每个请求都会绑定一个身份:普通用户 / 服务账号 / 匿名用户。

K8s 通过认证插件校验请求身份,认证成功后,会给请求绑定四类核心信息,供后续授权使用:

  • 用户名:标识操作者的名称

  • 用户ID:唯一、固定的用户标识,比用户名更稳定

  • 用户组:用户所属的逻辑分组,用于批量授权

  • 附加字段:自定义额外鉴权信息

集群支持同时开启多种认证方式,任意一种认证通过即判定身份合法;所有认证方式均失败,直接返回 401 认证失败。

K8s 默认启用两种认证:服务账号令牌认证、X509 客户端证书认证。

三、常用认证插件(官方原生)

1. X509 客户端证书认证(默认启用)

运维人员通过 kubectl、客户端工具操作集群时的核心认证方式,kubeconfig 文件的认证逻辑就是该方式。

API Server 通过启动参数 --client-ca-file 指定集群 CA 证书,用于校验客户端证书的合法性,合法证书即可完成身份认证。

2. 服务账号令牌认证(默认启用)

专为集群内部 Pod 设计的认证方式,永久自动启用。

系统自动为服务账号生成签名令牌,挂载到 Pod 内部,Pod 调用 API 时携带该令牌即可完成认证;也可手动通过 Pod 配置的 serviceAccountName 指定绑定的服务账号。

3. 启动引导令牌认证(Bootstrap Token)

主要用于集群初始化、新节点加入集群场景。

令牌以 Secret 形式存储在 kube-system 命名空间,支持动态创建和管理。需要在 API Server 开启启动参数 --enable-bootstrap-token-auth=true,kubeadm 部署的集群默认开启。

4. 静态令牌文件认证(默认未启用)

通过 API Server 启动参数 --token-auth-file 指定 CSV 格式令牌文件,文件内记录令牌、用户名、用户ID、用户组信息。

属于静态认证方式,修改后需重启 APIServer,生产极少使用。

四、整体工作流程

  1. 客户端发起 API 请求,携带证书、令牌等认证信息;

  2. APIServer 调用已启用的认证插件依次校验;

  3. 任意插件认证通过,绑定用户身份信息,进入后续授权环节;

  4. 全部插件认证失败,返回 401 拒绝请求;

  5. 无任何认证信息,判定为匿名用户。

认证插件

认证插件通用规则(直白原话翻译)
  1. apiserver 能同时开多种认证插件,客户端只要满足任意一种插件校验就算认证成功。

  2. 认证通过:提取出用户名、用户组等信息,传给授权模块判断有没有操作权限。

  3. 所有插件全部校验失败:接口返回 401 未授权。

常用认证插件:

  • X509 客户证书

    • 客户端用户与Kubernetes交互时候,使用的认证凭据文件.kube/config就是使用X509证书。

    • API Server启动时配置 --client-ca-file=SOMEFILE 参数。

       [root@master30 ~ 10:32:13]# cat /etc/kubernetes/manifests/kube-apiserver.yaml  | grep --  --client-ca-file
           - --client-ca-file=/etc/kubernetes/pki/ca.crt
       ​
  • 静态令牌文件

    • API Server启动时配置 --token-auth-file=SOMEFILE 参数。

       root@master30:~# cat /etc/kubernetes/manifests/kube-apiserver.yaml |\grep -- --token-auth-file
    • 文件为 csv格式,每行至少包括三列 token,username,user id。第四列为可选group 名项。如果有多个group名,列必须用””双引号包含其中,例如:

       token,user,uid,"group1,group2,group3"
    • 默认未启用。

  • 启动引导令牌

    • 为了支持平滑地启动引导新的集群,Kubernetes 包含了一种动态管理的持有者令牌类型, 称作 启动引导令牌(Bootstrap Token)。 这些令牌以 Secret 的形式保存在 kube-system 名字空间中,可以被动态管理和创建。 使用 kubeadm 引导和管理集群时,kubeadm 会自动完成这些设置。

    • 你必须在 API 服务器上设置 --enable-bootstrap-token-auth 标志来启用基于启动引导令牌的身份认证组件。

       [root@master30 ~ 10:33:37]# cat /etc/kubernetes/manifests/kube-apiserver.yaml  | grep bootstrap
           - --enable-bootstrap-token-auth=true
       ​
    • 请参阅启动引导令牌, 以了解关于启动引导令牌身份认证组件详细信息。

  • 服务账号令牌

    • 服务账号(Service Account)是一种自动被启用的用户认证机制,使用经过签名的持有者令牌来验证请求。

    • 服务账号通常由 API 服务器自动创建并通过 ServiceAccount 准入控制器关联到集群中运行的 Pod 上。 持有者令牌会挂载到 Pod 中可预知的位置,允许集群内进程与 API 服务器通信。

    • 服务账号也可以使用 Pod 规约的 serviceAccountName 字段显式地关联到 Pod 上。

  • Webhook 令牌身份认证

    Webhook 身份认证是一种用来验证持有者令牌的回调机制。

  • 身份认证代理

    API 服务器可以配置成从请求的头部字段值(如 X-Remote-User)中辩识用户。 这一设计是用来与某身份认证代理一起使用 API 服务器,代理负责设置请求的头部字段值。

  • basic-auth-file认证

    在kubernetes 1.19及之后的版本中,kubernetes放弃了 basic-auth-file 认证方式。

匿名请求

  1. 定义:请求没带任何合法证书 / 令牌,所有认证插件都没匹配上,就判定为匿名访问。

  2. 匿名固定身份:用户名 system:anonymous,用户组 system:unauthenticated。

  3. 版本默认开关:

    1. 1.5.x:匿名默认关闭,需手动加 --anonymous-auth=true 开启

    2. 1.6+:RBAC/ABAC 授权模式下匿名默认开启

  4. 权限规则: 匿名用户不会自动继承集群通用权限,必须单独给 system:anonymous 或者 system:unauthenticated 绑定权限才能操作集群。

  5. 区分两种场景:

    1. 带了令牌但令牌错误 → 全部插件校验失败 → 返回 401

    2. 完全没带任何令牌证书 → 直接识别为匿名用户,不返回 401,进入授权环节判断匿名有没有权限

创建账户

以下探讨使用 X509客户证书 插件管理用户。

整体流程直白拆解:给外部客户端创建 X509 证书,生成 kubeconfig,让普通用户访问 K8s 集群 整套流程分 6 大块:1.客户端环境准备、2.客户端生成证书请求、3.管理员签发证书、4.制作 kubeconfig、5.给用户分配权限、6.回收用户权限

客户端准备

客户端要想访问集群,必须安装与集群版本一致的kubectl工具。

 [root@client ~ 11:10:02]# apt install -y kubectl=1.30.2-1.1

准备申请材料

 # 创建私钥
 [root@client ~ 11:10:23]# openssl genrsa -out zy.key 2048
 ​
 # 根据私钥,创建请求证书
 [root@client ~ 11:10:36]# openssl req -new -key zy.key -out zy.csr -subj '/CN=zy/O=kubernetes'
 [root@client ~ 11:10:41]# ls
 zy.csr  zy.key
 ​
 # 参数说明:
 ## C,Country,代表国家
 ## ST,STate,代表省份
 ## L,Location,代表城市
 ## O,Organization,代表组织,公司
 ## OU,Organization Unit,代表部门
 ## CN,Common Name,代表服务器域名
 ## emailAddress,代表联系人邮箱地址。
 ​
 ​
 ​
 # 其他示例:
 root@client:~# openssl req -new -key servera.key -out servera.csr -subj "/C=CHINA/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=servera.lab.example.com/emailAddress=laoma@lab.example.com"
 ​
 # 客户端将自己请求证书发给kubernetes管理员
 [root@client ~ 11:11:01]# scp zy.csr root@master30:
 Warning: Permanently added 'master30' (ED25519) to the list of known hosts.
 zy.csr                                                     100%  907     1.1MB/s   00:00  

创建用户凭据

管理员使用以下资源文件创建用户的kubeconfig。

 # 使用ca.crt和ca.key签名zy.csr,得到zy.crt证书
 [root@master30 ~ 10:42:49]# openssl x509 -req -in zy.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out zy.crt -days 1095
 Certificate request self-signature ok
 subject=CN = zy, O = kubernets
 ​
 # 导出kubeconfig模版
 root@master30:~# kubectl config view > config.tpl
 ​
 #配置域名解析:
 [root@master30 ~ 11:22:53]# vim /etc/hosts
 行尾添加:10.1.8.33 client
 ​
 # 将kubeconfig模板、zy.crt和kubernetes的ca证书发给客户端
 [root@master30 ~ 11:24:20]# scp config.tpl zy.crt /etc/kubernetes/pki/ca.crt root@client:~
 Warning: Permanently added 'client' (ED25519) to the list of known hosts.
 config.tpl                                   100%  745   794.1KB/s   00:00    
 zy.crt                                       100% 1009     1.5MB/s   00:00    
 ca.crt                                       100% 1107     2.0MB/s   00:00    
 ​

创建 kubeconfig

kubeconfig创建方法:

方法一:使用kubectl config命令创建。

修改模版config.tpl,结果如下:

 [root@client ~ 14:53:18]#vim config.tpl
 apiVersion: v1
 clusters:
 - cluster:
     server: https://10.1.8.30:6443
   name: kubernetes
 contexts:
 - context:
     cluster: kubernetes
     namespace: default
     user: zy
   name: zy@kubernetes
 current-context: zy@kubernetes
 kind: Config
 users:
 - name: zy
 # 设置 cluster
 [root@client ~ 11:25:48]# mv config.tpl  config         #改名字的意思
 ​
 [root@client ~ 11:26:23]# kubectl config set-cluster kubernetes --kubeconfig=config --certificate-authority=ca.crt --embed-certs 
 Cluster "kubernetes" set.
 ​
 # --kubeconfig指定kubeconfig文件
 # --server指定kubernetes服务器认证地址
 # --certificate-authority选项指定ca证书
 # --embed-certs选项作用是将ca.crt的内容添加到config文件中,
 # 如果没有该选项,则添加 --certificate-authority 选项指定的路径,也就是ca.crt
 ​
 # 设置credentials
 [root@client ~ 11:28:29]# kubectl config set-credentials zy --kubeconfig=config --client-key=zy.key --client-certificate=zy.crt --embed-certs
 User "zy" set.
 ​
 # --client-key 指定用户私钥
 # --client-certificate 指定服务器为用户生成的证书
 ​
 # 设置context
 [root@client ~ 11:28:54]# kubectl config set-context zy --kubeconfig=config --namespace=default --cluster=kubernetes --user=zy
 Context "zy" created.
 ​
 # --namespace指定Namespace
 # --cluster指定集群
 # --user指定用户
 ​
 ​
 # 授权用户zy集群管理员角色,后续详细讲解角色管理
 root@master30:~# kubectl create clusterrolebinding zy-admin --clusterrole=cluster-admin --user=zy
 ​
 # 验证结果
 [root@client ~ 14:53:22]# kubectl get nodes --kubeconfig=config 
 NAME                STATUS   ROLES           AGE   VERSION
 master30.zy.cloud   Ready    control-plane   10d   v1.30.2
 worker31.zy.cloud   Ready    <none>          10d   v1.30.2
 worker32.zy.cloud   Ready    <none>          10d   v1.30.2
 #可以直接把config文件移动到kubectl 默认读取的路径./kube下面,后面就不用加--kubeconfig=config 参数了:
 [root@client ~ 15:23:19]# ls
 ca.crt  config  zy.crt  zy.csr  zy.key
 [root@client ~ 15:23:22]# mv config  .kube/
 [root@client ~ 15:23:32]# kubectl  get  nodes 
 NAME                STATUS   ROLES           AGE     VERSION
 master30.zy.cloud   Ready    control-plane   4d18h   v1.30.2
 worker31.zy.cloud   Ready    <none>          4d18h   v1.30.2
 worker32.zy.cloud   Ready    <none>          4d18h   v1.30.2
 ​

删除账户

 # 通过删除证书进行删除账户即可,为了后续操作方便,该账户不删除
 ​
 # k8s删除用户csr资源后,客户端用户仍可以访问集群。
 # 解释:用户认证功能由x509提供,与k8s无关。
 # 如果不予许用户登录,应该从x509认证机制方面下手,例如ca.crt将相应客户端csr加入黑名单。
 ​
 # 删除权限
 root@master30:~# kubectl delete clusterrolebindings.rbac.authorization.k8s.io zy-admin
 ​
 # 验证权限
 [root@client ~ 14:55:28]# kubectl get nodes 
 Error from server (Forbidden): nodes is forbidden: User "zy" cannot list resource "nodes" in API group "" at the cluster scope
 ​
 Kubernetes外部用户证书认证实验说明
 一、实验用途(实际工作里干嘛用)
 1. 给外部人员开通集群访问权限
 企业里运维、开发人员不在 master 节点操作,每个人自有办公机器,需要单独颁发证书,凭 kubeconfig 远程连集群,不用登录 master 主机。
 2. 权限精细化管控
 证书只证明身份(你是谁),再通过 RBAC 给不同人分配不同权限:开发只能看自己业务 Pod,管理员拥有全集群权限。
 3. 安全隔离
 - 私钥保存在用户本地,集群只存公钥证书;
 - 不用共享 master 管理员的 kubeconfig,避免超级权限泄露;
 - 人员离职可直接解绑权限绑定,快速回收集群操作权限。
 4. 理解 K8s 认证底层原理
 不用 kubeadm 自动生成配置,手动走完 openssl 证书签发、kubeconfig 组装,吃透 X509 证书认证整套逻辑。
 ​
 ​
 二、实验意义(学到的核心知识点)
 1. 弄懂 K8s 普通用户不靠集群内部存储,依靠 X509 证书 CN 字段识别用户名
 K8s 没有用户数据库,合法 CA 签名的证书就代表合法用户,这是集群外部用户标准认证方式。
 2. 分清认证与授权两件完全独立的事
 - 认证(证书):判断你是谁,证书有效就能通过;
 - 授权(RBAC 绑定):判断你能不能操作资源,没有绑定权限就算证书合法也会 403 禁止访问。
 3. 理解 kubeconfig 配置文件核心作用
 kubeconfig 是 kubectl 访问 apiserver 的凭证文件,包含集群地址、根证书、个人证书私钥,三种信息缺一不可。
 4. 掌握用户权限回收的正确方式
 只删除证书记录没用,证书只要 CA 签名过就永久有效;临时限制删除 RBAC 绑定,永久封禁需要证书吊销。
 5. 区分两类客户端场景
 可以独立虚拟机远程访问,也可本机新建系统用户模拟客户端,真实生产统一使用独立客户端机器管理集群。
 ​
 ​
 三、实验最终说明的结论
 1. Kubernetes 外部普通用户采用 X509 证书认证,身份由证书 CN 标识;
 2. 访问集群必须具备 kubectl 工具 + 合法 kubeconfig 凭证;
 3. 访问集群分两道校验:证书认证、RBAC 授权,两道关卡全部通过才能操作资源;
 4. 用户权限管理不依赖删除证书,通过 ClusterRoleBinding 绑定 / 解绑实现权限控制;
 5. 整套证书签发流程是企业运维开通外部人员集群权限的标准落地流程。
 ​

授权管理

学习参考:鉴权使用 RBAC 鉴权

鉴权概述

Kubernetes API 服务器对 API 请求进行鉴权。 它根据所有策略评估所有请求属性来决定允许或拒绝请求。 一个 API 请求的所有部分都必须被某些策略允许才能继续。 这意味着默认情况下拒绝权限。

当系统配置了多个鉴权模块时,Kubernetes 将按顺序使用每个模块。

  • 如果任何鉴权模块批准或拒绝请求,则立即返回该决定,并且不会与其他鉴权模块协商。

  • 如果所有模块对请求没有意见,则拒绝该请求。 被拒绝响应返回 HTTP 状态代码 403。

鉴权模式

授权(Authorization):认证已经确认你是谁,授权决定你能干什么,apiserver 通过 --authorization-mode 指定启用哪些鉴权方式,支持多模式逗号分隔依次校验。

 [root@master30 ~ 14:56:04]# cat /etc/kubernetes/manifests/kube-apiserver.yaml  | grep mode
     - --authorization-mode=Node,RBAC

这里使用RBACNode模式。

支持的模式:

1. Node 节点鉴权模式
含义

专门给 kubelet 程序用的授权方案。 kubelet 需要和 apiserver 交互(上报节点状态、拉取 Pod、挂载镜像、读写 secret/configmap),Node 鉴权会自动根据本机正在运行的 Pod,给 kubelet 分配对应资源的读写权限。

特点
  • 只针对节点组件 kubelet,普通用户不生效;

  • 自动授权,不需要手动创建 Role/RoleBinding;

  • 生产集群必开。

2. ABAC 基于属性访问控制
含义

把「用户、资源、操作、环境」各类属性写成静态 JSON 策略文件,apiserver 读取文件判断是否允许操作。 属性可以是:用户名、命名空间、资源类型、动作(get/list/create)等,组合匹配就放行。

缺点(基本淘汰)
  1. 策略是本地静态文件,改权限必须改文件 + 重启 apiserver;

  2. 不支持 API 动态管理,不能 kubectl 创建策略;

  3. 无法精细化区分集群 / 命名空间权限;

使用现状

早期 K8s 版本遗留方案,现在几乎全部改用 RBAC。

3. RBAC 基于角色访问控制(主流、重点)
原文拆解

启用后会启用 rbac.authorization.k8s.io API 组,管理员可以通过 kubectl 动态创建、修改、删除权限策略,不用重启 apiserver。 开启参数:--authorization-mode=RBAC

通俗原理

两层绑定:

  1. Role/ClusterRole:定义一组权限(能查节点、能创建 Pod、能删 Deployment 等);

  2. RoleBinding/ClusterRoleBinding:把角色绑定给用户、服务账号、组;

优势
  • 动态在线管理权限,实时生效;

  • 权限分层:集群级 (ClusterRole)、命名空间级 (Role);

  • 企业标准方案,你刚才创建 clusterrolebinding zy-admin 就是 RBAC 操作。

4. Webhook 回调鉴权
含义

apiserver 收到请求后,不自己判断权限,发一条 HTTP POST 请求到外部独立鉴权服务(Webhook 服务),由外部服务返回「允许 / 拒绝」。

适用场景

集群权限对接公司内部统一账号系统、自研权限平台、第三方身份管理系统,实现统一权限管控。

流程

用户请求 apiserver → apiserver POST 身份 + 操作信息给外部 webhook 服务 → 服务返回鉴权结果 → apiserver 放行 / 拦截。

5. AlwaysAllow 全部放行模式
含义

所有 API 请求全部无条件允许,不做任何权限校验,任何人拥有集群最高管理员权限。

适用场1景

仅本地单机测试、学习环境;绝对禁止生产使用

风险

任意用户、任意程序可以增删改集群所有资源,无安全隔离,极易泄露、销毁业务负载。

6.快速区分记忆
  1. Node:专门给 kubelet 节点代理用

  2. ABAC:静态文件老方案,淘汰

  3. RBAC:企业标准,动态管理用户权限(实验用的就是它)

  4. Webhook:对接外部自研权限系统

  5. AlwaysAllow:无权限限制,仅测试用

    6.AlwaysDeny,拒绝用户所有请求,不管用户是否具有权限,但不限制admin用户。

role 管理

kubernetes 方便管理权限,将一组特定权限赋予角色,然后将角色赋予用户,那么用户将继承该角色具有的权限。

K8s 权限管理遵循 「角色解耦」 逻辑,分两步:

  1. 角色(Role/ClusterRole):提前打包一堆权限(能操作哪些资源、能执行什么动作);

  2. 绑定(RoleBinding/ClusterRoleBinding):把做好的角色分配给用户 / 组 / 服务账号; 用户拿到绑定后,自动继承角色里全部权限。

两种角色区分
  1. Role(命名空间角色)

    1. 作用范围:仅限单个 namespace,不能跨命名空间;

    2. 绑定工具:RoleBinding,同样受 namespace 限制;

    3. 举例:default 命名空间的 Pod 查看权限,kube-system 里用不了。

  2. ClusterRole(集群角色)

    1. 作用范围:整个集群所有 namespace,甚至集群级资源(节点、存储类等);

    2. 绑定工具:ClusterRoleBinding

    3. 内置集群角色:admincluster-admineditview,系统自带不用手动创建。

 [root@master30 ~ 15:03:55]# kubectl  describe  clusterroles admin 
 Name:         admin
 Labels:       kubernetes.io/bootstrapping=rbac-defaults
 Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
 PolicyRule:
   Resources                                       Non-Resource URLs  Resource Names  Verbs
   ---------                                       -----------------  --------------  -----
   rolebindings.rbac.authorization.k8s.io          []                 []              [create delete deletecollection get list patch update watch]
   roles.rbac.authorization.k8s.io                 []                 []              [create delete deletecollection get list patch update watch]
   configmaps                                      []                 []              [create delete deletecollection patch update get list watch]
   endpoints                                       []                 []              [create delete deletecollection patch update get list watch]
 ......

输出说明:

  • Resources:代表系统中资源类型,例如Secret,Configmap等。

  • Resource Names:代表特定资源。如果Resources是Secret,那么这里就指特定Secret。

  • Non-Resource URLs: 被称为非资源URL或虚拟URL对象,是k8s中所需要的特殊动作(不需要关注)。

  • Verbs:代表针对资源执行的动作,包括操作get、list、create、delete、update、edit、watch、exec。

    • get,用于获得特定资源信息,我明确知道我要查哪个 Pod,精准点名查一个例如,

    • 针对pod,可以执行:GET /api/v1/ns/xxx/pods/【具体pod名字】

    • list,查全部资源列表,我不指定名字,我要系统把所有 Pod 全部列出来

    • 例如针对pod,可以执行GET /api/v1/namespaces/{namespace}/pods

 #get用法示例
 root@client:~# kubectl get pod -n kube-system 
 Error from server (Forbidden): pods is forbidden: User "laoma" cannot list resource "pods" in API group "" in the namespace "kube-system"
 ​
 root@client:~# kubectl get pod kube-proxy-75d9b -n kube-system 
 NAME               READY   STATUS    RESTARTS   AGE
 kube-proxy-8kp8w   1/1     Running   4          52d

 #教程文档里举的反例环境:这个教程里是重新新建了另一个 Role、重新绑定,权限反过来写的:
 #get、list 是两个独立开关,管理员在 master 创建 Role 时只写其中一个,就会出现一条命令成功、一条报错。
 #要想让两条命令都正常执行?
 #创建 Role 的时候,两个 verbs 同时写上:
 #rules:
 #- apiGroups: [""]
   #resources: ["pods"]
   #verbs:
   #- get
   #- list
   
   
 #list用法示例  
 root@client:~# kubectl get pod -n kube-system 
 NAME                                        READY   STATUS    RESTARTS   AGE
 calico-kube-controllers-6dfcd885bf-lq4n5    1/1     Running   4          52d
 calico-node-44cf4                           1/1     Running   4          52d
 calico-node-48sm4                           1/1     Running   4          52d
 .....
     
 root@client:~# kubectl get pod kube-proxy-8kp8w -n kube-system 
  Error from server (Forbidden): pods "kube-proxy-8kp8w" is forbidden: User "laoma" cannot get resource "pods" in API group "" in the namespace "kube-system"
1. 两条命令分别要什么权限
kubectl get pod -n kube-system

动作是 list(列出该命名空间全部 Pod) 权限要求:角色规则里必须写 verbs: [list] 你当前 laoma没有 list 权限 → 直接报 403 Forbidden

kubectl get pod kube-proxy-8kp8w -n kube-system

动作是 get(只查询指定名字的单个 Pod) 权限要求:角色规则里必须写 verbs: [get] 你当前 laoma拥有 get 权限 → 正常输出不报错

创建 role

kubectl create role = 创建一个命名空间内的权限包(岗位) 作用:规定在某个 namespace 里,用户能对哪些资源做哪些操作。

 [root@master30 ~ 11:42:20]# kubectl  create role --help 
 Create a role with single rule.
 ​
 ​
 --------------------------------------------------------------------------------------
 ​
 Usage:
   kubectl create role NAME --verb=verb --resource=resource.group/subresource
 [--resource-name=resourcename] [--dry-run=server|client|none] [options]
 ​
 #参数讲解:
 kubectl create role NAME --verb=动作 --resource=资源 -n 命名空间
 1.NAME:自定义角色名字,比如 pod-role
 2.--verb:操作动作(get/list/create/delete 等,多个用逗号隔开)
 3.--resource:管控的资源类型(pods、deployments、replicasets)
 4.--resource-name:可选,只管控某一个指定名字的资源,不写就是管控该类型全部资源
 5.--dry-run=client -o yaml:只输出 yaml 配置文件,不真实创建,用来预览模板,调试专用

示例1:创建角色,允许查看 default 下所有 Pod,可以对项目中所有pods执行get、list、watch操作

 #先预览 yaml,不创建(dry-run 干跑)
 [root@master30 ~ 11:42:45]# kubectl  create  role pod-role  --verb=get,list,watch --resource=pods -n default --dry-run=client -o yaml
 apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   creationTimestamp: null
   name: pod-role
   namespace: default
 rules:
 - apiGroups:
   - ""
   resources:
   - pods
   verbs:
   - get
   - list
   - watch
 ​
 #解释:
 apiVersion: rbac.authorization.k8s.io/v1  # 权限API版本固定
 kind: Role                               # 类型:命名空间内角色
 metadata:
   name: pod-role                         # 角色名字
   namespace: default                     # 权限只在default命名空间生效,别的ns无效
 rules:                                   # 权限规则
 - apiGroups: [""]                        # pods属于v1空分组基础资源
   resources: ["pods"]                    # 管控pod资源
   verbs: [get,list,watch]                # 允许3个动作
   
   
 3 个动作含义:
 get:查单个 Pod 详情
 list:列出全部 Pod 清单
 watch:实时监控 Pod 变化(kubectl get pod -w)
 #真实创建这个角色(去掉 dry-run)
 [root@master30 ~ 11:44:27]# kubectl  create  role pod-role  --verb=get,list,watch --resource=pods -n default 
 role.rbac.authorization.k8s.io/pod-role created
 ​
 #简单查看有哪些 role,只会显示角色名和创建时间。
 [root@master30 ~ 11:49:08]# kubectl  get roles pod-role -n default 
 NAME       CREATED AT
 pod-role   2026-07-10T03:49:08Z
 ​
 #详细查看权限规则(describe),输出 PolicyRule 表格,清晰看到:管控 pods,拥有 get list watch 三个权限。
 [root@master30 ~ 11:49:48]# kubectl  describe  roles pod-role -n default 
 Name:         pod-role
 Labels:       <none>
 Annotations:  <none>
 PolicyRule:
   Resources  Non-Resource URLs  Resource Names  Verbs
   ---------  -----------------  --------------  -----
   pods       []                 []              [get list watch]
 ​

示例2:访问特定资源pods/readablepod

 #核心关键点 --resource-name
 #不加这个参数:管控全部 pod
 #加--resource-name=xxx:只管控名字匹配的 Pod
 [root@master30 ~ 11:50:24]# kubectl  create  role pod-role --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
 role.rbac.authorization.k8s.io/pod-role created
 ​

示例3:可以对项目中所有replicasets执行get list watch操作

 [root@master30 ~ 15:00:26]# kubectl create role foo --verb=get,list,watch --resource=replicasets

修改 role
 # 增加create权限
 root@master30:~# kubectl edit roles -n default pod-role
 ......
 rules:
 - apiGroups:
   - ""
   resources:
   - pods
   verbs:
 # 在verbs下添加相应权限
   - list
   - get
   - watch
   - create
   
   
 实验变化
 修改前:用户只能查看 Pod,不能创建 Pod;
 修改后:用户新增create权限,可以执行kubectl run创建 Pod;
 所有绑定这个角色的用户,权限自动同步更新,不需要重新绑定。

apiGroups
  • 角色的 rules 属性中 apiGroups 默认为空

  • pod、service 资源的 apiVersion 是v1,apiGroups为""。

  • Deployment、DaemonSet 资源的 apiVersion 是apps/v1,apiGroups为"apps"。如下:

 apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   creationTimestamp: null
   name: deployments-role
   namespace: default
 rules:
 - apiGroups:
   - "apps"
   resources:
   - deployments
   verbs:
   - get
   - list
   - watch

示例1:定义角色,无法操作deployments,因为apiGroups未指定apps。

 apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   creationTimestamp: null
   name: deployments-role
   namespace: default
 rules:
 - apiGroups:
   - ""
   resources:
   - deployments
   verbs:
   - get
   - list
   - watch

示例2:定义一个可以 scale deployments 的角色。

 apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   creationTimestamp: null
   name: deployments-role
   namespace: default
 rules:
 - apiGroups:
   - "apps"
   resources:
   - deployments
   # 额外添加以下资源
   - deployments/scale
   verbs:
   - get
   - list
   - watch
   # 额外添加以下权限
   - patch

示例3:定义一个对不同类型资源赋予不同权限的角色。

 apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   creationTimestamp: null
   name: all-role
   namespace: default
 rules:
 - apiGroups:
   - ""
   resources:
   - pods
   verbs:
   - get
   - list
   - watch
 - apiGroups:
   - "apps"
   resources:
   - deployments
   - deployments/scale
   verbs:
   - get
   - list
   - watch
   - patch

常见apiGroups

apiGroups:K8s 把各种资源分大类存放,每一大类就是一个 apiGroups(资源分组)。

apiVersion 和 apiGroups 的关系: yaml 第一行 apiVersion: apps/v1 拆开看: apps = 分组 (apiGroups),v1 = 版本 只有单纯 v1 的资源,没有分组,apiGroups 填 ""

TypeapiVersionapiGroups
Pod、Service、PersistentVolume、PersistentVolumeClaimv1""
Deployment、DaemonSet、StatefulSetsapps/v1apps
Jobbatch/v1batch
CronJobbatch/v1beta1batch
Role RoleBinding ClusterRole ClusterRoleBindingrbac.authorization.k8s.io/v1rbac.authorization.k8s.io
NetworkPolicynetworking.k8s.io/v1networking.k8s.io

每种类型资源的 apiVersion 都可以通过以下命令查询:

 apiVersion` 格式 = `分组名/版本`,比如 `apps/v1
  • / 前面:apiGroups(资源分组,写权限规则必须填这个)

  • / 后面:v1 是版本号 像 Pod、Service 只有 v1,没有分组,分组填空 ""

 #1. kubectl explain deployment:查看 deployment 这个资源的完整官方说明文档
 #2. | grep VERSION:只过滤出带 VERSION 这一行,不用看一堆没用内容
 root@master30:~# kubectl explain deployment|grep VERSION
 VERSION:  apps/v1
 ​
 root@master30:~# kubectl explain networkpolicy|grep VERSION
 VERSION:  networking.k8s.io/v1
 # 或者
 root@master30:~/auth# kubectl api-resources |grep -i deploy
 deployments                       deploy       apps/v1                                true         Deployment
 ​
 ​
 这两条命令的作用
 你写 RBAC 权限(Role)的时候,不知道某个资源该填什么apiGroups,直接跑这两条命令查,填错分组权限直接失效、会报 403 无权限。
 举个易错对比:
 1. 查 pod:kubectl explain pods |grep VERSION → VERSION: v1,分组填""
 2. 查 deployment:VERSION: apps/v1,分组填apps

role 绑定
先记住一句核心真理(整段实验的关键):

Role = 一堆权限规则(空模板,没人能用)

RoleBinding = 把权限模板分给某个用户(真正授权)

只建 Role 不绑定,权限永远不生效!

 #将 role 绑定给用户。预览绑定配置(dry-run 只模拟、不创建)
 root@master30:~# kubectl create rolebinding default-pod-zy -n default --role=pod-role --user=zy --dry-run=client -o yaml
 apiVersion: rbac.authorization.k8s.io/v1
 kind: RoleBinding  # 资源类型:角色绑定
 metadata:
   name: default-pod-laoma
   namespace: default  # 仅限default命名空间生效
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: Role
   name: pod-role  # 绑定的是哪一个权限角色
 subjects:  # 授权对象
 - apiGroup: rbac.authorization.k8s.io
   kind: User
   name: zy  # 被授权的用户:zy
 ​
 ​
 核心:把 default命名空间下的 pod-role 所有权限,全权交给 zy 用户
 # 绑定 ns/default 中角色 pod-role 给 zy
 root@master30:~# kubectl create rolebinding default-pod-laoma -n default --role=pod-role --user=zy
 # 角色绑定完成后,角色的权限发生变化,用户获得的权限也会跟着动态变化。
 ​
 ​
 # 简洁查看绑定关系, 查看绑定是否成功
 root@master30:~# kubectl get rolebindings -n default default-pod-zy
 NAME                    ROLE              AGE
 default-pod-zy   Role/pod-role   2m15s
 # 详细查看:绑定角色、授权用户
 root@master30:~# kubectl describe rolebindings -n default default-pod-zy
 Name:         default-pod-zy
 Labels:       <none>
 Annotations:  <none>
 Role:
   Kind:  Role
   Name:  pod-role
 Subjects:
   Kind  Name   Namespace
   ----  ----   ---------
   User  zy 
  
 # 验证: 客户端验证权限(zy用户)
 root@client:~# kubectl run web --image=hub.laoma.cloud/library/httpd --image-pull-policy=IfNotPresent -n default
 ​
 root@client:~# kubectl get pod -n default
 NAME   READY   STATUS    RESTARTS   AGE
 web    1/1     Running   0          2m30s
 ​
 ​
 root@client:~# kubectl get pod -n default -w
 NAME   READY   STATUS    RESTARTS   AGE
 web    1/1     Running   0          2m42s
 ​
 结果:全部成功,无报错,证明绑定成功、权限完全生效

role 回收
回收原理:

删除 RoleBinding(绑定记录) = 立刻收回用户权限

注意:只解绑用户,Role权限模板还在,可重新绑定给其他人(推荐用法)

 #解绑命令
 root@master30:~# kubectl delete rolebindings default-pod-laoma -n kube-system 
 rolebinding.rbac.authorization.k8s.io "default-pod-laoma" deleted
 ​
 # 再次验证:显示报错:Forbidden 禁止访问
 root@client:~# kubectl get pod -n default
 Error from server (Forbidden): pods is forbidden: User "zy" cannot list resource "pods" in API group "" in the namespace "default"
 ​
 原因:绑定记录删了,zy 和 pod-role 权限彻底断开,瞬间无权限。

Role彻底删除(销毁权限模板)

后果:

  • 所有绑定过这个角色的用户,全部失效

  • 以后想再用这套权限,必须重新创建Role

 root@master30:~# kubectl delete roles pod-role -n default

整套实验 极简逻辑闭环(必背):
  1. 建Role:写好一套权限规则(能干啥)

  2. 建RoleBinding:把规则分给用户(真正授权)

  3. 用户测试:权限正常使用

  4. 回收权限:删RoleBinding(用户下岗,模板保留)

  5. 彻底销毁:删Role(模板直接作废)

新手最容易混淆的2个点
1. 为什么改Role权限,不用重新绑定?

绑定是「永久关联」,模板变了,关联的用户权限自动跟着变。

2. 删除RoleBinding 和 删除Role 的区别:
  • 删Binding:只撤用户权限,模板还在(灵活,推荐)

  • 删Role:模板直接没了,所有人都不能用(彻底销毁)

实践 1:角色管理
  1. 在 auth 命名空间,创建角色 pod-reader,针对pod,具备权限get、list、watch

  2. 赋予 zy 用户 auth 命名空间 角色 pod-reader

  3. 管理员身份在 auth 命名空间创建 deployment

  4. 回收 zy 用户 集群管理员角色 cluster-admin(如果存在)

  5. zy用户验证:查看deployment和pod

  6. 清理资源:回收用户角色,删除 deployment

 实践1:角色管理 完整实操流程(含详细解释)
 实验需求总览
 1. 在 auth 命名空间 创建角色 pod-reader:对pod拥有 get、list、watch 权限
 2. 将该角色授权给用户 zy(仅 auth 命名空间生效)
 3. 管理员在 auth 命名空间创建一个 deployment
 4. 回收 zy 可能存在的集群管理员权限 cluster-admin(防干扰)
 5. 切换 zy 用户验证权限:能看pod、不能看deployment
 6. 最后清理所有实验资源
 ​
 ---
 步骤1:创建实验命名空间 auth
 kubectl create ns auth
 解释:所有本次实验的角色、资源全部隔离在 auth 命名空间,不影响集群其他环境。
 ​
 ---
 步骤2:在auth命名空间创建角色 pod-reader
 权限要求:pod资源、get / list / watch
 # 先预览(可选)
 kubectl create role pod-reader -n auth --verb=get,list,watch --resource=pods --dry-run=client -o yaml
 ​
 # 真正创建角色
 [root@master30 ~ 15:36:17]# kubectl  create  role pod-reader -n auth  --
 verb=get,list,watch --resource=pods 
 role.rbac.authorization.k8s.io/pod-reader created
 ​
 ​
 通俗解释:
 创建了一个「权限模板」:
 在 auth 命名空间内:允许查看所有Pod、单个Pod、实时监控Pod
 注意:只给了pod权限,完全没给deployment权限
 ​
 ---
 步骤3:角色绑定——把 pod-reader 权限分给用户 zy
 [root@master30 ~ 15:37:19]# kubectl  create  rolebinding  zy-pod-reader -n auth  --role=pod-reader --user=zy
 ​
 通俗解释:
 Role 只是空规则,必须绑定用户才生效。
 本条命令含义:在auth命名空间,让zy用户拥有 pod-reader 全套权限
 ​
 ---
 步骤4:管理员在auth命名空间创建Deployment
 [root@master30 ~ 15:38:00]# kubectl  create  deployment test-web -n auth --image=nginx
 deployment.apps/test-web created
 ​
 解释:
 创建一个deployment用于后面测试权限隔离:
 zy只有pod权限、没有deployment权限
 ​
 ---
 步骤5:回收zy用户可能存在的集群最高权限(关键步骤)
 [root@master30 ~ 15:38:36]# kubectl delete clusterrolebinding cluster-admin-zy 2>/dev/null
 实验必考解释:
 很多同学之前做实验给 zy 绑过 cluster-admin(超级管理员)
 如果不回收,zy权限无敌,本次实验的权限隔离直接失效!
 本条作用:剥夺zy全局所有权限,只保留我们刚刚手动分配的pod权限
 ​
 ---
 步骤6:切换 zy 用户验证权限(核心考点)
 zy用户权限预期:
 ✅ 可以:kubectl get pods -n auth
 ❌ 不可以:kubectl get deploy -n auth(会403报错)
 验证1:查看Pod(有权限)
 [root@client ~ 15:27:18]# kubectl  get pods  -n auth
 NAME                        READY   STATUS    RESTARTS   AGE
 test-web-7cb54d765c-sw9nf   1/1     Running   0          56s
 ​
 正常输出运行中的pod,证明 get、list 权限生效
 验证2:查看Deployment(无权限)
 [root@client ~ 15:39:32]# kubectl  get  deployment -n auth
 Error from server (Forbidden): deployments.apps is forbidden: User "zy" cannot list resource "deployments" in API group "apps" in the namespace "auth"
 ​
 必报错 Forbidden
 原因:我们创建的角色 只授权了pod,没有授权deployment
 ​
 ---
 步骤7:实验收尾——清理所有资源
 1. 回收zy用户角色(解绑权限)
 [root@master30 ~ 15:39:16]# kubectl delete rolebinding zy-pod-reader -n auth
 rolebinding.rbac.authorization.k8s.io "zy-pod-reader" deleted
 ​
 解释:立刻收回zy的pod查看权限
 2. 删除实验deployment
 [root@master30 ~ 15:40:36]# kubectl delete deploy test-web -n auth
 deployment.apps "test-web" deleted
 [root@master30 ~ 15:40:47]# kubectl  get all
 No resources found in auth namespace.
 ​
 3. 可选:删除角色、删除命名空间(彻底清零)
 kubectl delete role pod-reader -n auth
 kubectl delete ns auth
 ​
 ​
 ---
 本实验核心总结(考试必背)
 1. Role 是命名空间级权限:只在 auth 生效,其他ns无效
 2. Role必须绑定用户才生效(RoleBinding)
 3. 权限是精细隔离的:给pod权限 ≠ 拥有deployment权限
 4. 实验前必须清掉 cluster-admin 超级权限,否则实验无效
 5. get/list 独立权限:本实验同时给了,所以查单个、查列表都成功
 ​
 ​

clusterrole 管理

一、先分清两个核心概念:Role vs ClusterRole
1. Role(上一节学的)
  • 作用范围:仅限某一个 namespace,带 -n xxx

  • 绑定工具:RoleBinding(同样受命名空间限制)

  • 举例:default 命名空间的 pod 查看权限,kube-system、auth 命名空间用不了

2. ClusterRole(本节内容)
  • 作用范围:整个集群,所有 namespace 全部生效,不需要加 -n

  • 绑定工具:ClusterRoleBinding(全局绑定,不受命名空间约束)

  • 举例:拥有 pod 查看权限后,default、auth、kube-system 所有命名空间 pod 都能看

二、系统 4 个内置预定义 ClusterRole(自带,不用手动创建)
  1. view(只读) 只能 get/list/watch 所有资源,不能创建、删除、修改任何资源。适合普通查看人员。

  2. edit(编辑) 包含 view 全部权限,额外能 create/delete/update/patch 普通业务资源;不能操作权限类资源(Role、ClusterRole)。适合开发人员。

  3. admin(命名空间管理员) 单个 namespace 内几乎所有权限,可以删改本命名空间一切资源,但不能操作集群级资源(node、存储、集群角色)。

  4. cluster-admin(超级全局管理员) 集群最高权限,所有资源、所有命名空间、集群节点全部能操作,相当于 root,实验做完必须回收,否则权限过大不安全。

创建 clusterrole
 [root@master30 ~ 15:40:55]# kubectl  create  clusterrole --help 
 Create a cluster role.
 ​
 Usage:
   kubectl create clusterrole NAME --verb=verb --resource=resource.group
 [--resource-name=resourcename] [--dry-run=server|client|none] [options]
 ​
 #语法讲解:
 kubectl create clusterrole 角色名 --verb=操作 --resource=资源 
 和普通 Role 命令几乎一样,只有两点区别:
 1. 不用写 -n 命名空间;
 2. 类型是 ClusterRole,权限全集群生效。

示例1:创建一个可以get、list、watch所有项目中pods的clusterrole。效果:这套权限作用于集群全部 namespace

 [root@master30 ~ 16:07:03]# kubectl  create  clusterrole pod-role --verb=get,list,watch  --resource=pods  --dry-run=client -o yaml
 #yaml 关键区别:kind: ClusterRole,没有 namespace 字段
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole # 全局角色,无namespace限制
 metadata:
   creationTimestamp: null
   name: pod-role
 rules:
 - apiGroups:
   - ""
   resources:
   - pods
   verbs:
   - get
   - list
   - watch
 #创建真实角色:
 [root@master30 ~ 16:09:44]# kubectl  create  clusterrole pod-role --verb=get,list,watch  --resource=pods 
 clusterrole.rbac.authorization.k8s.io/pod-role created
 ​
 ​
 #查看 / 验证权限
 [root@master30 ~ 16:10:29]# kubectl  get clusterrole pod-role 
 NAME       CREATED AT
 pod-role   2026-07-10T08:10:29Z
 [root@master30 ~ 16:10:48]# kubectl  describe  clusterrole pod-role 
 Name:         pod-role
 Labels:       <none>
 Annotations:  <none>
 PolicyRule:
   Resources  Non-Resource URLs  Resource Names  Verbs
   ---------  -----------------  --------------  -----
   pods       []                 []              [get list watch]
 ​

示例 2:只允许全局查看指定名字的 Pod

--resource-name 限定资源名,只能 get 这两个 pod,不能 list 全部 pod。

 root@master30:~# kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod

示例3:同时授权 pod 和 pod 状态子资源

pods/status 是 pod 的子资源,单独写在 resources 里才能查看 pod 运行状态。

 root@master30:~# kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status

修改 clusterrole:

打开 yaml,在 verbs 添加create保存即可,全局权限实时更新,不用重新绑定

 [root@master30 ~ 16:11:07]# kubectl  edit  clusterrole pod-role 
 clusterrole.rbac.authorization.k8s.io/pod-role edited
 ​
 ....................................
 rules:
 - apiGroups:
   - ""
   resources:
   - pods
   verbs:
   - get
   - list
   - watch
   # 添加create权限
   - create

clusterrole 绑定

ClusterRole 只是权限模板,必须通过ClusterRoleBinding绑定用户才能生效。

将clusterrole绑定给用户。

 #预览绑定 yaml
 [root@master30 ~ 16:11:53]# kubectl  create  clusterrolebinding   zy-pod-role --clusterrole=pod-role  --user=zy  --dry-run=client -o yaml
 ​
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRoleBinding          # 全局绑定,无namespace
 metadata: 
   creationTimestamp: null
   name: zy-pod-role           
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
   name: pod-role            # 绑定刚才创建的全局角色
 subjects:
 - apiGroup: rbac.authorization.k8s.io
   kind: User
   name: zy        # 授权用户zy
 [root@master30 ~ 16:16:07]# kubectl  create  clusterrolebinding   zy-pod-role --clusterrole=pod-role  --user=zy 
 clusterrolebinding.rbac.authorization.k8s.io/zy-pod-role created
 ​
 [root@master30 ~ 16:18:59]# kubectl  get  clusterrolebindings  zy-pod-role 
 NAME          ROLE                   AGE
 zy-pod-role   ClusterRole/pod-role   2m42s
 ​
 [root@master30 ~ 16:19:21]# kubectl  describe  clusterrolebindings  zy-pod-role 
 Name:         zy-pod-role
 Labels:       <none>
 Annotations:  <none>
 Role:
   Kind:  ClusterRole
   Name:  pod-role
 Subjects:
   Kind  Name  Namespace
   ----  ----  ---------
   User  zy    
 ​
 ​
 # client节点使用zy用户测试权限
 [root@client ~ 15:39:49]# kubectl  get pod -n kube-system
 NAME                                        READY   STATUS    RESTARTS         AGE
 calico-kube-controllers-585df69d45-2cc6g    1/1     Running   20 (4h38m ago)   4d19h
 calico-node-5l6qm                           1/1     Running   5 (4h38m ago)    4d19h
 calico-node-6kjbg                           1/1     Running   4 (4h38m ago)    4d19h
 calico-node-jpn9r                           1/1     Running   4 (4h38m ago)    4d19h
 coredns-7db6d8ff4d-2vz26                    1/1     Running   4 (4h38m ago)    4d19h
 ......
 ​
 [root@client ~ 16:20:45]# kubectl  get pod -n default
 No resources found in default namespace.
 ​
 ​
 如果是普通 Role 绑定,只能看绑定时指定的单个 namespace,别的命名空间会报 403;ClusterRole 全局绑定全部 namespace 都放行。

回收 / 删除权限两种操作
  1. 回收用户权限(推荐):删除 ClusterRoleBinding 只断开用户和全局角色的关联,ClusterRole 模板保留,后续可以重新绑定给其他人。

 [root@master30 ~ 16:19:34]# kubectl  delete clusterrolebindings.rbac.authorization.k8s.io   zy-pod-role 
 clusterrolebinding.rbac.authorization.k8s.io "zy-pod-role" deleted
 ​

删除后 laoma 立刻失去所有 namespace 的 pod 查看权限。

2.彻底销毁权限模板:删除 ClusterRole 直接删掉全局权限模板,所有绑定过这个 ClusterRole 的用户全部失效。

 kubectl delete clusterrole pod-reader

对比Role和ClusterRole:
项目Role(命名空间角色)ClusterRole(集群全局角色)
生效范围仅单个 namespace集群所有 namespace
创建命令-n xxx无需 -n
绑定工具RoleBindingClusterRoleBinding
适用场景只给用户开放某个项目资源用户需要查看全集群资源(节点、所有 ns、集群配置)
一句话大白话总结
  1. Role = 只管一个班级;ClusterRole = 管全校所有班级;

  2. RoleBinding = 分配班级权限;ClusterRoleBinding = 分配全校权限;

  3. cluster-admin 是全校超级管理员,权限最大,实验用完一定要解绑回收。

实践 2:使用现有集群角色
  1. 赋予 laoma 用户集群角色 admin,指定在auth命名空间

  2. laoma 用户在 auth 命名空间:创建、查看和删除 deployment

  3. laoma 用户在 default 命名空间:创建、查看和删除 deployment

  4. 回收 laoma 用户权限

 实践 2:绑定 ClusterRole(admin)给用户,想限制只在 auth 命名空间,失败
 完整流程
 1. 需求:给 laoma 绑定系统自带 ClusterRole admin,希望只让他操作 auth 空间,不能碰 default
 2. 执行绑定命令(全局绑定,不能加 - n 限制)
 ​
 结论(考点)
 ClusterRoleBinding 是集群全局绑定,没有命名空间限制,一旦绑定 admin 这个集群角色,用户在所有 namespace都拥有 admin 权限,无法通过绑定命令限定仅某个命名空间使用。
 如果只想让用户在单一 namespace 拥有管理员权限,不能用 ClusterRoleBinding,要用:本地 Role + RoleBinding

实践 3:自定义集群角色
  1. 创建 clusterrole 名称 cluster-pod-deploy-reader,能够查看pod和deployment

  2. 赋予给 laoma 用户

  3. laoma 用户在 auth 命名空间中:查看pod、deployment

  4. laoma 用户在 kube-system 命名空间中:查看pod、deployment

  5. 删除集群角色绑定和集群角色

 实践 3 核心要说明 3 个重点考点
 1. ClusterRole 是集群全局权限,不受命名空间限制
 自定义的 cluster-pod-deploy-reader 属于集群级角色,没有绑定任何单个 namespace:
 在 auth 命名空间能查 pod、deploy
 在 kube-system 系统命名空间照样能查 pod、deploy
 不管集群里有多少命名空间,全部生效。
 对比之前的普通 Role:Role 只能在创建时指定的那一个 namespace 生效,别的空间无权访问。
 ​
 2. ClusterRoleBinding 实现全局授权
 ClusterRole 本身只是一套权限规则,必须通过 ClusterRoleBinding 绑定用户才生效;
 绑定一次后,用户在集群全部命名空间复用这套查看权限。
 ​
 3. 区分两个删除操作的作用(实验最后一步目的)
 删除 clusterrolebinding:仅断开用户 laoma 和权限模板的关联,laoma 立刻失去权限,但是cluster-pod-deploy-reader这个角色模板还留在集群,可以后续分给其他用户;
 删除 clusterrole:直接删掉权限模板本身,就算还有绑定记录也全部失效,整套查看 pod/deploy 的规则彻底消失。
 ​

服务账户

学习参考:管理服务账号配置服务账号

一、什么是 Service Account(SA)
大白话定义

User 用户账号:给用的,你在电脑上 kubectl 登录操作集群。 ServiceAccount 服务账号:给Pod 里的程序用的。 Pod 内部的程序如果需要调用 K8s API(查 Pod、删资源、监控集群),不能用人的证书,只能绑定 SA 身份访问集群。

默认自带 SA

每个命名空间自动生成一个名叫 default 的 SA; 新建 Pod不指定 sa 名称时,自动挂载 default 服务账号。 验证命令:

 [root@master30 ~ 16:23:00]# kubectl  get sa
 NAME      SECRETS   AGE
 default   0         22h
 ​
 ​
 # 创建一个pod,验证Service Account信息
 [root@master30 ~ 17:08:19]# kubectl  run  web --image=docker.io/library/httpd --image-pull-policy=IfNotPresent
 pod/web created
 [root@master30 ~ 17:10:38]# kubectl  get pods
 NAME   READY   STATUS    RESTARTS   AGE
 web    1/1     Running   0          89s
 ​
 ​
 [root@master30 ~ 17:11:31]# kubectl  get pod web  -o yaml | grep serviceAccount  serviceAccount: default
   serviceAccountName: default
       - serviceAccountToken:
 ​
       
 #输出能看到 serviceAccountName: default,代表这个容器用默认 sa 身份运行。

二、用户账号 vs 服务账号 对比
对比项用户账号 (User)服务账号 (ServiceAccount)
给谁用运维 / 开发人员(人操作)Pod 内部应用程序(程序自动调用 API)
生效范围全局集群,名字唯一命名空间隔离,不同 ns 可以同名 sa
创建方式外部系统提供(证书、LDAP、OIDC),集群不存用户列表kubectl create sa 直接在集群创建,轻量简单
设计目的人和集群交互程序自动操作集群,遵循最小权限

核心考点:K8s 内部没有 User 资源对象,查不到所有用户;但 SA 是标准 v1 资源,能 kubectl get sa 查看。

三、SA 令牌自动挂载机制(重点)
1、自动投射卷

新版 K8s(1.22+)不用 secret,kubelet 自动给 Pod 挂载一个只读目录: /var/run/secrets/kubernetes.io/serviceaccount 进入 Pod 查看里面 3 个文件:

  1. token:SA 身份令牌,程序拿着这个令牌调用 kube-apiserver;

  2. ca.crt:集群根证书,用来安全连接 API;

  3. namespace:当前 Pod 所在命名空间名称。

2、短期令牌 TokenRequest(新版优势)
  1. 令牌有过期时间(默认 1 小时),自动轮换,更安全;

  2. 令牌绑定当前 Pod,Pod 删除令牌直接失效

  3. 淘汰旧方案:以前把令牌存 Secret,永久有效,泄露风险高。

3、Pod 内部如何使用

程序读取目录下的 token,带上请求头访问集群 API,集群识别 SA 身份,再用 RBAC 判断能不能操作资源。

 [root@master30 ~ 17:17:48]# kubectl  get pod web  -o yaml 
 ...
     volumeMounts:
     - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
       name: kube-api-access-sjffr
       readOnly: true
 ...
   volumes:
   - name: kube-api-access-sjffr
     projected:
       sources:
         - serviceAccountToken:
             path: token # 必须与应用所预期的路径匹配
         - configMap:
             items:
               - key: ca.crt
                 path: ca.crt
             name: kube-root-ca.crt
         - downwardAPI:
             items:
               - fieldRef:
                   apiVersion: v1
                   fieldPath: metadata.namespace
                 path: namespace

该清单片段定义了由三个数据源组成的投射卷。在当前场景中,每个数据源也代表该卷内的一条独立路径。这三个数据源是:

三个数据源分别干什么(人话终极解释)
1. serviceAccountToken → 【身份令牌】

作用:相当于 Pod 的动态身份证

关键知识点(考试必考)
  1. 新版机制:TokenRequest API kubelet 动态从 apiserver 申请短期令牌,默认有效期 1 小时、自动轮换

  2. 绑定当前 Pod 这个 token 只属于当前这一个 Pod,别的 Pod 用不了。

  3. 过期机制很安全

  • Pod 删除 → 令牌立刻失效

  • 1 小时到期 → 自动换新 token

对比旧版

旧版:token 存在 Secret 里 永久有效,泄露 = 炸库。 新版:限时、自动销毁、绑定 Pod,安全性大幅提升。

重点注意

无法手动作废 token 不信任这个令牌 → 直接删 Pod 即可销毁权限。

2. configMap → 集群根证书 ca.crt
作用:【安全锁】

让 Pod 确认自己连接的是真实的 apiserver,不是伪造、中间人劫持。

程序访问集群 API 时: 拿着 ca.crt 校验服务器证书,确保通信安全。

3. downwardAPI → 自动注入当前 Pod 的 namespace
作用:【位置信息】

自动把 当前 Pod 所在命名空间 写入文件 namespace

比如你在 auth 命名空间启动 Pod,文件内容就是:

 auth

程序读取这个文件,就知道自己在哪个命名空间运行,自动适配 API 请求路径。

Pod 内挂载这个特定卷的所有容器都可以访问上述信息。
 [root@master30 ~ 17:26:08]# kubectl  exec  -it web  -- bash
 root@web:/usr/local/apache2# ls /var/run/secrets/kubernetes.io/serviceaccount/
 ca.crt  namespace  token
 ​
 #三个文件一一对应上面三大功能:
 1. token = 身份通行证
 2. ca.crt = 安全证书
 3. namespace = 当前位置
 ​
 root@web:/usr/local/apache2# ls /var/run/secrets/kubernetes.io/serviceaccount/
 ca.crt  namespace  token
 root@web:/usr/local/apache2# cat /var/run/secrets/kubernetes.io/serviceaccount/token 
 eyJhbGciOiJSUzI1NiIsImtpZCI6Ik1oT2h1X3JrbkJxMjJHcmFmUXVIUk4zUl9xNTlBZnJqbThvMzhSV3FyVlEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxODE1MjEwNjAyLCJpYXQiOjE3ODM2NzQ2MDIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiODFiMWU5NTQtYzQ4Yy00NjA3LThlYzgtMmUwZWM4ODFiMjdhIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJhdXRoIiwibm9kZSI6eyJuYW1lIjoid29ya2VyMzIuenkuY2xvdWQiLCJ1aWQiOiI5NzEzYmMyNC0yYTc0LTRmOTktOWRiYS0wMDJhOGYzOTc4NDYifSwicG9kIjp7Im5hbWUiOiJ3ZWIiLCJ1aWQiOiI5Njc4M2Y2MS0yNzMwLTQ1MTQtYThlOS1hY2NmYmQ4MGY0OGYifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiJjNmI5NTBjNC01YTUxLTRlNzMtOTdkZC1mMTQwZWFhYjYzMjIifSwid2FybmFmdGVyIjoxNzgzNjc4MjA5fSwibmJmIjoxNzgzNjc0NjAyLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6YXV0aDpkZWZhdWx0In0.B7l8HRnUih_sL5aFoPVN2iNxVnRJN8txFt6Uke7rCdQssYqc8OBR_fyClhbo9C7hEv2MfPEpQuR0ttt4J0qqPwES5pPU8UNaBbpmIK2NDxu7jVM217L1tnKqaZKqW2DuofODthDai3YTZj92jAolqbfOpsjqtRHPAKHcJKBghNz05Y49xemJl5sYvkBmbEeDFV4-_Riryb3uZhgZcygZ0synKUMW3g0kT4xHickntV2jomb_ZXdpou_rioE8M3Qh2l91lakONdn0D7isk8i6ivmv9n2L9FiMMIAWR9_G-uMiwY-NkLdAkFV9882goUreSgyRJq4-ZTJFtJLSWS-Y-A
 root@web:/usr/local/apache2# cat /var/run/secrets/kubernetes.io/serviceaccount/
 ca.crt 
 -----BEGIN CERTIFICATE-----
 MIIDBTCCAe2gAwIBAgIIJz1ulbddcc0wDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
 AxMKa3ViZXJuZXRlczAeFw0yNjA3MDUxMjU4MTVaFw0zNjA3MDIxMzAzMTVaMBUx
 EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
 AoIBAQDViIuDsljALOOsUyrNPVDQPACCS0JwajxOTD87TamCl9qSOiaZZzCg8v1u
 eWu6A7vNGtGADin/pe6JSqDH8cb5JdW+CmwDvALzrdb9f5lTz+DO5dIBBLNGL4yt
 9tCJZY5eznfEGWCbMu1Svn8mQx4i5Oaig/9C4wPB8y0KEi7W8NauIwLFFul+tcjU
 5uHp40V2UphuoUyA9ElJLVs/79ykjEcacYsAWetb9lLiIrEmpwrKtMjCnn9WzifO
 3ckxF58+1Y+AOlxcynlhHTQfXMOo9ys4kTuOEn7og3hntL+rS3bvSazqjeZYbFbM
 Y0PObf0827z+e1t0+yAEXM/hmiudAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRSYXzxPFy/Q6enZSz/ezsBMwF8HTAV
 BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQCEd1J6K+Yb
 jTIbJZbquxJBrio58uhKLNrQeAYcVEGhD4gEK4eEa3rwoBnEUriW0Bsz4avRdcxa
 l441YdAHX+Jv1BbxeUpcLNMo2yRYVwjQQ9e0VjJNBDyekVHaDdDQRyQT9GXu8mqk
 YGYI65BT3M89K1fgnnZ9MVa8RSpzROm90NgQwyhXJ50P6wmEUhbqlMFEgMQPxwis
 YdoyecIhbMXkZuMUOm0mJ7zhmMooKZlp6QzW/CDu0tKQFMerdF2EiUPHbtJHRuE8
 07kbHa7i4KG9uqpcT1lgsyatcg59eLq+2VHKRvhYmJ+4kozJH7IMh4D27d97zw1N
 QynzXBL4dnuH
 -----END CERTIFICATE-----
 ​
 root@web:/usr/local/apache2# cat /var/run/secrets/kubernetes.io/serviceaccount/namespace 
 authroot
 ​
 #证明:这个 Pod 运行在 auth 命名空间

四:服务账户管理
1. 创建自定义 SA
 # 在当前命名空间创建sa1
 [root@master30 ~ 17:30:16]# kubectl  create  sa sa1
 serviceaccount/sa1 created
 [root@master30 ~ 17:30:27]# kubectl  get sa sa1 
 NAME   SECRETS   AGE
 sa1    0         10s
 ​
2. 给 SA 授权(核心:绑定 RBAC 角色)

SA 只是身份,没有权限,必须用 ClusterRoleBinding/RoleBinding 绑定角色。 语法特殊点:--serviceaccount=命名空间:sa名称

 # 给auth命名空间sa1绑定全局超级管理员cluster-admin
 [root@master30 ~ 17:30:37]# kubectl  create  clusterrolebinding  auth-sa1-cluster-admin --clusterrole=cluster-admin  --serviceaccount=auth:sa1
 clusterrolebinding.rbac.authorization.k8s.io/auth-sa1-cluster-admin created
 ​
 # 选项--serviceaccoun指明Service Account时,格式为namespace:Service Account Name
3. Pod 指定使用自定义 SA

Pod 默认用 default,想要 sa1 权限必须在 spec 声明:

 # 删除 pod 重新创建
 [root@master30 ~ 17:31:41]# kubectl  delete  pod web
 ​
 #1. 导出 pod yaml 修改
 [root@master30 ~ 17:32:06]# kubectl  run web --image=docker.io/library/httpd --image-pull-policy=IfNotPresent --dry-run=client -o yaml > web.yaml
 ​
 #2. yaml 添加配置
 [root@master30 ~ 17:33:19]# vim web.yaml 
 apiVersion: v1
 kind: Pod
 metadata:
   creationTimestamp: null
   labels:
     run: web
   name: web
 spec:
   containers:
   - image: httpd
     imagePullPolicy: IfNotPresent
     name: web
     resources: {}
   dnsPolicy: ClusterFirst
   restartPolicy: Always
   # 添加以下任一记录,只写一个另一个就会出现
   serviceAccount: sa1
   serviceAccountName: sa1
 ​
 status: {}
 #3. 创建 pod
 [root@master30 ~ 17:34:39]# kubectl  apply -f web.yaml 
 pod/web created
 ​
 [root@master30 ~ 17:35:03]# kubectl  get pod web  -o yaml 
 ......
 spec:
 ......
   serviceAccount: sa1
   serviceAccountName: sa1
   
   
 #对应上面的添加以下任一记录,加任意一个就行,最终 yaml 都会自动出现两个字段。
 1、核心真相
 serviceAccount 和 serviceAccountName 是同一个功能
 作用都是:让这个 Pod 使用 sa1 服务账号
 你 只写其中任意一个 就行
 你保存创建 Pod 后,k8s 自动补全两个字段
 所以你看到 yaml 里两个都存在,不是你写的,是集群自动补的
   

重要:虽然 pod/web 中 httpd 进程具有 clusterrole/cluster-admin 角色,但是它只是用来提供httpd服务,不会做其他操作。

4. 回收 SA 权限

删除绑定关系即可收回权限,SA 本身保留,删除后,使用 sa1 的 Pod 再调用 API 全部报 403 无权。

 [root@master30 ~ 17:36:42]# kubectl  delete  clusterrolebindings.rbac.authorization.k8s.io  auth-sa1-cluster-admin 
 clusterrolebinding.rbac.authorization.k8s.io "auth-sa1-cluster-admin" deleted
 ​

五、手动管理 SA 令牌(两种令牌)
方式 1:临时短期令牌(推荐,新版默认)

无需创建 secret,实时生成限时 token:

 kubectl create token sa1

特点:一次性临时令牌,不存集群,过期失效,安全。

方式 2:永久长效令牌(不推荐,兼容旧版本)

手动创建带注解的 secret,永久有效,除非删除 sa 或 secret:

 # sa1-token.yaml
 apiVersion: v1
 kind: Secret
 metadata:
   name: sa1-secret
   annotations:
     kubernetes.io/service-account.name: sa1
 type: kubernetes.io/service-account-token

自动填充 token 到 secret;删除 sa 时,这个 secret 会自动清理。

方式一:创建临时令牌
 # 1. 创建服务账号sa1:作用:在当前命名空间生成一个 ServiceAccount 身份,只是账号,不带固定 token。
 [root@master30 ~ 17:48:31]# kubectl  create  tocken sa1
 ​
 # 2. 实时生成短期访问令牌
 [root@master30 ~ 17:48:53]# kubectl  create  token sa1
 eyJhbGciOiJSUzI1NiIsImtpZCI6Ik1oT2h1X3JrbkJxMjJHcmFmUXVIUk4zUl9xNTlBZnJqbThvMzhSV3FyVlEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzgzNjgwNTQ0LCJpYXQiOjE3ODM2NzY5NDQsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiZWFjYTY0NWMtMjMxOC00ZGRkLTlkZjYtYzZlNmEzODFmMTg0Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJhdXRoIiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InNhMSIsInVpZCI6ImRlNTQzMDc1LWExOWItNDYyOC1iZDY3LWIxNGRkYzdlZTA4YyJ9fSwibmJmIjoxNzgzNjc2OTQ0LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6YXV0aDpzYTEifQ.c-Cv_0qaXdcwIV2tqD_qcV9D7d45geNO7APqelB2OBXO5a5gqGtIRtRTmhBqXa7dO5fU6cQRLqTKDx04tB2bD5KEawn6AFzK16_q9uuVYJbWYqnmPzwXbdLqBZKLed4qIn9iglPzGU2zlbQxKReuwxwizhPKPIP36-M36HPZJkjHR6lPy90j7m70WIbrkiDNIezHmKdYAd7aNMWZ5tM3qOw2ie6fnTNPDljx8O0CkO_fgUPEnlftUti3nFCBg-WX3-96bWX9xlpe7FLWTQxLmc1C0DOoSWooAG4eP_FxE2mshPwVu8h8ZvZ8FV4hYchw6DWC1EUMYMxly4ZI00DPng
 ​
 # # 查看sa完整配置,看不到token相关内容,注意:服务账号属性中是看不到关联的token的。
 [root@master30 ~ 17:49:32]# kubectl get sa sa1 -o yaml
 apiVersion: v1
 kind: ServiceAccount
 metadata:
   creationTimestamp: "2026-07-10T09:30:27Z"
   name: sa1
   namespace: auth
   resourceVersion: "108250"
   uid: de543075-a19b-4628-bd67-b14ddc7ee08c
 ​

方式二:创建永久令牌

创建一个带有特殊注解 kubernetes.io/service-account.name 的 Secret 对象。一旦你手动创建一个 Secret 并将其关联到 ServiceAccount, Kubernetes 控制平面就会自动将令牌填充到该 Secret 中。

 [root@master30 ~ 17:49:36]# vim sa1-token.yaml
 apiVersion: v1
 kind: Secret
 metadata:
   name: sa1-secret
   annotations:
     kubernetes.io/service-account.name: sa1
 type: kubernetes.io/service-account-token
 [root@master30 ~ 17:50:16]# kubectl apply -f sa1-token.yaml
 secret/sa1-secret created

当你删除一个与某 Secret 相关联的 ServiceAccount 时,Kubernetes 的控制面会自动清理该 Secret 中长期有效的令牌。

 [root@master30 ~ 17:50:34]# kubectl delete sa sa1 
 serviceaccount "sa1" deleted
 [root@master30 ~ 17:50:45]# kubectl get secrets 
 No resources found in auth namespace.
 ​

说明: 尽管存在手动创建长久 ServiceAccount 令牌的机制,但还是推荐使用 TokenRequest 获得短期的 API 访问令牌。

六、思考题:K8s 为什么不内置用户管理?
  1. K8s 只专注容器编排,认证鉴权只提供标准接口,不做账号存储;

  2. 企业内部已有成熟账号系统:LDAP、AD、Keycloak、证书系统;

  3. 解耦设计:用户信息外置,集群不用维护海量用户,灵活对接企业现有登录体系;

  4. 只有 SA 是集群内部原生账号,专门给程序使用。

简单一句话:管人交给外部系统,管程序内置 SA。

七、SA 整体使用场景总结
  1. 自动化组件:Dashboard、监控 Prometheus、日志收集,Pod 需要查询集群资源;

  2. CI/CD 流水线 Pod:自动创建 / 删除部署;

  3. 自定义控制器 Operator:程序监听集群资源变化,必须 SA 身份调用 API;

  4. 最小权限安全管控:给 Pod 分配专用 SA,只开放必要权限,不用超级管理员。

八、核心易混点总结
  1. User = 人;ServiceAccount = 程序 / Pod;

  2. 每个 ns 自带 default SA,Pod 不指定则默认使用;

  3. SA 本身无权限,必须通过 RoleBinding/ClusterRoleBinding 绑定角色;

  4. 新版自动挂载短期 token,无需手动创建 secret;

  5. 短期 token 安全,永久 token 仅老旧环境兼容使用;

  6. K8s 不管理人类用户,仅原生支持服务账号 SA。

环境清理

 [root@master30 ~ 17:50:49]# kubectl delete ns auth
 ​

更多推荐