Kubernetes RBAC 认证机制

1. 简介与核心作用

RBAC(Role-Based Access Control)是 K8S 控制谁能对哪些资源执行什么操作的核心授权机制。

K8S 访问控制链路

plaintext

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        Kubernetes API Server                     │
├─────────────────────────────────────────────────────────────────┤
│   ┌──────────┐    ┌──────────────┐    ┌─────────────┐           │
│   │ Request  │───▶│ Authentication│───▶│ RBAC        │           │
│   │(User/SA) │    │ 身份认证      │    │ 授权检查    │           │
│   └──────────┘    └──────────────┘    └──────┬──────┘           │
│                                               │                  │
│                                       ┌───────▼───────┐         │
│                                       │ Admission     │         │
│                                       │ Controllers    │         │
│                                       └───────────────┘         │
└─────────────────────────────────────────────────────────────────┘

RBAC vs ABAC

表格

特性 RBAC ABAC
配置复杂度
权限粒度 角色+规则 属性+策略
K8S 推荐度 ✅ 生产首选 仅特殊场景

2. 核心资源对象详解

2.1 Role / ClusterRole

简介
  • Role:命名空间级权限
  • ClusterRole:集群级或所有命名空间权限
权限 verbs 分类

表格

类型 verbs
READ get, list, watch
WRITE create, update, patch, delete
SPECIAL escalate, bind, impersonate
YAML 示例

Role - 命名空间级只读

yaml

复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]

ClusterRole - 集群级只读

yaml

复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-reader
rules:
- apiGroups: [""]
  resources: ["pods", "services", "configmaps"]
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics", "/healthz"]
  verbs: ["get"]
常用命令

bash

复制代码
kubectl get clusterroles
kubectl get role pod-reader -n default -o yaml
kubectl describe role pod-reader -n default

2.2 RoleBinding / ClusterRoleBinding

简介
  • RoleBinding:将 Role/ClusterRole 绑定到用户/组/SA,作用于单个命名空间
  • ClusterRoleBinding:绑定到用户/组/SA,作用于整个集群
工作原理

plaintext

复制代码
┌─────────────────────────────────────────────────────────────┐
│                     RoleBinding                              │
├─────────────────────────────────────────────────────────────┤
│   subjects:                    roleRef:                     │
│   - kind: User                 - kind: Role                 │
│     name: john                 name: pod-reader             │
│   - kind: ServiceAccount       ────────────────────────▶ grants
│     name: my-sa                                          permissions
└─────────────────────────────────────────────────────────────┘
YAML 示例

RoleBinding - 绑定用户到 Role

yaml

复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: john-pod-reader
  namespace: default
subjects:
- kind: User
  name: john
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding - 绑定多个主体到 ClusterRole

yaml

复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-admin-binding
subjects:
- kind: User
  name: admin@example.com
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: devops-team
  apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
  name: ci-deployer
  namespace: ci-cd
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
常用命令

bash

复制代码
kubectl get rolebindings -n default
kubectl get rolebinding john-pod-reader -n default -o yaml
kubectl auth can-i --list --as=john
kubectl auth can-i get pods --as=john -n default

2.3 ServiceAccount

简介

ServiceAccount 是 Pod 的身份标识,用于 Pod 访问 API Server。

工作原理

plaintext

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                     ServiceAccount 认证流程                        │
├──────────────────────────────────────────────────────────────────┤
│   ┌─────────┐        ┌─────────────┐        ┌───────────────┐     │
│   │   Pod   │───────▶│ ServiceAcct │───────▶│  API Server   │     │
│   │         │ 挂载    │   Token     │ 持有    │  RBAC Check   │     │
│   └─────────┘ Token  └─────────────┘        └───────────────┘     │
│        │                                                          │
│        ▼ /var/run/secrets/kubernetes.io/serviceaccount/          │
│        ├── token      # JWT Token                                │
│        ├── namespace  # 命名空间名称                              │
│        └── ca.crt     # API Server CA                            │
└──────────────────────────────────────────────────────────────────┘
YAML 示例

创建 ServiceAccount

yaml

复制代码
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: production
automountToken: false  # 禁用自动挂载

Pod 使用 ServiceAccount

yaml

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: production
spec:
  serviceAccountName: my-app-sa
  containers:
  - name: app
    image: my-app:latest
常用命令

bash

复制代码
kubectl get serviceaccounts -n production
kubectl get sa my-app-sa -n production -o yaml
# 获取 SA 的 JWT Token
kubectl get secret $(kubectl get sa my-app-sa -n production \
  -o jsonpath='{.secrets[0].name}') -n production \
  -o jsonpath='{.data.token}' | base64 -d

3. 工作原理与请求链路

完整请求流程

plaintext

