K8S细粒度权限控制

K8S细粒度权限控制

Kubernetes 中的 RBAC(基于角色的访问控制,Role-Based Access Control) 是一种授权机制,用于管理和控制用户或服务账户在集群中对资源的访问权限。RBAC 在 Kubernetes 中通过角色(Role)和角色绑定(RoleBinding)来实现对不同资源的权限分配。

RBAC 的作用
  1. 细粒度的权限控制:RBAC 允许管理员为用户、组或服务账户定义细粒度的权限,包括对哪些资源有访问权限、可以执行哪些操作(如查看、创建、修改、删除等),从而避免过大的权限授予。
  2. 增强集群安全性:通过严格限制用户和应用程序的访问权限,RBAC 有助于减少安全风险,防止未经授权的访问和操作。例如,开发人员只被允许访问开发环境的命名空间,生产环境的命名空间可以限制访问。
  3. 支持多租户环境:在多租户 Kubernetes 集群中,不同的团队或应用共享同一个集群。RBAC 可以确保每个租户只能管理和访问自己所属的资源,保障数据隔离和资源隔离。
  4. 灵活的权限管理:RBAC 允许动态修改权限,管理员可以在需要时增加或减少用户的权限,确保权限可以随时调整以符合业务需求。
RBAC 的应用背景
  1. 多用户环境:在 Kubernetes 集群中,多个团队或用户需要共享同一个集群资源时,RBAC 用来确保每个用户只能访问和管理其职责范围内的资源。例如,运维团队需要访问所有命名空间,而开发团队可能只需要访问自己项目的命名空间。
  2. 服务账户权限管理:Kubernetes 中的应用程序通过服务账户(ServiceAccount)与 API 交互,RBAC 确保这些应用程序只能对其所需的资源进行操作,防止服务账户拥有过多权限。特别是在微服务架构中,服务之间的权限应该是隔离的,以防止一个服务对其他服务的资源进行不必要的操作。
  3. 合规性和审计要求:在某些合规性要求严格的行业,如金融或医疗,细粒度的权限控制和访问审计是必须的。RBAC 可以确保只有特定角色的用户可以访问敏感资源,保证符合合规性要求,并支持对用户行为进行审计。
  4. 生产环境的隔离:生产环境往往需要比开发和测试环境更严格的权限控制。RBAC 确保开发人员和测试人员无法在未经授权的情况下对生产环境的资源进行任何操作,减少生产事故的发生。
RBAC 的核心概念
  1. Role(角色)
    • 定义一组权限,指定对某类资源的允许操作(如 pods、services)。
    • 可以在特定的命名空间中使用(Role),也可以在整个集群范围内使用(ClusterRole)。
  2. RoleBinding(角色绑定)
    • 将一个 Role(或 ClusterRole)绑定到一个用户、组或服务账户,赋予它相应的权限。
    • 可以绑定到命名空间级别的 Role,或集群范围的 ClusterRole。
  3. ClusterRole(集群角色)
    • 类似于 Role,但作用于集群级别,适用于全局资源(如节点、集群角色等)、跨多个命名空间的资源访问(Pod)和非资源端点(/healthz)
  4. ClusterRoleBinding(集群角色绑定)
    • 将 ClusterRole 绑定到用户、组或服务账户,赋予其在整个集群范围的权限。

Role 和 ClusterRole

RBAC 的 RoleClusterRole 中包含一组代表相关权限的规则。 这些权限是纯粹累加的(不存在拒绝某操作的规则)。Role的应用场景针对命名空间,ClusterRole的应用场景针对整个集群。这两种资源的名字不同(Role 和 ClusterRole) 是因为 Kubernetes 对象要么是名字空间作用域的,要么是集群作用域的,不可两者兼具。

Role示例如下,授予对Pod的读访问权限。apiGroups一般为空

[root@master-01 ~]# cat role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader
rules:
- apiGroups: [""]  # "" 表示核心 API 组
  resources: ["pods"]
  verbs: [""]

ClusterRole示例如下,为任一特定名字空间中的 Secret 授予读访问权限, 或者跨名字空间的访问权限(取决于该角色是如何绑定的)

