【云原生】RBAC授权详解

使用 RBAC签权

文章目录

一、RBAC介绍

1.1、介绍

基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。

RBAC签权机制使用rbac.authorization.k8s.ioAPI(Kubernetes API中的一组相关路径)组来驱动签权决定,允许你通过Kubernetes API动态配置策略。

1.2、RBAC四种对象

RBAC API声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding和ClusterRoleBinding 。你可以像使用其他 Kubernetes 对象一样,通过类似kubectl这类工具描述或修补 RBAC 对象

  • 注意*:这些对象在设计即实施了一些访问限制。如果你在学习过程中对集群做了更改,请避免特权提升

二、Role和ClusterRole

RBAC的RoleClusterRole中包含一组代表相关权限的规则。这些权限是纯碎累加的(不存在拒绝某些操作的规则)。

Role总是用来在某个名称空间内设置访问权限;在你创建Role时,你必须指定该Role所属的名称空间。

与之相对,ClustreRole则是一个集群作用域的资源。这两种资源的名称不同(Role和ClusterRole)是因为 Kubernetes 对象要么是名称空间作用域的,要么是集群作用域,不可两者兼具。

ClusterRole 若干用法。你可以用它来:

  • (1)、定义对某名称空间域对象的访问权限,并将名称空间内被授予访问权限;
  • (2)、名称空间作用域的对象设置访问权限,并将授予跨所有名称空间的访问权限;
  • (3)、为集群作用域的资源定义访问权限。

如果你希望在名称空间内角色,应该使用Role;如果你希望定义集群范围的角色,应该使用ClusterRole。

三、RoleBinding和ClusterRoleBinding

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。它包含若干主体(Subject) (用户、组或服务账户)的列表和对这些主体所获得的角色的引用。RoleBinding在指定的名称空间中执行授权,而ClusterRoleBinding在集群范围执行授权。

一个RoleBinding可以引用同一的名称空间中的任何Role。或者,一个RoleBinding可以引用某ClusterRole并将该ClusterRole绑定到RoleBinding所在的名称空间。如果你希望将某ClusterRole绑定到集群中所有名称空间,你要是用ClusterRoleBinding。

RoleBindimg或ClusterRoleBinding对象的名称必须是合法的路径分段名称

四、示例Role

4.1、创建Kubernetes用户

  • 创建 Kubernetes 的wzh1账号
bash 复制代码
# 进去 Kubernetes 的公钥设施文件夹
[root@master ~]# cd /etc/kubernetes/pki/


# 生成 wzh  认证证书
[root@master pki]# openssl genrsa -out wzh1.key 2048
[root@master pki]# openssl req -new -key wzh1.key -out wzh1.csr -subj "/CN=wzh1"
[root@master pki]# openssl x509 -req -in wzh1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out wzh1.crt -days 3650


# 将 wzh1 账户加入Kubernetes
[root@master pki]# kubectl config set-credentials wzh1 --client-certificate=./wzh1.crt --client-key=./wzh1.key --embed-certs=true 
[root@master pki]# kubectl config set-context wzh1@kubernetes --cluster=kubernetes --user=wzh1
bash 复制代码
# 查看 Kubernetes Config
[root@master pki]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.93.145:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
#####################################################
- context:
    cluster: kubernetes
    user: wzh1
  name: wzh1@kubernetes
#####################################################
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: wzh1
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

4.2、Role示例

  • 下面是一个位于default名称空间的Role的示例,可以用来授予对Pod的读访问权限:
bash 复制代码
[root@master rbac]# cat role.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"  
kind: Role  # 创建的资源类型
metadata:
  namespace: default  # 这个Role将使用与default名称空间中
  name: pod-reader
rules:   # 规则
- apiGroups: [""] # "" 标明核心组  core API(不用纠结什么意思)
  resources: ["pods"]  # 指定权限使用的资源类型为Pod,适用的资源要写全称,可以通过kubectl api-resources  查看NAME字段,就是资源的全称
  verbs: ["get","watch","list"] # 指定可以对指定资源执行的操作
bash 复制代码
# 加载资源
[root@master rbac]# kubectl apply -f role.yaml 
role.rbac.authorization.k8s.io/pod-reader created
bash 复制代码
# 查看 Role 角色创建情况
[root@master rbac]# kubectl get role pod-reader 
NAME         CREATED AT
pod-reader   2024-08-19T00:54:42Z

4.3、RoleBinding

  • 下面的例子中的 RoleBinding将"pod-reader" Role授予在"default"名称空间中的用户"wzh1".这样,用户"wzh1"就具有了读取"default"名称空间中所有Pod的权限。
