Role 和 RoleBinding

RoleRoleBinding 资源都是命名空间中的资源。前者决定可以针对哪些 URL 路径执行哪些操作;后者将前者与用户主体绑定(当然后者也可以与 ClusterRole 进行绑定,虽然这样还是只能操作 RoleBinding 所在命名空间的 URL 路径)。

创建 Role

Role 是 Kubernetes 中的一种资源,因此可以通过 YAML 定义来生成。如下,在 foo 命名空间中创建一个名为 service-reader 的 Role 对象,该角色规定能够对 services/test-service 资源对象执行 getlist 操作:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role    # 类型为 Role
metadata:
  namespace: foo    # 所在命名空间名
  name: service-reader
rules:    # 重点!定义了能够对哪些 URL 路径执行哪些操作
- apiGroups: [""]    # 由于 services.apiGroup=v1,即没有 "/","/" 前面是资源所属的组,所以 services 不属于任何组,所以这里为空
  verbs: ["get", "list"]    # 能够执行 get 和 list 操作
  resources: ["services"]    # 针对 Service 资源
  resourceNames: ["test-service"] # 针对 Service 资源中的名为 test-service 的对象;若这里省略,则表示针对所有 Service 资源

当然也可以使用 kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run] [options] 命令来创建该资源:

kubectl create role service-reader --verb=get,list --resource=services --resource-name=test-service -n foo

创建 RoleBinding

在创建完 Role 之后,需要创建 RoleBinding 来将 用户主体Role 绑定,从而限制用户主体可以对哪些 URL 路径执行哪些操作。

创建 RoleBinding 同样可以使用 YAML 定义来生成。如下,在 foo 命名空间中创建一个名为 test 的 RoleBinding 对象,其与名为 service-reader 的 Role 对象绑定,并与 foo 命名空间中名为 default 的 ServiceAccount 以及 bar 命名空间中名为 default 的 ServiceAccount 绑定:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding    # 类型为 RoleBinding
metadata:
  name: test
  namespace: foo    # 所在命名空间名
roleRef:    # 绑定的 Role(也支持绑定 ClusterRole 资源)
  apiGroup: rbac.authorization.k8s.io    # Role 资源所属的 API 组
  kind: Role    # 类型为 Role
  name: service-reader    # Role 的名字
subjects:    # 绑定的用户主体(可以是 用户名、ServiceAccount、组)
- kind: ServiceAccount    # 绑定的用户主体类型为 ServiceAccount
  name: default    # ServiceAccount 名
  namespace: foo    # 用户主体所属的 命名空间
- kind: ServiceAccount
  name: default
  namespace: bar

当然也可以使用 kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run] [options] 命令来创建该资源:

kubectl create rolebinding test --role=service-reader --serviceaccount=foo:default --serviceaccount=bar:default -n foo

测试

根据上述的创建命令创建完后,会得到下面的关系图,由于 ServiceAccount 均为各自命名空间中的默认 ServiceAccount,因此若 Pod 的 pod.spec.serviceAccountName 没有指定的话,则默认使用其所在命名空间的 default ServiceAccount。

部署结果关系图

在命名空间 foobar 中分别生成一个 Pod,均使用各自命名空间中的默认 ServiceAccount,那么正常情况下,这两个 Pod 将均能通过 API 服务器获得命名空间 foo 中的名为 test-service 的 Service 对象信息。在 Pod 中的测试命令如下(Pod 使用的是 luksa/kubectl-proxy 镜像,内部安装了 kubectl 组件):

curl localhost:8001/api/v1/namespaces/foo/services/test-service
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {

  },
  "status": "Failure",
  "message": "services \"test-service\" not found",
  "reason": "NotFound",
  "details": {
    "name": "test-service",
    "kind": "services"
  },
  "code": 404
}

从输出结果可以看出,提示的不是没有权限,而是 404 资源不存在,这是因为集群中并没有 test-service 这个资源对象,所以授权是成功的

Last updated

Was this helpful?