【k8s】集群安全机制(二):鉴权

本专栏文章持续更新,新增内容使用蓝色表示。

在上一篇博客中,介绍了 Kubernetes 的**认证(Authentication)**机制。

【k8s】集群安全机制(一):认证-CSDN博客

认证只是确定了通信双方是可信的,可以建立连接。但这还不够------我们还需要确定:"这个可信的请求方,具体能做什么?"

这就是 授权(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 单个命名空间 RoleClusterRole 的权限授予给特定的用户、组或服务账户。生效范围限于单个命名空间。
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:超级用户权限,对整个集群拥有完全控制。


如有问题或建议,欢迎在评论区中留言~

相关推荐
智算菩萨2 小时前
2025通用ChatGPT Agent架构综述:从工具调用、工作流编排到可观测与安全闭环
安全·chatgpt·架构
A13247053122 小时前
SSH远程连接入门:安全高效地管理服务器
linux·运维·服务器·网络·chrome·github
zz-zjx2 小时前
Kubernetes 的部署方式 (一)通过 Minikube 部署
云原生·容器·kubernetes
德迅云安全-小潘2 小时前
网络威胁演变与态势感知的防御
安全·web安全
yenggd3 小时前
企业总部-分支-门点-数据中心使用骨干网SRv6 BE互联互通整体架构配置案例
运维·网络·计算机网络·华为·架构
Hello.Reader3 小时前
Flink SQL CALL 语句调用存储过程做数据操作与运维任务(含 Java 示例 + 避坑指南)
运维·sql·flink
阿豪学编程3 小时前
【Linux】进程间通信(IPC):从管道到共享内存
linux·运维·服务器
qq7590353663 小时前
docker一键部署网页版Win11系统
运维·docker·容器
Joren的学习记录3 小时前
【Linux运维大神系列】docker详解(三)
linux·运维·docker