[root@master-01 ~]# cat clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
  name: secret-reader
rules:
- apiGroups: [""]
  # 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

RoleBinding 和 ClusterRoleBinding

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

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

Role Binding示例如下。,,,,,,,,,,,将 "pod-reader" Role 授予在 "default" 名字空间中的用户 "jane"。 这样,用户 "jane" 就具有了读取 "default" 名字空间中所有 Pod 的权限。

[root@master-01 ~]# cat rolebinding.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
#可以指定不止一个“subject(主体)”
subjects:
- kind: ServiceAccount
  name: caijx  # 这里指明服务账户名称
  namespace: default
## "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

由于1.24版本后,K8S在创建SA时,不会自动创建Token,需要读者手动创建

[root@master-01 ~]# kubectl create serviceaccount caijx
serviceaccount/caijx created
[root@master-01 ~]# kubectl create token caijx
eyJhbGciOiJSUzI1NiIsImtpZCI6Im5MSHM0SE9MX2ZRRTBDc29YOXJQYW9RLW1PVFd4cFZmX3dYVEN2M0g1azgifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzI5NzI2NjcwLCJpYXQiOjE3Mjk3MjMwNzAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiYjgwYjFlNTYtNjA0ZS00MDE4LTk1ODAtMjc4ZDRjZDVkZjc5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImNhaWp4IiwidWlkIjoiYmZhNjhiMGItMTZhNi00NTZkLTgxZmEtNTA5YTBmOTJkOGVjIn19LCJuYmYiOjE3Mjk3MjMwNzAsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmNhaWp4In0.j6MprBf8SwSLpEGavgBdKzTas79VKEmpUntPIjZD8kERwy2kyfCWJ4ZQHzp5L9JzO-ZNpU71YwdbQN4lXHvDmldg1X9rzscp1I6WJ1tx5qjAihbTQcftBKesDKTFLPkLFNDuNbExafbxhbFI_sBvTt2c8HQEfitwi3-irZWUsa-V8L_EOI1Iuoq0lBVq7m6ZYYcNzk80Hm03V2YQYdIxO2FyILtodYWYlQEriiKlg5F79KDKG0ZStjkcZ-j059XSDodGZGCuN666UrLW1JyzyNCHHBKyw0pWIilhkUUuY0Eqyv2dz-QgBVBaATTYflAWF86Bod_xJT5NkY8o-rLmGQ

在没有创建role和rolebinding资源的情况下,通过生成的Token登录dashboard界面进行验证,可以观察caijx用户无法查看default命名空间下的Pod资源

无法查看default空间下的Pod

创建role和rolebinding资源,并查看资源创建情况。重新登陆role和rolebinding资源,可以观察到caijx用户可以查看default命名空间下的Pod资源,但是仍然无法查看其他资源

[root@master-01 ~]# kubectl create -f role.yaml
role.rbac.authorization.k8s.io/pod-reader created
[root@master-01 ~]# kubectl describe role/pod-reader
Name:         pod-reader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get watch list]
[root@master-01 ~]# kubectl create -f rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/read-pods created
[root@master-01 ~]# kubectl describe rolebindings.rbac.authorization.k8s.io read-pods
Name:         read-pods
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  pod-reader
Subjects:
  Kind            Name   Namespace
  ----            ----   ---------
  ServiceAccount  caijx  default

查看Pod资源,无法查看其他资源

要跨整个集群完成访问权限的授予,可以使用 ClusterRoleBinding。 下面的 ClusterRoleBinding 允许 "manager" 组内的所有用户访问任何名字空间中的 Secret。

[root@master-01 ~]# cat grouprolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
# 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 Secret 资源
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager      # 'name' 是区分大小写的
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

读者需要限制某些资源下的字资源,可以用"/"进行分隔

[root@master-01 ~]# cat separation.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

读者可以通过 resourceNames 列表按名称引用资源。 在指定时,可以将请求限定为资源的单个实例。 下面的例子中限制可以 get 和 update 一个名为 my-configmap 的 ConfigMap

