本专栏文章持续更新,新增内容使用蓝色表示。
在上一篇博客中,介绍了 Kubernetes 的**认证(Authentication)**机制。
认证只是确定了通信双方是可信的,可以建立连接。但这还不够------我们还需要确定:"这个可信的请求方,具体能做什么?"
这就是 授权(Authorization) 要解决的问题。
一、授权策略概览
Kubernetes API Server 支持多种授权策略,可以通过启动参数 --authorization-mode 进行配置。目前主要有以下几种:
-
AlwaysDeny:拒绝所有请求,主要用于测试。
-
AlwaysAllow:允许所有请求。如果你的集群不需要授权流程(比如内部测试环境),可以使用此策略。
-
ABAC(Attribute-Based Access Control):基于属性的访问控制。管理员配置规则来匹配用户请求。优点是规则清晰简单,缺点是不便于批量管理。
-
Webhook:通过调用外部的 REST 服务来完成授权决策。
-
RBAC (Role-Based Access Control):基于角色的访问控制 ,这也是 Kubernetes 现行默认的授权策略。通过"角色"这一抽象层来批量管理用户权限,一个角色可以绑定多个用户,在规模化部署中优势明显。
二、RBAC
RBAC 之所以成为默认选择,主要和以下优势有关:
1)覆盖全面:对集群中的资源(如 Pods、Services)和非资源端点(如 /healthz)都能进行权限控制。
2)声明式 API:整个 RBAC 机制由几个标准的 Kubernetes API 对象(如 Role、RoleBinding)定义,可以像管理其他资源一样,使用 kubectl 或直接调用 API 来操作它们。
3)动态生效:权限的调整可以在运行时进行,无需重启 API Server。
2.1 资源对象
RBAC 机制引入了4个顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding,4种对象类型均可以通过 kubectl 与 API 操作。
| 对象 | 作用范围 | 说明 |
|---|---|---|
| Role | 单个命名空间 (Namespace) | 定义一组权限规则,权限只会叠加,不会减少。作用范围仅限于创建它的命名空间。 |
| ClusterRole | 集群级别 (Cluster-wide) | 定义集群级别的权限规则。可用于: 1. 集群资源(如 Nodes) 2. 非资源端点(如 /healthz) 3. 所有命名空间中的资源(如跨 Namespace 的 Pods) |
| RoleBinding | 单个命名空间 | 将 Role 或 ClusterRole 的权限授予给特定的用户、组或服务账户。生效范围限于单个命名空间。 |
| ClusterRoleBinding | 集群级别 | 将 ClusterRole 的权限授予给特定的用户Users、组Groups或服务账户ServiceAccount。生效范围为整个集群。 |
关键概念解析
1. 资源(Resources) 在 Kubernetes 中,资源通常以其名称字符串表示(如 pods, services),并出现在 API 路径中。有些资源还包含子资源(例如,logs 就是 pods 的子资源),对应的 API 路径类似:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
2. 主体(Subjects)
RoleBinding 和 ClusterRoleBinding 将角色绑定到主体。主体可以是:
-
Users:用户,通常由客户端证书中的 CN(Common Name)字段定义。格式可以是普通字符串(如 alice)或邮箱格式。system: 前缀是系统保留的。
-
Groups:组,通常由客户端证书中的 O(Organization)字段定义。格式同样是字符串,system: 前缀同样被保留。
-
ServiceAccounts:服务账户,是 Kubernetes 内部标识工作负载身份的主要方式。


