本文由作者授权发布,未经许可,请勿转载。
作者:李岚清,网易数帆轻舟事业部资深工程师
基于角色的访问控制(Role-Based Access Control, 即“RBAC”)使用 “rbac.authorization.k8s.io” API Group 实现授权控制,用户可以通过 Kubernetes API 动态配置策略。
RBAC 共包含4个类型的资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding
。用户可以通过增删改查上述四个API对象来实现访问权限的动态控制。
假如没有创建任何ClusterRole和Role,则所有用户是无权限访问任何K8S的API的,K8S的权限控制是类似于白名单的,通过创建 Role&RoleBinding 和 ClusterRole&ClusterRoleBinding 将用户权限添加到“白名单”中,以此来实现授权。
在 RBAC API 中,Role 和 Cluster 都表示一组权限的集合,Role 是 namespace-scoped的,定义的是某一个namespace中的资源权限;而如果想要实现集群级别的或者跨namespace的权限控制,则需要创建 ClusterRole。
如上文所说,Role 是 namespace-scoped的,定义的是某一个namespace中的资源权限。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
上述 pod-reader
role,表示可以get/list/watch default namespce下面的pods资源。
Role 中可以定义多条rules,每条rule表示一个权限,rule类型定义如下:
type Rule struct {
// Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds.
Verbs []string
// APIGroups is the name of the APIGroup that contains the resources.
// If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed.
APIGroups []string
// Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups.
// '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.
Resources []string
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.
ResourceNames []string
// NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
// If an action is not a resource API request, then the URL is split on '/' and is checked against the NonResourceURLs to look for a match.
// Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
// Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
NonResourceURLs []string
}
ClusterRole 是用来实现集群级别的或者跨namespace的权限控制:
nodes
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" omitted since ClusterRoles are not namespaced
name: secret-reader
rules:
- apiGroups: [""]
#
# at the HTTP level, the name of the resource for accessing Secret
# objects is "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]
secret-reader
表示 get/list/watch 所有namespaces下面的secrets资源的权限。
Role 和 ClusterRole 都表示了权限的集合,权限只有授予某个user或者group才有实际意义。权限和用户之间的关联关系 是通过 RoleBinding 和 ClusterRoleBinding 两个API资源来实现的。RoleBinding 是 namespace-scoped的,而 ClusterRoleBinding是 cluster-scoped的。
RoleBinding 可以引用在同一命名空间内定义的 Role 对象。 下面示例中定义的 RoleBinding 对象在“default” 命名空间中将“pod-reader” 角色授予用户“jane”。 这一授权将允许用户“jane” 从“default” 命名空间中读取 pod。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
RoleBinding 对象也可以引用一个 ClusterRole 对象用于在 RoleBinding 所在的命名空间内授予用户对所引用的 ClusterRole 中 定义的命名空间资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色。
例如,尽管下面示例中的 RoleBinding 引用的是一个 ClusterRole 对象,但是用户”dave”(即角色绑定主体)还是只能读取”development” 命名空间中的 secret(即 RoleBinding 所在的命名空间)。
# 以下角色绑定允许用户 "dave" 读取 "development" 命名空间中的 secret。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets
namespace: development # 这里表明仅授权读取 "development" 命名空间中的资源。
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
可以使用ClusterRoleBinding在集群级别和所有命名空间中授予权限。下面示例中所定义的ClusterRoleBinding允许在用户组”manager” 中的任何用户都可以读取集群中任何命名空间中的 secret。
以下 ClusterRoleBinding 对象允许在用户组 "manager" 中的任何用户都可以读取集群中任何命名空间中的 secret。
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
大多数资源由代表其名字的字符串表示,例如”pods”,就像它们出现在相关 API endpoint 的 URL 中一样。然而,有一些 Kubernetes API 还 包含了” 子资源”,比如 pod 的 logs。在 Kubernetes 中,pod logs endpoint 的 URL 格式为:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
在这种情况下,“pods” 是命名空间资源,而“log” 是 pods 的子资源。为了在 RBAC 角色中表示出这一点,我们需要使用斜线来划分资源 与子资源。如果需要角色绑定主体读取 pods 以及 pod log,您需要定义以下角色:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
通过resourceNames
列表,角色可以针对不同种类的请求根据资源名引用资源实例。当指定了resourceNames列表时,不同动作 种类的请求的权限,如使用get、delete、update、patch
等动词的请求,将被限定到资源列表中所包含的资源实例上。 例如,如果需要限定一个角色绑定主体只能“get” 或者“update” 一个 configmap 时,您可以定义以下角色:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["configmap"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
值得注意的是,如果设置了resourceNames
,则请求所使用的动词不能是 list、watch、create 或者 deletecollection
。 由于资源名不会出现在 create、list、watch 和 deletecollection
等 API 请求的 URL 中,所以这些请求动词不会被设置了resourceNames的规则所允许,因为规则中的resourceNames 部分不会匹配这些请求。
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
/healthz
及其所有子路径的 GET 和 POST 请求(此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # 在非资源 URL 中,'*' 代表后缀通配符
verbs: ["get", "post"]
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
subjects:
- kind: User
name: "[email protected]"
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
作者简介
李岚清,网易数帆轻舟事业部资深系统开发工程师,具有多年 Kubernetes 开发运维经验,负责在 / 离线业务混部、容器网络编排等多个项目,推动和协助网易内部多个业务实现容器化。目前专注于云原生、分布式系统架构等技术领域。