[root@master-01 ~]# cat limitindividual.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  # 在 HTTP 层面,用来访问 ConfigMap 资源的名称为 "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

可以使用通配符 批量引用所有的 resources、apiGroups 和 verbs 对象,无需逐一引用。 对于 nonResourceURLs,你可以将通配符 作为后缀实现全局通配, 对于 resourceNames,空集表示没有任何限制。 下面的示例对 example.com API 组中所有当前和未来资源执行所有动作。但是请读者注意,这样做并不安全, 通配符条目会自动授予访问权限,在实际生产环境当中,应该执行最小特权原则, 使用具体的 resources 和 verbs 确保仅赋予工作负载正常运行所需的权限

[root@master-01 ~]# cat wildcards.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: example.com-superuser # 此角色仅作示范,请勿使用
rules:
- apiGroups: ["example.com"]
  resources: ["*"]
  verbs: ["*"]

类似的,系统默认的cluster-admin也是使用这样的授权方式

[root@master-01 ~]# kubectl get clusterrole | grep cluster-admin
cluster-admin                                                          2024-10-14T06:01:52Z
[root@master-01 ~]# kubectl describe clusterrole cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]

聚合的 ClusterRole

将若干 ClusterRole 聚合(Aggregate) 起来,形成一个复合的 ClusterRole。 作为集群控制面的一部分,控制器会监视带有 aggregationRule 的 ClusterRole 对象集合。aggregationRule 为控制器定义一个标签选择算符供后者匹配应该组合到当前 ClusterRole 的 roles 字段中的 ClusterRole 对象。

创建聚合 ClusterRole

[root@master-01 ~]# cat polymerization.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true" # 未来需要匹配的标签
rules: [] # 控制面自动填充这里的规则