2.2 清单示例
2.2.1 Role 角色
作用范围:单个命名空间内
bash
# role-dev.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev # 此 Role 仅在 dev 命名空间中生效
name: pod-reader
rules:
- apiGroups: [""] # 核心 API 组
resources: ["pods"] # 资源类型
verbs: ["get", "list", "watch"] # 允许的操作
2.2.2 ClusterRole 角色
作用范围:整个集群
bash
# clusterrole-global.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: global-pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# 此 ClusterRole 可以在所有命名空间中读取 Pods
bash
# clusterrole-non-resource.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: health-checker
rules:
- nonResourceURLs: ["/healthz", "/readyz"] # 非资源型端点
verbs: ["get"]
# 允许检查集群健康状态
2.2.3 RoleBinding + Role
场景:在特定命名空间中为用户/组/ServiceAccount 授权
bash
# rolebinding-dev.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-reader-binding
namespace: dev # 此绑定仅在 dev 命名空间生效
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader # 引用 dev 命名空间中的 Role
apiGroup: rbac.authorization.k8s.io
# 效果:用户 alice 在 dev 命名空间中有 pod-reader 权限
bash
# rolebinding-sa.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: monitoring-binding
namespace: monitoring
subjects:
- kind: ServiceAccount
name: prometheus-sa
namespace: monitoring # ServiceAccount 必须指定命名空间
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
# 效果:prometheus-sa 在 monitoring 命名空间中有 pod-reader 权限
2.2.4 RoleBinding + ClusterRole
场景:复用全局角色,在特定命名空间中授权
bash
# rolebinding-with-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-admin-binding
namespace: dev
subjects:
- kind: User
name: bob
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole # 引用集群级别的 ClusterRole
name: admin # 使用预置的 admin ClusterRole
apiGroup: rbac.authorization.k8s.io
# 效果:用户 bob 在 dev 命名空间中有 admin 权限
# 管理员可以创建一次 ClusterRole,在各个命名空间通过 RoleBinding 复用
2.2.5 ClusterRolebinding
场景:在整个集群范围内授权
bash
# clusterrolebinding-manager.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-secret-access
subjects:
- kind: Group
name: manager # 组名,通常来自证书的 O 字段
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader # 假设已创建此 ClusterRole
apiGroup: rbac.authorization.k8s.io
# 效果:manager 组中所有用户在所有命名空间都可以读取 Secrets
bash
# 对应的 secret-reader ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
【实验】为特定用户划分命名空间权限
目标:创建一个用户 devuser,使其只能管理 dev 命名空间内的资源。
思路:创建用户证书 -> 生成 kubeconfig -> 创建命名空间 -> 通过 RoleBinding 绑定权限。
建议操作目录:/etc/kubernetes/pki/(因为集群 CA 证书通常在此)。
bash
cd /etc/kubernetes/pki/
具体步骤
创建证书签名请求(CSR)
首先,定义用户的证书请求信息:
bash
cat > devuser-csr.json <<EOF
{
"CN": "devuser",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Shanghai",
"L": "Shanghai",
"O": "k8s",
"OU": "System"
}
]
}
EOF
下载并安装证书工具(cfssl)
bash
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson
生成用户证书
使用集群的 CA 为 devuser 签发证书:
bash
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes ./devuser-csr.json | cfssljson -bare devuser
可以发现生成了四个文件:devuser.pem(证书), devuser-key.pem(私钥), devuser.csr。
生成 kubeconfig 文件
bash
# 设置集群API Server地址
export KUBE_APISERVER="https://[API Server的IP地址]:6443"
# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig
# 设置用户凭据参数
kubectl config set-credentials devuser \
--client-certificate=devuser.pem \
--client-key=devuser-key.pem \
--embed-certs=true \
--kubeconfig=devuser.kubeconfig
# 设置上下文(指定用户、集群和默认命名空间)
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=devuser \
--namespace=dev \
--kubeconfig=devuser.kubeconfig
# 将新创建的上下文设置为默认
kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig
至此,devuser.kubeconfig 文件已生成,但用户还没有任何权限。
创建命名空间并绑定权限
bash
kubectl create ns dev
为 devuser 在 dev 命名空间内绑定一个预置的 admin 角色(这是一个 ClusterRole):
bash
# 创建 RoleBinding,授予 devuser 在 dev 命名空间内的 admin 权限
kubectl create rolebinding devuser-admin-binding \
--clusterrole=admin \
--user=devuser \
--namespace=dev
测试
kubectl 会默认寻找,当前用户家目录的 .kube/config 文件。
bash
# 方式一:指定 kubeconfig 文件
kubectl get pods --namespace=dev --kubeconfig=./devuser.kubeconfig
# 方式二:将 kubeconfig 拷贝到默认位置
mv ~/.kube/config ~/.kube/config.backup # 可以先备份原有配置,恢复时源和目标换一下
cp ./devuser.kubeconfig ~/.kube/config
kubectl get pods -n dev
kubectl get pods -n default # 这个命令应该会被拒绝,因为没有 default 命名空间的权限
三、补充
3.1 权限绑定速查表
| 资源目标 | 角色类型 | 绑定类型 |
|---|---|---|
| 集群级别资源(Nodes, PersistentVolumes, ...) | ClusterRole | ClusterRoleBinding |
| 非资源型 URL(/api, /healthz, ...) | ClusterRole | ClusterRoleBinding |
| 跨所有命名空间的资源 | ClusterRole | ClusterRoleBinding |
| 在具体某个命名空间中的资源(计划在多个命名空间复用此角色) | ClusterRole | RoleBinding |
| 在具体某个命名空间中的资源(角色无需复用) | Role | RoleBinding |
3.2 官方预设角色
Kubernetes 内置了许多实用的 ClusterRole,可直接使用以下命令进行查看:
bash
kubectl get clusterrole
常见的预设角色包括:
-
view:只读权限,适用于大多数资源,除了 Role、RoleBinding 和 Secret。
-
edit:允许读写修改资源,但不能查看或修改权限相关的资源,防止权限扩散。
-
admin:在命名空间内的完全控制权(包括授权)。
-
cluster-admin:超级用户权限,对整个集群拥有完全控制。
如有问题或建议,欢迎在评论区中留言~