bash 复制代码
[root@master rbac]# cat rolebinding.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"
# 此角色绑定运行 "wzh1" 用户读取 "default" 名称空间中的Pod
# 你需要在该名称空间中又有一个名为"pod-reader"的 Role
kind: RoleBinding   # 创建的类型
metadata:
  name: read-pods
  namespace: default  # 与Role保持同一名称空间即可
subjects:  
# 你可以指定不止一个"subject(主体)"
- kind: User  # 创建的是用户类型(User)
  name: wzh1   # 需要绑定的用户
  apiGroup: rbac.authorization.k8s.io  # 不用纠结这个字段
roleRef:   # 指定与某Role 或 ClusterRole的绑定关系
  kind: Role   # 此字段必须是Role 或 ClusterRole
  name: pod-reader    # 此字段必须要与你绑定的Role 或 ClusterRole的名称匹配
  apiGroup: rbac.authorization.k8s.io
bash 复制代码
# 加载资源
[root@master rbac]# kubectl apply -f rolebinding.yaml 
rolebinding.rbac.authorization.k8s.io/read-pods created

4.4、验证

bash 复制代码
# 切换到Kubernetes的wzh1用户
[root@master rbac]# kubectl config use-context wzh1@kubernetes 
Switched to context "wzh1@kubernetes".
bash 复制代码
# 查看 default 中的Pod
# 通过以下可以看出,是可以访问 default 名称空间中的 Pod 的,只是该名称空间下没有Pod
[root@master rbac]# kubectl get pod -n default
No resources found in default namespace.
bash 复制代码
# 做一些没有赋予权限的操作将会报错,比如使用wzh1用户查看默认名称空间service资源
[root@master rbac]# kubectl get service -n default
Error from server (Forbidden): services is forbidden: User "wzh1" cannot list resource "services" in API group "" in the namespace "default"

4.5、退回管理员权限用户

bash 复制代码
[root@master rbac]# kubectl config use-context kubernetes-admin@kubernetes 
Switched to context "kubernetes-admin@kubernetes".

五、示例ClusterRole

  • ClusterRole同样可以用于授予Role能够授予的权限。因为ClusterRole属于集群范围,所以它可以为以下资源授予访问权限:
    • 集群范围资源(比如节点(Node))
    • 非资源端点(比如/healthz)
    • 跨名称空间访问的名称空间作用域的资源(如Pod)
      • 比如,你可以使用ClusterRole来允许某特定用户指定kubectl get pod -A

5.2、创建Kubernetes用户

  • 创建 Kubernetes 的wzh2账号
bash 复制代码
# 进去 Kubernetes 的公钥设施文件夹
[root@master ~]# cd /etc/kubernetes/pki/


# 生成 wzh2  认证证书
[root@master pki]# openssl genrsa -out wzh2.key 2048
[root@master pki]# openssl req -new -key wzh2.key -out wzh2.csr -subj "/CN=wzh2"
[root@master pki]# openssl x509 -req -in wzh2.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out wzh2.crt -days 3650


# 将 wzh 账户加入Kubernetes
[root@master pki]# kubectl config set-credentials wzh2 --client-certificate=./wzh2.crt --client-key=./wzh2.key --embed-certs=true 
[root@master pki]# kubectl config set-context wzh2@kubernetes --cluster=kubernetes --user=wzh2
bash 复制代码
# 查看 Kubernetes Config
[root@master pki]# kubectl config view 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.93.145:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: kubernetes
    user: wzh1
  name: wzh1@kubernetes
#####################################################
- context:
    cluster: kubernetes
    user: wzh2
  name: wzh2@kubernetes
#####################################################
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: wzh1
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: wzh2
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

5.3、ClusterRole示例

  • 下面是一个ClusterRole的示例,可用来为任意一特定名称空间中的Secret授予读访问权限,或者跨名称空间的访问权限(取决于该角色是如何绑定的):
bash 复制代码
[root@master pki]# cat clusterrole.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"
kind: ClusterRole  # 创建的资源类型
metadata: 
  # "namespace" 被忽略,因为 ClusterRole 不受名称空间限制
  name: secret-reader  
rules:  # 规则
- apiGroups: [""]  # 核心组,不用纠结这个字段
  # 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
  resources: ["secrets"]  # 可以操作的资源对象
  verbs: ["get","watch","list"]  # 可以做使用kubectl对secret做的操作
