前言
Kubernetes几乎所有操作,kubectl操作、Pod内部程序访问集群、第三方平台对接,全部都要请求kube‑apiserver。如果API接口没有访问管控,任何人都可以随意增删集群资源,集群安全将完全失控。
K8s设计了一套分层访问控制链路,一次API请求会依次经历:TLS传输安全 → 身份认证 → 鉴权授权 → 准入控制,最后写入etcd,还支持审计日志记录操作行为。很多同学容易混淆认证和授权:认证解决"你是谁",授权解决"你能干什么"。本文结合实操带你完整理解整套权限体系。
一、Kubernetes API访问控制完整流程
完整请求链路:
- 传输安全TLS:客户端与apiserver通信全部走TLS加密,apiserver默认监听6443端口,生产环境常用443。客户端需要CA证书验证服务端证书,防止中间人劫持。
- 身份认证Authentication :校验请求方身份,确认你是谁。认证失败直接返回
401 Unauthorized。多个认证插件顺序尝试,任意一个认证成功即通过。 - 鉴权授权Authorization :确认身份之后,判断该用户是否允许执行本次操作(什么用户、什么命名空间、什么资源、什么动作)。全部鉴权模块都无许可则返回
403 Forbidden。 - 准入控制Admission Control :仅针对增删改请求,只读请求不会执行。多个准入控制器串行执行,任意一个拒绝,请求直接失败;还可以自动补全资源默认字段。
- 校验资源格式合法,写入etcd持久化。
- 审计Audit:按时间记录集群安全相关操作,用于事后追溯排查。
区分状态码:401代表身份不合法(认证失败);403代表身份没问题,但是权限不足(鉴权拒绝)。
二、身份认证:确认访问者"你是谁"
K8s有两类访问身份:普通用户(人使用)、服务账号ServiceAccount(Pod内程序使用)。
2.1 两类用户核心区别
- 普通用户User
Kubernetes没有User这个API资源对象!集群不会保存普通用户账号。用户名来源于外部认证插件:X509证书CN字段、令牌、外部LDAP/OIDC。集群不能通过kubectl查询普通用户列表。
设计哲学:K8s只做编排,身份交给外部系统,方便对接企业AD、LDAP。
- 服务账号ServiceAccount
属于K8s原生API资源,命名空间隔离,每个ns自带defaultSA;会生成令牌,挂载进Pod,供容器内部程序调用apiserver。
2.2 主流认证插件
- X509客户端证书:日常kubectl使用方式,apiserver启动参数
--client‑ca‑file校验客户端证书。证书CN就是用户名,O对应用户组。 - Bootstrap Token:集群节点加入的引导令牌,存放在kube-system下Secret。
- ServiceAccount JWT令牌:Pod内部访问集群默认认证方式。
- 静态令牌文件、Webhook认证、认证代理;1.19版本废弃basic‑auth-file。
实操:X509证书创建外部普通用户
实现创建laoma用户,签发证书,生成kubeconfig配置文件。
- 客户端生成私钥与证书请求csr
bash
openssl genrsa -out laoma.key 2048
openssl req -new -key laoma.key -out laoma.csr -subj '/CN=laoma/O=kubernetes'
- Master节点使用集群CA签发用户证书
bash
openssl x509 -req -in laoma.csr -CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out laoma.crt -days 1095
- 组装kubeconfig,写入集群CA、用户证书私钥。
重点:删除普通用户权限,只需要删除RBAC绑定;证书本身没有过期撤销机制,如果证书未过期,即使删除集群内RBAC绑定,持有证书依然可以完成认证,只是鉴权会403。真正封禁用户需要证书黑名单。
匿名请求
没有携带任何有效认证凭据的请求,识别为匿名用户system:anonymous,用户组system:unauthenticated,交由鉴权模块判断是否允许操作。
三、授权鉴权:判断"你可以干什么"
认证通过只是知道用户是谁,授权决定该用户可以执行哪些操作。apiserver参数--authorization‑mode指定启用鉴权模块,生产常用Node,RBAC。
支持模式:
- RBAC:最常用,动态API配置权限;
- Node:专门给kubelet节点使用的鉴权;
- ABAC:静态json策略文件,现已不推荐;
- Webhook:把鉴权交给外部http服务;
- AlwaysAllow全部放行;AlwaysDeny全部拒绝。
RBAC核心4种资源
| 资源 | 作用 | 生效范围 |
|---|---|---|
| Role | 定义一组权限规则(资源+动作verbs) | 单个命名空间 |
| RoleBinding | 把Role绑定给User/SA/Group | 绑定的命名空间内生效 |
| ClusterRole | 集群级权限规则,可以包含集群资源、所有ns资源 | 集群全局 |
| ClusterRoleBinding | ClusterRole全局绑定主体 | 全部命名空间生效 |
小技巧:ClusterRole也可以被RoleBinding引用,此时该ClusterRole权限只会在RoleBinding所在的命名空间生效,不需要ClusterRoleBinding。
verbs 常用动作
get:获取单个资源详情list:列出某类型全部资源watch:监听资源变化create/update/patch/delete:增改删操作
apiGroups一定要写对!pod/service属于
""空组;deployment属于apps;job属于batch,写错apiGroups会权限一直报错。
实操演示命名空间Role + RoleBinding
创建auth命名空间,创建pod‑reader角色,只允许get/list/watch pod资源。
bash
# 创建命名空间
kubectl create ns auth
# 创建Role,auth命名空间内,pod只读权限
kubectl create role pod‑reader -n auth --verb=get,list,watch --resource=pods
# RoleBinding把角色绑定给laoma用户
kubectl create rolebinding laoma‑podread -n auth --role=pod‑reader --user=laoma
此时laoma用户只能在auth命名空间查看pod,其他命名空间无权限。删除rolebinding就回收权限。
ClusterRole与ClusterRoleBinding
系统内置预定义ClusterRole:
view:只读,get/list/watch大部分资源;edit:普通开发者,读写命名空间内资源;admin:命名空间管理员;cluster‑admin:集群超级管理员,最高权限。
示例:创建集群角色,允许所有命名空间查看pod
bash
kubectl create clusterrole cluster‑pod‑read --verb=get,list,watch --resource=pods
# 全局绑定,所有命名空间生效
kubectl create clusterrolebinding laoma‑allpod --clusterrole=cluster‑pod‑read --user=laoma
四、服务账号ServiceAccount深度解析
ServiceAccount是Pod内部程序访问apiserver的身份。每个namespace自带default SA,新建Pod默认挂载default账号。
SA令牌机制变化(重点!1.24+)
- k8s1.24之前:SA会自动生成永久token的Secret,永久有效,风险高;
- k8s1.24及以上:Bound ServiceAccount Token,短期临时令牌,kubelet通过TokenRequest API获取,默认1小时有效期,Pod销毁令牌立刻失效,通过projected投射卷挂载。
容器内部固定路径:/var/run/secrets/kubernetes.io/serviceaccount/,里面包含token、ca.crt、namespace。Pod内部程序读取token,放在http请求Authorization: Bearer <token>访问apiserver。
SA授权与使用
bash
# 创建sa
kubectl create sa sa‑app -n auth
# 将集群角色绑定给服务账号,格式:命名空间:sa名称
kubectl create clusterrolebinding sa‑app‑admin --clusterrole=view --serviceaccount=auth:sa‑app
Pod通过serviceAccountName: sa‑app指定使用的服务账号。
注意:不要随意给业务Pod授予cluster‑admin最高权限,遵循最小权限原则。
手动获取临时token:
bash
kubectl create token sa‑app -n auth
五、常见坑点总结
- 401和403区分不清:401认证失败(证书/token错误);403认证成功但是权限不足,排查RBAC;
- apiGroups写错:deployment写空字符串,权限永远不生效;
- 普通用户删除:删除RBAC绑定不等于吊销证书,证书没过期依旧认证成功;
- RoleBinding引用ClusterRole:权限只在当前命名空间,不是全局;
- ServiceAccount新版本不会自动生成Secret,不要手动创建永久token,优先使用临时token;
- 多个鉴权模块:只要一个模块允许就放行;全部无意见才拒绝。
六、思考:K8s为什么没有内置普通用户管理?
Kubernetes本身不提供User资源,不存储人类用户账号。遵循UNIX设计哲学:一件事做好一件工作。K8s专注容器编排,身份认证向外提供插件接口。企业可以对接LDAP、OIDC、Keycloak等成熟身份系统,实现账号统一管理,集群和身份系统解耦。
总结
- K8s API访问四层防护:TLS传输加密、身份认证、RBAC鉴权、准入控制,再加审计日志完成安全闭环;
- 认证解决"你是谁",分为外部普通用户(证书、令牌)、内部服务账号SA;
- RBAC区分命名空间级别Role和集群级别ClusterRole;绑定对象区分RoleBinding和ClusterRoleBinding;
- 新版本ServiceAccount使用短期Bound Token,废弃永久Secret令牌;
- K8s把用户身份交给外部系统,自身只做权限鉴权,便于企业集成。
环境清理
bash
kubectl delete ns auth