复制代码
┌────────────────────────────────────────────────────────────────────────────┐
│                              RBAC 授权流程                                    │
├────────────────────────────────────────────────────────────────────────────┤
│   1. Request ──▶ GET /api/v1/namespaces/default/pods                       │
│                  Authorization: Bearer xxx                                   │
│                           │                                                  │
│                           ▼                                                  │
│   2. Authentication ──▶ 验证证书/Token ──▶ 提取: username, uid, groups     │
│                           │                                                  │
│                           ▼                                                  │
│   3. RBAC Authorization                                                   │
│      ① 收集所有 RoleBinding/ClusterRoleBinding (含该用户)                   │
│      ② 获取关联的 Role/ClusterRole                                          │
│      ③ 检查 verbs 是否匹配 requested verb                                  │
│      ④ 检查 resources/apiGroups 是否匹配                                   │
│      ⑤ 检查 namespace 范围                                                  │
│                           │                                                  │
│                           ▼                                                  │
│   4. 决策结果                                                               │
│      ✓ 匹配到规则 ──▶ 允许访问 (200)                                        │
│      ✗ 无匹配规则 ──▶ 拒绝访问 (403 Forbidden)                              │
└────────────────────────────────────────────────────────────────────────────┘

4. 实战 YAML 配置

场景 1:最小权限只读用户

yaml

复制代码
---
# 定义只读 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: readonly-all-namespaces
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch"]
---
# 绑定到用户
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: readonly-user-binding
subjects:
- kind: User
  name: readonly-user
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: readonly-all-namespaces
  apiGroup: rbac.authorization.k8s.io

场景 2:开发者命名空间权限

yaml

复制代码
---
# 命名空间读写权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: developer-role
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets"]
  verbs: ["*"]
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["*"]
---
# 绑定到用户组
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-team-binding
  namespace: dev
subjects:
- kind: Group
  name: dev-team
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer-role
  apiGroup: rbac.authorization.k8s.io
---
# 其他命名空间只读
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dev-team-readonly
subjects:
- kind: Group
  name: dev-team
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

场景 3:Pod 访问 API 的 ServiceAccount

yaml

复制代码
---
# 创建 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: monitoring
---
# 创建 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus-metrics-reader
rules:
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
- apiGroups: [""]
  resources: ["nodes/metrics", "nodes/proxy"]
  verbs: ["get"]
---
# 绑定 SA 到 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus-metrics-binding
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: monitoring
roleRef:
  kind: ClusterRole
  name: prometheus-metrics-reader
  apiGroup: rbac.authorization.k8s.io
---
# Deployment 使用 SA
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      serviceAccountName: prometheus
      containers:
      - name: prometheus
        image: prom/prometheus:latest

场景 4:ClusterRole 聚合

yaml

复制代码
---
# 定义聚合角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: base-read
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-base-read: "true"
rules: []  # 由聚合自动填充
---
# 实现层:Pods 只读
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: base-read-pods
  labels:
    rbac.example.com/aggregate-to-base-read: "true"
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
# 实现层:日志读取
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: base-read-logs
  labels:
    rbac.example.com/aggregate-to-base-read: "true"
rules:
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]

场景 5:常用内置 ClusterRole

表格

ClusterRole 说明 使用场景
cluster-admin 完全控制 管理员
admin 命名空间全部权限 命名空间所有者
edit 命名空间读写 开发者
view 命名空间只读 观察者

yaml

复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-edit
  namespace: dev
subjects:
- kind: User
  name: developer@example.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: edit
  apiGroup: rbac.authorization.k8s.io

场景 6:跨命名空间 ServiceAccount

需求ci-cd 命名空间的 CI Deployer 需要操作 production 的 Deployment

yaml

复制代码
---
# 创建 CI CD ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ci-deployer
  namespace: ci-cd
---
# 定义权限(在 production 命名空间)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: ci-deployer-role
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
---
# 跨命名空间绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ci-deployer-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: ci-deployer
  namespace: ci-cd  # 从 ci-cd 引用
roleRef:
  kind: Role
  name: ci-deployer-role
  apiGroup: rbac.authorization.k8s.io

5. 常用操作命令

权限查看与测试

bash

复制代码
# 权限测试
kubectl auth can-i get pods
kubectl auth can-i create pods -n dev
kubectl auth can-i delete deployments -n prod

# 模拟其他用户
kubectl auth can-i get pods --as=john -n default
kubectl auth can-i --list --as=john

# 模拟 SA
kubectl auth can-i --list --as=system:serviceaccount:monitoring:prometheus

# 查看用户身份
kubectl auth whoami

资源查询

bash

复制代码
kubectl get clusterroles
kubectl get clusterrole admin -o yaml
kubectl get rolebindings --all-namespaces -o wide

6. 常见问题与排查

问题 1:权限不足 403

症状

plaintext