创建一个与某个已存在的聚合 ClusterRole 的标签选择算符匹配的 ClusterRole, 这一变化会触发新的规则被添加到聚合 ClusterRole 的操作。 下面的例子中,通过创建一个标签同样为 rbac.example.com/aggregate-to-monitoring: true`的 ClusterRole,新的规则可被添加到 "monitoring" ClusterRole 中

[root@master-01 ~]# cat crlabelmatch.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
# 当创建 "monitoring-endpoints" ClusterRole 时,
# 下面的规则会被添加到 "monitoring" ClusterRole 中
rules:
- apiGroups: [""]
  resources: ["services", "endpointslices", "pods"]
  verbs: ["get", "list", "watch"]

创建资源并查看资源状态。

[root@master-01 ~]# kubectl create -f polymerization.yaml
clusterrole.rbac.authorization.k8s.io/monitoring created
[root@master-01 ~]# kubectl get clusterrole/monitoring
NAME         CREATED AT
monitoring   2024-10-25T00:13:16Z
[root@master-01 ~]# kubectl describe clusterrole/monitoring
Name:         monitoring
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----

可以观察到,在创建第2个clusterrole后,由于标签匹配的缘故,此时第一个clusterrole也获取到了权限

[root@master-01 ~]# kubectl create -f rclabelmatch.yaml
clusterrole.rbac.authorization.k8s.io/monitoring-endpoints created
[root@master-01 ~]# kubectl describe clusterrole/monitoring
Name:         monitoring
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources       Non-Resource URLs  Resource Names  Verbs
  ---------       -----------------  --------------  -----
  endpointslices  []                 []              [get list watch]
  pods            []                 []              [get list watch]
  services        []                 []              [get list watch]
[root@master-01 ~]# kubectl describe clusterrole/monitoring-endpoints
Name:         monitoring-endpoints
Labels:       rbac.example.com/aggregate-to-monitoring=true
Annotations:  <none>
PolicyRule:
  Resources       Non-Resource URLs  Resource Names  Verbs
  ---------       -----------------  --------------  -----
  endpointslices  []                 []              [get list watch]
  pods            []                 []              [get list watch]
  services        []                 []              [get list watch]

将ClusterRole与SA caijx绑定

[root@master-01 ~]# kubectl create rolebinding test-aggregation --clusterrole=monitoring --serviceaccount=default:caijx
rolebinding.rbac.authorization.k8s.io/test-aggregation created
[root@master-01 ~]# kubectl get rolebindings test-aggregation
NAME               ROLE                     AGE
test-aggregation   ClusterRole/monitoring   17s
[root@master-01 ~]# kubectl describe rolebinding test-aggregation
Name:         test-aggregation
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  monitoring
Subjects:
  Kind            Name   Namespace
  ----            ----   ---------
  ServiceAccount  caijx  default

登录Dashboard。可以观察到当前caijx用户可以访问到SVC、Pod和Endpoints。但是仍然无法访问其他资源(右上角报错)

可查看svc,无法查看其他资源

读者如果需要查看其他Role示例,可以访问官网

https://kubernetes.io/docs/reference/access-authn-authz/rbac/
默认集群角色 默认集群角色绑定 说明
cluster-admin system:masters组 允许超级用户在平台上的任何资源上执行所有操作。 当在 ClusterRoleBinding 中使用时,可以授权对集群中以及所有名字空间中的全部资源进行完全控制。 当在 RoleBinding 中使用时,可以授权控制角色绑定所在名字空间中的所有资源,包括名字空间本身
admin 允许管理员访问权限,旨在使用 RoleBinding 在名字空间内执行授权。如果在 RoleBinding 中使用,则可授予对名字空间中的大多数资源的读/写权限, 包括创建角色和角色绑定的能力。 此角色不允许对资源配额或者名字空间本身进行写操作。 此角色也不允许对 Kubernetes v1.22+ 创建的 EndpointSlices(或 Endpoints)进行写操作
edit 允许对名字空间的大多数对象进行读/写操作。此角色不允许查看或者修改角色或者角色绑定。 不过,此角色可以访问 Secret,以名字空间中任何 ServiceAccount 的身份运行 Pod, 所以可以用来了解名字空间内所有服务账户的 API 访问级别。 此角色也不允许对 Kubernetes v1.22+ 创建的 EndpointSlices(或 Endpoints)进行写操作。
view 允许对名字空间的大多数对象有只读权限。 它不允许查看角色或角色绑定。此角色不允许查看 Secret,因为读取 Secret 的内容意味着可以访问名字空间中 ServiceAccount 的凭据信息,进而允许利用名字空间中任何 ServiceAccount 的身份访问 API(这是一种特权提升)。

下面的 ClusterRole 和 RoleBinding 将允许用户 user-1 把名字空间 user-1-namespace 中的 admin、edit 和 view 角色赋予其他用户

[root@master-01 ~]# cat authorization.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-grantor
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["rolebindings"]
  verbs: ["create"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["clusterroles"]
  verbs: ["bind"]
  # 忽略 resourceNames 意味着允许绑定任何 ClusterRole
  resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: role-grantor-binding
  namespace: user-1-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: user-1

命令行工具

kubectl create role

创建名称为 “pod-reader” 的 Role 对象,允许用户对 Pods 执行 get、watch 和 list 操作

[root@master-01 ~]# kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
role.rbac.authorization.k8s.io/pod-reader created

创建名称为 “pod-reader” 的 Role 对象并指定 resourceNames

[root@master-01 ~]# kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
role.rbac.authorization.k8s.io/pod-reader created

创建名为 “foo” 的 Role 对象并指定 apiGroups

[root@master-01 ~]# kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
role.rbac.authorization.k8s.io/foo created

创建名为 “foo” 的 Role 对象并指定子资源权限

[root@master-01 ~]# kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
role.rbac.authorization.k8s.io/foo created

创建名为 “my-component-lease-holder” 的 Role 对象,使其具有对特定名称的资源执行 get/update 的权限

[root@master-01 ~]# kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
role.rbac.authorization.k8s.io/my-component-lease-holder created

kubectl create clusterrole

创建名称为 “pod-reader” 的 ClusterRole 对象,允许用户对 Pods 对象执行 get、 watch 和 list 操作

[root@master-01 ~]# kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
clusterrole.rbac.authorization.k8s.io/pod-reader created

创建名为 “pod-reader” 的 ClusterRole 对象并指定 resourceNames

[root@master-01 ~]# kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
clusterrole.rbac.authorization.k8s.io/pod-reader created

创建名为 “foo” 的 ClusterRole 对象并指定 apiGroups

[root@master-01 ~]# kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
clusterrole.rbac.authorization.k8s.io/foo created

创建名为 “foo” 的 ClusterRole 对象并指定子资源

[root@master-01 ~]# kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
clusterrole.rbac.authorization.k8s.io/foo created

创建名为 “foo” 的 ClusterRole 对象并指定 nonResourceURL

[root@master-01 ~]# kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
clusterrole.rbac.authorization.k8s.io/foo created

创建名为 “monitoring” 的 ClusterRole 对象并指定 aggregationRule

[root@master-01 ~]# kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
clusterrole.rbac.authorization.k8s.io/monitoring created

kubectl create rolebinding

在名字空间 “acme” 中,将名为 admin 的 ClusterRole 中的权限授予名称 “bob” 的用户

kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme

在名字空间 “acme” 中,将名为 view 的 ClusterRole 中的权限授予名字空间 “acme” 中名为 myapp 的服务账户

kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme

在名字空间 “acme” 中,将名为 view 的 ClusterRole 对象中的权限授予名字空间 “myappnamespace” 中名称为 myapp 的服务账户

kubectl create rolebinding myappnamespace-myapp-view-binding --clusterrole=view --serviceaccount=myappnamespace:myapp --namespace=acme

kubectl create clusterrolebinding

在整个集群范围,将名为 cluster-admin 的 ClusterRole 中定义的权限授予名为 “root” 用户

kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root

在整个集群范围内,将名为 system:node-proxier 的 ClusterRole 的权限授予名为 “system:kube-proxy” 的用户

kubectl create clusterrolebinding kube-proxy-binding --clusterrole=system:node-proxier --user=system:kube-proxy

在整个集群范围内,将名为 view 的 ClusterRole 中定义的权限授予 “acme” 名字空间中名为 “myapp” 的服务账户

kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp

kubectl auth reconcile

kubectl auth reconcile 是一个用于在 Kubernetes 中同步权限资源的命令,它会根据指定的权限配置文件(如 Role、RoleBinding、ClusterRole 和 ClusterRoleBinding)来创建或更新集群中的权限资源,而不会删除现有的权限规则。

测试应用 RBAC 对象的清单文件,显示将要进行的更改

kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client

应用 RBAC 对象的清单文件,删除角色(roles)中的额外权限和绑定中的其他主体

kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions

RBAC企业实战

请读者思考,在企业内如果管理众多用户?是否每一个权限都需要创建一个Role或者ClusterRole,然后分配给对应的用户,并指定命名空间?如何对权限进行统一管理? 此处提出一个解决方案,创建一个新的命名空间,里面只存放需要授权的用户,对权限进行单独划分和创建,比如Pod的读取、Pod的写入、切换命名空间、日志的读写、Pod的删除等一系列的权限,对于全局的权限,创建ClusterRoleBinding,对于用户单独拥有的权限,创建RoleBinding指定绑定的命名空间。最终实现权限的细粒度划分。

权限细粒度划分

场景如下:用户moms可以查看default、kube-system下Pod的日志。用户caijx可以在default下的Pod中执行命令,并且可以删除Pod。

由于moms用户需要查看其它命名空间下的Pod日志,所以需要创建对应的查看命名空间的ClusterRole

[root@master-01 ~]# vim read-namespace.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: namespace-readonly
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
[root@master-01 ~]# kubectl create -f read-namespace.yaml
clusterrole.rbac.authorization.k8s.io/namespace-readonly created

创建权限为删除Pod的ClusterRole

[root@master-01 ~]# vim pod-delete.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-delete
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "delete"]
[root@master-01 ~]# kubectl create -f pod-delete.yaml
clusterrole.rbac.authorization.k8s.io/pod-delete created

创建权限为在Pod内执行命令的ClusterRole

[root@master-01 ~]# vim pod-exec.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-exec
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]
[root@master-01 ~]# kubectl create -f pod-exec.yaml
clusterrole.rbac.authorization.k8s.io/pod-exec created

创建权限为查看Pod日志的ClusterRole

[root@master-01 ~]# vim pod-logs.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-log
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]
[root@master-01 ~]# kubectl create -f pod-logs.yaml
clusterrole.rbac.authorization.k8s.io/pod-log created

创建用户管理命名空间

[root@master-01 ~]# kubectl create namespace kube-users
namespace/kube-users created

创建用户对应的ServiceAccount账号

[root@master-01 ~]# kubectl create serviceaccount moms -n kube-users
serviceaccount/moms created
[root@master-01 ~]# kubectl create serviceaccount caijx -n kube-users
serviceaccount/caijx created

通过ClusterRoleBindin授予用户全局的可读命名空间权限

[root@master-01 ~]# vim namespaces-readonly.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: namespace-readonly-sa
subjects:
- kind: Group
  name: system:serviceaccounts:kube-users  # 指定命名空间
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: namespace-readonly  # 指定你要绑定的 ClusterRole
  apiGroup: rbac.authorization.k8s.io
[root@master-01 ~]# kubectl create -f namespaces-readonly.yaml
clusterrolebinding.rbac.authorization.k8s.io/namespace-readonly-sa created

查看绑定状态

[root@master-01 ~]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io namespace-readonly-sa
Name:         namespace-readonly-sa
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  namespace-readonly
Subjects:
  Kind   Name                               Namespace
  ----   ----                               ---------
  Group  system:serviceaccounts:kube-users

通过create token命令,获取对应用户的token,登录Dashboard界面查看用户是否可以切换命名空间。可以观察到moms和caijx用户当前可以查看命名空间,但是无法浏览命名空间下的其他资源

命名空间只读权限

[root@master-01 ~]# kubectl create token -n kube-users caijx
eyJhbGciOiJSUzI1NiIsImtpZCI6Im5MSHM0SE9MX2ZRRTBDc29YOXJQYW9RLW1PVFd4cFZmX3dYVEN2M0g1azgif...省略部分输出...

为moms服务账号绑定查看kube-system和default命名空间查看Pod日志的权限

[root@master-01 ~]#  kubectl create rolebinding moms-pod-log --clusterrole=pod-log --serviceaccount=kube-users:moms --namespace=kube-system
rolebinding.rbac.authorization.k8s.io/moms-pod-log created
[root@master-01 ~]#  kubectl create rolebinding moms-pod-log --clusterrole=pod-log --serviceaccount=kube-users:moms --namespace=default
rolebinding.rbac.authorization.k8s.io/moms-pod-log created

通过Token登录Dashboard,读者需要验证,能够在Kube-system和Default命名空间下查看Pod的日志,并且无其他权限,如执行、删除等。在其他命名空间无法查看Pod。

(1)可以查看对应命名空间下Pod的日志

可以读取日志

(2)无法在Pod内执行命名

不可执行命令

(3)在其他命名空间查看Pod资源

其他命名空间无法查看Pod

为caijx服务账号绑定在默认命名空间下的Pod执行命令和删除权限

[root@master-01 ~]# kubectl create rolebinding caijx-pod-exec --clusterrole=pod-exec --serviceaccount=kube-users:caijx --namespace=default
rolebinding.rbac.authorization.k8s.io/caijx-pod-exec created
[root@master-01 ~]# kubectl create rolebinding caijx-pod-del --clusterrole=pod-delete --serviceaccount=kube-users:caijx --namespace=default
rolebinding.rbac.authorization.k8s.io/caijx-pod-del created

通过Token登录Dashboard,读者需要验证,能够在Default命名空间下对Pod执行命令,并且可以删除Pod,但是无法查看Pod日志,在其他命名空间下也没有权限等

(1)执行命令

执行命令

(2)删除Pod

删除容器

(3)无法查看Pod日志

无法查看日志

(4)在其他命名空间无权限

在其他命名空间无权限