Kubernetes RBAC 权限控制
Kubernetes RBAC 权限控制
什么是 RBAC
RBAC(Role-Based Access Control,基于角色的访问控制)是 Kubernetes 集群安全的基石。在 Kubernetes 中,每一个对 API Server 的请求——无论是 kubectl get pods 还是 Pod 内部调用 Kubernetes API——都需要经过认证(Authentication)和授权(Authorization)两个阶段。
RBAC 解决的是授权问题:当系统确认"你是谁"之后,决定"你能做什么"。它通过以下四个核心资源实现精细化的权限控制:
| 资源类型 | 作用范围 | 说明 |
|---|---|---|
| Role | 命名空间 | 定义在特定命名空间内的权限规则 |
| ClusterRole | 集群全局 | 定义集群级别的权限规则,也可绑定到命名空间 |
| RoleBinding | 命名空间 | 将 Role 绑定到用户、组或 ServiceAccount |
| ClusterRoleBinding | 集群全局 | 将 ClusterRole 绑定到用户、组或 ServiceAccount |
为什么 RBAC 如此重要?在生产集群中,以下场景都需要正确的 RBAC 配置:
- CI/CD 流水线:部署服务时需要创建/更新 Deployment 的权限,但不能删除节点
- 开发人员:查看日志和 Pod 状态的权限,但不能修改生产配置
- 监控组件:读取 Pod 和 Node 指标的权限,但不能修改任何资源
- 安全合规:所有 API 访问可审计、可追溯,满足合规要求
RBAC 核心概念详解
API Group 与 Resource
理解 RBAC 的第一步是理解 Kubernetes 的 API 组织方式。Kubernetes API 按照组(apiGroup)进行组织:
# 常见的 API Group
# 核心组(apiVersion: v1)
resources: ["pods", "services", "configmaps", "secrets", "persistentvolumeclaims"]
# apps 组(apiVersion: apps/v1)
resources: ["deployments", "statefulsets", "daemonsets", "replicasets"]
# batch 组(apiVersion: batch/v1)
resources: ["jobs", "cronjobs"]
# networking.k8s.io 组(apiVersion: networking.k8s.io/v1)
resources: ["networkpolicies", "ingresses"]
# rbac.authorization.k8s.io 组
resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]在 RBAC 规则中,apiGroups 字段必须与资源的实际 API Group 匹配:
# 核心组的 apiGroups 写作空字符串 ""
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list"]
# apps 组必须显式指定
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch"]Verbs(操作动词)
RBAC 支持以下 verbs:
| Verb | 说明 |
|---|---|
| get | 获取单个资源 |
| list | 列出资源集合 |
| watch | 监听资源变更 |
| create | 创建资源 |
| update | 更新整个资源 |
| patch | 部分更新资源 |
| delete | 删除单个资源 |
| deletecollection | 批量删除资源 |
| exec | 在容器中执行命令 |
| port-forward | 端口转发 |
| proxy | API 代理 |
| bind | 绑定 Role/ClusterRole |
| escalate | 创建更高级别的 Role |
| * | 通配符,匹配所有动词 |
实战配置示例
命名空间级别的权限控制
# 只读角色:允许查看 Pod、Service 和 Deployment
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/status", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs", "cronjobs"]
verbs: ["get", "list"]
---
# 将只读角色绑定到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: production
subjects:
- kind: ServiceAccount
name: monitoring-agent
namespace: production
# 也可以绑定到用户或组
# - kind: User
# name: alice
# apiGroup: rbac.authorization.k8s.io
# - kind: Group
# name: dev-team
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io集群级别的权限控制
# 集群只读角色,适合运维人员查看资源
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-viewer
# 使用聚合规则自动合并内置的 view 角色
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules: [] # 规则由 aggregationRule 自动生成
---
# 集群管理员角色(谨慎使用)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: limited-admin
rules:
# 管理所有命名空间级别的资源
- apiGroups: ["", "apps", "batch", "networking.k8s.io"]
resources: ["*"]
verbs: ["*"]
# 只读节点信息
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
# 管理命名空间
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "watch", "create"]
# 不能管理集群级别的资源(如 ClusterRole、PersistentVolume、CSRs)CI/CD 流水线专用 ServiceAccount
# CI/CD 专用的 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: cicd-deployer
namespace: production
# 添加标签便于管理
labels:
managed-by: cicd
team: platform
---
# CI/CD 部署权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer-role
namespace: production
rules:
# 管理 Deployment(创建、更新、回滚、扩缩容)
- apiGroups: ["apps"]
resources: ["deployments", "deployments/scale", "deployments/status"]
verbs: ["get", "list", "watch", "create", "update", "patch", "rollback"]
# 查看 Pod 状态和日志(部署验证)
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/status"]
verbs: ["get", "list", "watch"]
# 管理 ConfigMap 和 Secret
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
# 管理 Service 和 Ingress
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
# 管理 HorizontalPodAutoscaler
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
# 绑定 ServiceAccount 到 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cicd-deployer-binding
namespace: production
subjects:
- kind: ServiceAccount
name: cicd-deployer
namespace: production
roleRef:
kind: Role
name: deployer-role
apiGroup: rbac.authorization.k8s.io为 Pod 配置 ServiceAccount
# Pod 使用特定 ServiceAccount
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
namespace: production
spec:
template:
spec:
serviceAccountName: cicd-deployer # 使用自定义 ServiceAccount
automountServiceAccountToken: true # 自动挂载 token
containers:
- name: app
image: myapp:v2.0
env:
- name: POD_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName禁用默认 ServiceAccount 的自动挂载
默认情况下,每个 Pod 都会自动挂载 default ServiceAccount 的 token。如果 Pod 不需要访问 Kubernetes API,应该禁用自动挂载以减少安全风险:
# 方法 1:在 Pod spec 中禁用
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
template:
spec:
automountServiceAccountToken: false # 禁用自动挂载
containers:
- name: app
image: myapp:latest
---
# 方法 2:在 ServiceAccount 上全局禁用
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: production
automountServiceAccountToken: false内置 ClusterRole
Kubernetes 提供了四个内置 ClusterRole,满足最常见的权限需求:
| ClusterRole | 说明 | 风险等级 |
|---|---|---|
| cluster-admin | 超级管理员,拥有所有权限 | 极高 |
| admin | 命名空间管理员,可以管理命名空间内所有资源 | 高 |
| edit | 可以编辑命名空间内资源,但不能管理 RBAC 和配额 | 中 |
| view | 只读访问,可以查看但不能修改任何资源 | 低 |
# 查看内置 ClusterRole 的详细规则
kubectl describe clusterrole view
kubectl describe clusterrole edit
kubectl describe clusterrole admin
kubectl describe clusterrole cluster-admin生产环境警告:绝对不要将 cluster-admin 绑定给非管理员用户或 ServiceAccount:
# 危险操作!永远不要这样做!
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dangerous-admin-binding
subjects:
- kind: ServiceAccount
name: default # 默认 ServiceAccount
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin # 超级管理员权限
apiGroup: rbac.authorization.k8s.io权限验证与审计
kubectl auth 命令
# 检查当前用户是否有权限
kubectl auth can-i list pods -n production
# 检查指定 ServiceAccount 是否有权限
kubectl auth can-i list pods \
--as=system:serviceaccount:production:monitoring-agent \
-n production
# 检查是否可以执行特定操作
kubectl auth can-i create deployments \
--as=system:serviceaccount:production:cicd-deployer \
-n production
# 检查是否可以删除节点(应该返回 no)
kubectl auth can-i delete nodes \
--as=system:serviceaccount:production:cicd-deployer
# 查看用户/ServiceAccount 的所有权限(使用 kubectl-who-can 插件)
kubectl who-can create deployments -n production
kubectl who-can delete secrets --all-namespaces
# 使用 rakkess 审计集群权限
# 项目:https://github.com/corneliusweig/rakkess
rakkess --namespace productionRBAC 审计清单
# 1. 列出所有 ClusterRoleBinding(检查是否有过度授权)
kubectl get clusterrolebindings -o wide
# 2. 查找绑定到 cluster-admin 的主体
kubectl get clusterrolebindings -o json | \
jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .subjects[]? | "\(.kind)/\(.name) (\(.namespace // "cluster"))"'
# 3. 查找绑定到 admin 的主体
kubectl get clusterrolebindings -o json | \
jq -r '.items[] | select(.roleRef.name=="admin") | .subjects[]? | "\(.kind)/\(.name) (\(.namespace // "cluster"))"'
# 4. 检查命名空间中 default ServiceAccount 是否被授予了额外权限
kubectl get rolebindings -A -o json | \
jq -r '.items[] | select(.subjects[]?.name=="default") | "\(.metadata.namespace)/\(.metadata.name) -> \(.roleRef.name)"'
# 5. 列出所有未使用的 ServiceAccount(没有被任何 RoleBinding 引用)
kubectl get serviceaccounts -A --no-headers | while read ns name; do
if ! kubectl get rolebindings,clusterrolebindings -A -o json 2>/dev/null | \
jq -e --arg sa "$name" '.items[].subjects[]? | select(.name==$sa)' > /dev/null 2>&1; then
echo "$ns/$name (unused)"
fi
done聚合 ClusterRole
聚合 ClusterRole 是一种强大的机制,可以将多个 ClusterRole 的规则自动合并到一个 ClusterRole 中:
# 自定义的只读角色,自动聚合所有标记为 "read-only" 的规则
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: custom-reader
labels:
rbac.authorization.k8s.io/aggregate-to-custom-reader: "true"
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.k8s.io/aggregate-to-custom-reader: "true"
rules: [] # 规则自动聚合
---
# 其他 ClusterRole 可以声明被聚合
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-resources-reader
labels:
rbac.authorization.k8s.io/aggregate-to-custom-reader: "true"
rules:
- apiGroups: ["monitoring.coreos.com"]
resources: ["servicemonitors", "podmonitors"]
verbs: ["get", "list", "watch"]RBAC 最佳实践
最小权限原则
# 好的实践:精确控制权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-resolver
namespace: cert-manager
rules:
- apiGroups: ["cert-manager.io"]
resources: ["challenges", "orders"]
verbs: ["get", "list", "watch", "create", "update"]
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["letsencrypt-prod", "letsencrypt-staging"] # 限制到特定 Secret
verbs: ["get"]
# 不好的实践:过度授权
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-resolver
namespace: cert-manager
rules:
- apiGroups: ["*"] # 所有 API Group
resources: ["*"] # 所有资源
verbs: ["*"] # 所有操作ServiceAccount Token 管理
# Kubernetes 1.24+ 默认不再自动创建 ServiceAccount token Secret
# 如果需要长期 token(如 CI/CD),手动创建
kubectl create token cicd-deployer \
--namespace=production \
--duration=87600h # 10 年有效期
# 短期 token(推荐)
kubectl create token cicd-deployer \
--namespace=production \
--duration=1h # 1 小时有效期在 CI/CD 中使用 kubeconfig
# 为 CI/CD 生成专用的 kubeconfig
# 1. 获取 ServiceAccount token
TOKEN=$(kubectl create token cicd-deployer -n production --duration=87600h)
# 2. 获取 API Server 地址
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
# 3. 获取 CA 证书
CA_CERT=$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
# 4. 生成 kubeconfig
cat > cicd-kubeconfig.yaml <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: ${CA_CERT}
server: ${APISERVER}
name: production
contexts:
- context:
cluster: production
user: cicd-deployer
name: cicd-production
current-context: cicd-production
users:
- name: cicd-deployer
user:
token: ${TOKEN}
EOF
# 5. 将 kubeconfig 存储为 CI/CD Secret
# GitHub Actions: Settings > Secrets > New repository secret
# GitLab CI: Settings > CI/CD > Variables优点
缺点
总结
RBAC 是 Kubernetes 集群安全的基石,每个生产集群都必须启用并严格配置。核心原则是最小权限:每个 ServiceAccount 只授予必需的权限,定期审计 RoleBinding 和 ClusterRoleBinding,避免过度授权。
关键原则:
- 最小权限:只授予完成任务所需的最小权限集
- 禁止 cluster-admin 泛滥:cluster-admin 只授予极少数的集群管理员
- ServiceAccount 隔离:每个服务使用独立的 ServiceAccount
- 定期审计:使用工具定期检查过度授权和废弃的 RoleBinding
- 版本控制:所有 RBAC 配置纳入 Git 管理
关键知识点
- RBAC 由 Role(定义权限)和 RoleBinding(绑定身份)两部分组成
- Role/RoleBinding 限制在命名空间内,ClusterRole/ClusterRoleBinding 作用于集群全局
- verbs 包括 get/list/watch/create/update/patch/delete/deletecollection
- ServiceAccount 是 Pod 访问 API Server 的身份凭证,通过 automountServiceAccountToken 自动挂载
- ClusterRole 可以通过 ClusterRoleBinding 绑定到全局,也可以通过 RoleBinding 绑定到命名空间
- 聚合 ClusterRole 允许通过标签选择器自动合并多个 ClusterRole 的规则
项目落地视角
- 为每个微服务创建独立的 ServiceAccount,按需授予最小权限
- CI/CD 流水线使用专用的 ServiceAccount 和 token,禁止使用管理员凭证
- 将 RBAC 配置纳入 Helm Chart 或 Kustomize 管理,随应用一起部署和审计
- 禁用不需要 API 访问的 Pod 的 automountServiceAccountToken
常见误区
- 给所有 ServiceAccount 授予 cluster-admin 权限图方便
- 忽略默认 ServiceAccount 的权限,以为 Pod 没有绑定 Role 就无法访问 API
- RoleBinding 引用了不存在的 ServiceAccount,导致权限静默失效
- 使用 apiGroups: ["*"] 授予所有 API Group 的权限
- 忘记 RBAC 的 verbs 区分大小写,写成了 "Get" 或 "List"
进阶路线
- 学习 Kubernetes 准入控制(Admission Controller)和 OPA/Gatekeeper 策略引擎
- 了解 ABAC(Attribute-Based Access Control)与 RBAC 的对比
- 掌握 Kubernetes 审计日志(Audit Log)配置,记录所有 API 访问行为
- 了解 Kyverno 的 RBAC 自动生成和策略管理能力
适用场景
- 多团队共享集群,需要按命名空间和资源类型隔离权限
- CI/CD 流水线需要安全的 Kubernetes API 访问凭证
- 合规要求所有 API 访问需可审计、可追溯
- 需要限制第三方组件(如监控、日志采集)的 API 访问范围
落地建议
- 建立权限申请和审批流程,任何 RBAC 变更需经过安全评审
- 定期运行权限审计工具(如 kubectl-who-can、rakkess)检查过度授权
- 为生产环境禁用默认 ServiceAccount 的自动挂载 token
- 将所有 RBAC 配置纳入 Git 版本控制
排错清单
- 权限被拒绝时,用 kubectl auth can-i 验证具体操作是否被允许
- 检查 ServiceAccount 是否正确绑定到 Role,Role 的 rules 是否覆盖所需资源
- 确认 Pod 的 serviceAccountName 字段是否指向正确的 ServiceAccount
- 检查 apiGroups 是否正确(核心组写空字符串 "",其他组写完整名称)
- 确认 resourceNames 是否限制了特定资源的名称
复盘问题
- 当前集群中是否存在 cluster-admin 绑定给非管理员用户的情况?
- 每个服务的 ServiceAccount 权限是否都经过最小化审查?
- 上次 RBAC 审计是什么时候?是否有废弃的 RoleBinding 未清理?
- CI/CD 使用的 ServiceAccount token 是否设置了合理的有效期?