复制代码
Error from server (Forbidden): pods is forbidden: User "john" 
cannot list resource "pods" in API group "" in the namespace "default"

排查步骤

bash

复制代码
# 1. 确认用户身份
kubectl auth whoami

# 2. 测试权限
kubectl auth can-i get pods --as=john -n default
kubectl auth can-i list pods --as=john -n default

# 3. 检查绑定
kubectl get rolebindings -n default --as=john
kubectl describe rolebinding -n default | grep -A5 "john"

# 4. 检查 Role 定义
kubectl get role <role-name> -n default -o yaml

# 5. 确认 apiGroup
# 错误: apps 组资源使用 apiGroups: [""]
# 正确: Deployment 使用 apiGroups: ["apps"]

问题 2:ServiceAccount Token 不可用

症状:Pod 内 token 调用 API 失败

bash

复制代码
# 1. 检查 SA 存在
kubectl get sa -n production | grep my-app

# 2. 验证 token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -k -H "Authorization: Bearer $TOKEN" \
  https://kubernetes.default.svc/api/v1/namespaces/production/pods

# 3. 检查 token 过期
kubectl get secret <secret-name> -n production \
  -o jsonpath='{.data.token}' | base64 -d | cut -d. -f2 | base64 -d

解决方案:删除 SA 自动重建

bash

复制代码
kubectl delete sa my-app-sa -n production

问题 3:RoleBinding 绑错命名空间

排查

bash

复制代码
# 查看各命名空间权限
for ns in $(kubectl get ns -o name | cut -d/ -f2); do
  echo "=== $ns ==="
  kubectl auth can-i get pods --as=john -n $ns
done

# 检查绑定关系
kubectl get rolebindings --all-namespaces -o wide | grep john

解决方案:使用 ClusterRoleBinding 作用于所有命名空间

7. 最佳实践

安全配置

  • 最小权限原则 :避免 * 通配符,只授予必需权限
  • 区分用户类型:Human → User/Group,Pod → ServiceAccount
  • 禁用匿名访问--anonymous-auth=false
  • 禁用 SA 自动挂载 :设置 automountToken: false

权限设计

plaintext

复制代码
ClusterRoleBinding ──▶ ClusterRole ──▶ 集群级/所有NS
       │
       └── RoleBinding ──▶ Role ──▶ 单NS资源
  • 使用 Role + RoleBinding 管理 NS 级权限
  • ClusterRole + RoleBinding 授予集群范围只读
  • ClusterRoleBinding 仅用于管理员和特殊权限

操作规范

  • 权限变更需审批:通过 GitOps/CD 管理 RBAC 资源
  • 定期审计 :使用 kubectl auth can-i --list 审计权限
  • 命名规范 :Role <用途>-role,RoleBinding <主体>-<角色>-binding

故障排查清单

  1. kubectl auth whoami 确认身份
  2. kubectl auth can-i <verb> <resource> 测试权限
  3. ✅ 检查 RoleBinding subjects + roleRef
  4. ✅ 验证 apiGroups / resources / verbs 匹配
  5. ✅ 确认 namespace 作用范围

附录

表格

资源 作用域 用途
Role 单 NS 定义 NS 内权限
ClusterRole 集群/所有 NS 集群级权限或聚合
RoleBinding 单 NS 绑定 Role 到主体
ClusterRoleBinding 集群 绑定 ClusterRole 到主体

表格

verbs 含义
get/list/watch 只读
create/update/patch 写入
delete 删除
escalate/bind/impersonate 特权(需显式授予)

SA Token 路径/var/run/secrets/kubernetes.io/serviceaccount/

  • token:JWT Token
  • namespace:命名空间名
  • ca.crt:API Server CA 证书
相关推荐
humcomm1 小时前
云原生技术的未来发展趋势是什么(2026年4月)
云原生
岳来1 小时前
k8s pod 重启策略RestartPolicy 学习
容器·kubernetes·pod·restartpolicy
曾庆睿2 小时前
【基于 RHEL 9.3 的 K8s + GitLab 全自动化部署环境搭建第一篇】
kubernetes·自动化·gitlab
曾庆睿2 小时前
【基于 RHEL 9.3 的 K8s + GitLab 全自动化部署环境搭建第二篇】
kubernetes·自动化·gitlab
不恋水的雨4 小时前
docker安装clickhouse数据库容器
clickhouse·docker·容器
炸炸鱼.4 小时前
Docker 高级管理:Compose 容器编排与私有仓库实战
云原生·eureka
步步为营DotNet5 小时前
深入探究.NET 11中的 Native AOT 性能优化与实践
安全·云原生·.net
脑子加油站5 小时前
K8S-RBAC认证中心
云原生·容器·kubernetes·rbac认证
Cat_Rocky5 小时前
K8s RBAC认证 简单讲
java·docker·kubernetes