bash 复制代码
# 加载资源
[root@master pki]# kubectl apply -f clusterrole.yaml 
clusterrole.rbac.authorization.k8s.io/secret-reader created
bash 复制代码
# 查看 ClusterRole 角色创建情况
[root@master pki]# kubectl get clusterrole secret-reader 
NAME            CREATED AT
secret-reader   2024-08-19T01:31:49Z

5.3、ClusterRoleBinding

  • 要跨整个集群访问全新啊的授予,你可以使用一个ClusterRoleBinding。下面的ClusterRoleBinding允许"wzh2"用户访问任何名称空间中的Secret。
bash 复制代码
[root@master pki]# cat clusterrolebinding.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"
# 此集群角色绑定允许 "wzh2"用户访问任何名称空间中的Secret资源
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: User  # 用户类型为(User)
  name: wzh2  # 此允许必须存在
  apiGroup: rbac.authorization.k8s.io
roleRef:   # 指定引用的角色资源
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io
bash 复制代码
# 加载资源
[root@master pki]# kubectl apply -f clusterrolebinding.yaml 
clusterrolebinding.rbac.authorization.k8s.io/read-secrets-global created

5.4、验证

bash 复制代码
# 切换到Kubernetes的wzh2用户
[root@master pki]# kubectl config use-context wzh2@kubernetes 
Switched to context "wzh2@kubernetes".
bash 复制代码
# 查看ClusterRole角色中运行查看的资源
# ClusterRole 针对的是全局的的权限,也就是集群,可以看到集群所有Secret资源
[root@master pki]# kubectl get secret -A
NAMESPACE         NAME                                             TYPE                                  DATA   AGE
default           default-token-9vp59                              kubernetes.io/service-account-token   3      19d
kube-flannel      default-token-x4r9d                              kubernetes.io/service-account-token   3      19d
kube-flannel      flannel-token-kjfjp                              kubernetes.io/service-account-token   3      19d
kube-node-lease   default-token-nwgqw                              kubernetes.io/service-account-token   3      19d
...
bash 复制代码
# 查看别的资源将会报错
[root@master pki]# kubectl get pod -A
Error from server (Forbidden): pods is forbidden: User "wzh2" cannot list resource "pods" in API group "" at the cluster scope

六、删除资源的要求

  • 创建绑定之后,你不能再修改绑定对象所引用的Role或ClusterRole。试图改变绑定对象的roleRef将导致合法性检查错误。如果你想要改变现有绑定对象中的roleRef字段的内容,必须删除重新创建绑定对象

七、扩展1

7.1、对资源的引用

  • 在Kubernetes API中,大多数资源都是使用对象名称的资源串表示来呈现与访问的。例如,对于Pod应用使用"Pods"。RBAC使用对应的API端点的URL中呈现的名称来引用资源。有一些Kubernetes API涉及子资源(subresource),例如Pod的日志。对于Pod的日志请求看起来像这样:
bash 复制代码
GET /api/v1/namespaces/{namespace}/pods/{name}/log
  • 在这里,Pods对应的名称空间作用域的Pod资源,而logpogs的子资源。在RBAC角色表达子资源时,使用斜线(/)来分隔资源和子资源。要么允许某主体读取pods同时访问这些Pod的log子资源,你可以这样写:
bash 复制代码
# 你可以把以上的所有资源删除,来进行以下的验证
[root@master rbac]# cat role.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"  
kind: Role 
metadata:
  namespace: default  
  name: pod-reader
rules:   
- apiGroups: [""] 
  resources: ["pods","pods/log"]  
  verbs: ["get","watch","list"]


# 最终可以实现以下效果
[root@master rbac]# kubectl logs nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
  • 对于某些请求,也可以通过resourceNames列表按名称引用资源。在指定时,可以将请求限定为资源的单个实例。下面的例子中限制可以getupdate一个名为my-configmap1的Config Map。
bash 复制代码
# 创建两个ConfingMap
[root@master rbac]# kubectl create configmap my-configmap1
[root@master rbac]# kubectl create configmap my-configmap2
bash 复制代码
[root@master rbac]# cat role.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"  
kind: Role 
metadata:
  namespace: default  
  name: pod-reader
rules:   
- apiGroups: [""] 
  resources: ["configmaps"]
  resourceNames: ["my-configmap1"]  # 只能在defalut名称空间中查看名为my-configmaop1的ConfigMap 
  verbs: ["get","watch","list"]
bash 复制代码
# 进行RoleBinding之后可以实现以下效果
  
# 有权限可以查看 my-configmap1
[root@master rbac]# kubectl get configmap my-configmap1
NAME            DATA   AGE
my-configmap1   0      2m1s


# 没有权限查看 my-configmap2
[root@master rbac]# kubectl get configmap my-configmap2
Error from server (Forbidden): configmaps "my-configmap2" is forbidden: User "wzh1" cannot get resource "configmaps" in API group "" in the namespace "default"

八、扩展2

8.1、RoleBinding也可以引用ClusterRole,

  • 以将对应ClusterRole中定义的访问权限授予RoleBind所在的名称空间的资源。这种引用是的你跨整个集群定义一组通用的角色,之后在多个名称空间中复用即可。

  • 例如:尽管下面的RoleBinding引用的是一个ClusterRole,"wzh1"(这里的主体,(User用户))只能访问"development"名称空间中的Secret对象,因为RoleBinding所在的名称空间(由其metadata决定)是"developemtn"。

bash 复制代码
# 创建 ClusterRole角色
[root@master rbac]# cat clusterrole.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"
kind: ClusterRole  # 创建的资源类型
metadata: 
  # "namespace" 被忽略,因为 ClusterRole 不受名称空间限制
  name: secret-reader  
rules:  # 规则
- apiGroups: [""]  # 核心组,不用纠结这个字段
  # 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
  resources: ["secrets"]  # 可以操作的资源对象
  verbs: ["get","watch","list"]  # 可以做使用kubectl对secret做的操作
bash 复制代码
# 创建 RoleBinding
[root@master rbac]# cat rolebinding.yaml 
apiVersion: "rbac.authorization.k8s.io/v1"
# 此角色绑定运行 "wzh1" 用户读取 "development" 名称空间中的Secret
# 你需要在该名称空间中又有一个名为"secret-reader"的 ClusterRole
kind: RoleBinding   # 创建的类型
metadata:
  name: read-secrets
  namespace: development  # RoleBinding的名称空间决定了访问权限的授予范围
subjects:  
# 你可以指定不止一个"subject(主体)"
- kind: User  # 创建的是用户类型(User)
  name: wzh1   # 需要绑定的用户
  apiGroup: rbac.authorization.k8s.io  # 不用纠结这个字段
roleRef:   # 指定与某Role 或 ClusterRole的绑定关系
  kind: ClusterRole   # 此字段必须是Role 或 ClusterRole
  name: secret-reader    # 此字段必须要与你绑定的Role 或 ClusterRole的名称匹配
  apiGroup: rbac.authorization.k8s.io
bash 复制代码
# 创建所需名称空间
[root@master rbac]# kubectl create namespace development
namespace/development created


# 加载资源
[root@master rbac]# kubectl apply -f clusterrole.yaml
[root@master rbac]# kubectl apply -f rolebinding.yaml 
bash 复制代码
# 验证
# 切换 wzh1 用户
[root@master rbac]# kubectl config use-context wzh1@kubernetes 
[root@master rbac]# kubectl get secrets -n development
NAME                  TYPE                                  DATA   AGE
default-token-sq4t8   kubernetes.io/service-account-token   3      106s


# 查看别的名称空间中的secret就会报错没有权限
[root@master rbac]# kubectl get secrets -n default
Error from server (Forbidden): secrets is forbidden: User "wzh1" cannot list resource "secrets" in API group "" in the namespace "default"
相关推荐
lagrahhn24 分钟前
无服务器计算简单介绍
云原生·云计算·无服务器
张3231 小时前
ConfigMap
云原生·kubernetes
东北甜妹2 小时前
Docker 命令
云原生·eureka
倔强的胖蚂蚁3 小时前
Ollama 大模型参数调整
运维·人工智能·云原生
鼎道开发者联盟3 小时前
OpenClaw在K8s Pod中稳定运行的Docker制作指南(源码版)
docker·k8s·openclaw
文静小土豆17 小时前
Java 应用上 K8s 全指南:从部署到治理的生产级实践
java·开发语言·kubernetes
努力搬砖的咸鱼18 小时前
Label 与 Selector:Kubernetes 资源选择的核心机制
微服务·云原生·容器·架构·kubernetes
Devin~Y1 天前
大厂Java面试实战:Spring Boot/WebFlux、Redis+Kafka、K8s可观测性与Spring AI RAG/Agent三轮连环问
java·spring boot·redis·kafka·kubernetes·resilience4j·spring webflux
立莹Sir1 天前
SaaS多租户资源隔离的云原生解决方案:在不单独部署的情况下实现租户级资源保障
云原生
密瓜智能1 天前
从 Device Plugin 到 DRA:GPU 调度范式升级与 HAMi-DRA 实践
人工智能·kubernetes·开源·密瓜智能