一.RBAC的概念
基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。其在kubernetes 1.5版本引入,在1.6版本升级为beta版本,并成为kubeadm安装方式下的默认选项。要启用 RBAC,在启动 API 服务器时将 --authorization-mode
参数设置为一个逗号分隔的列表并确保其中包含 RBAC。
kube-apiserver --authorization-mode=Example,RBAC --<其他选项> --<其他选项>
RBAC API 声明了四种 Kubernetes 对象:Role、ClusterRole、 ClusterRoleBinding、RoleBinding。你可以像使用其他 Kubernetes 对象一样使用kubectl操作这些资源。
RBAC 的 Role 或 ClusterRole 中包含一组代表相关权限的规则,这些权限是纯粹累加的(不存在拒绝某操作的规则)
两者的区别是Role是作用于命名空间的角色,ClusterRole是作用于整个集群的集群角色。在你创建 Role 时,你必须指定该 Role 所属的名字空间,这两种资源的名字不同(Role 和 ClusterRole) 是因为 Kubernetes 对象要么是名字空间作用域的,要么是集群作用域的,不可两者兼具。
ClusterRole也是可以作用于单个命名空间的,不仅仅用于整个集群作用域。
ClusterRole 有若干用法。你可以用它来:
Role 示例
下面是一个位于 "default" 名字空间的 Role 的示例,可用来授予对 pod的读访问权限
- apiVersion: rbac.authorization.k8s.io/v1 #该资源的api版本,使用v1版本,其他版本在1.22上将被弃用
- kind: Role #资源类型为Role
- metadata: #元数据定义
- namespace: default #命名空间
- name: pod-reader #Role的名称
- rules: #定义Role具体的权限
- - apiGroups: [""] # "" 标明 core API 组
- resources: ["pods"] #定义对哪些资源进行授权,比如pods,service等
- verbs: ["get", "watch", "list"] #可以执行的操作,还有create、delete、list、get、watch、deletecollection等
ClusterRole 示例
ClusterRole 同样可以用于授予 Role 能够授予的权限。 因为 ClusterRole 属于集群范围,所以它也可以为以下资源授予访问权限:
集群范围资源(比如节点(Node))
非资源端点(比如 /healthz
)
跨名字空间访问的名字空间作用域的资源(如 Pod)
- 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"]
从以上配置可以看出,Role、ClusterRole的yaml文件的配置区别不大,只是kind资源类型是Role还是ClusterRole。
角色绑定(Role Binding)是将角色中定义的权限赋予User、Group或者ServiceAccount。
RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。
一个 RoleBinding 可以引用同一的名字空间中的任何 Role,RoleBinding 也可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。
RoleBinding 示例
RoleBinding引用Role赋权
- apiVersion: rbac.authorization.k8s.io/v1
- # 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pod
- # 你需要在该命名空间中有一个名为 “pod-reader” 的 Role
- kind: RoleBinding
- metadata:
- name: read-pods
- namespace: default
- subjects:
- # 你可以指定不止一个“subject(主体)”
- - kind: User
- name: jane # "name" 是区分大小写的
- apiGroup: rbac.authorization.k8s.io
- roleRef:
- # "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
- kind: Role # 此字段必须是 Role 或 ClusterRole
- name: pod-reader # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
- apiGroup: rbac.authorization.k8s.io
RoleBinding引用ClusterRole赋权,管理员可以为整个集群定义一组公用的ClusterRole,然后在多个命名空间重复使用。
- apiVersion: rbac.authorization.k8s.io/v1
- # 此角色绑定使得用户 "dave" 能够读取 "development" 名字空间中的 Secrets
- # 你需要一个名为 "secret-reader" 的 ClusterRole
- kind: RoleBinding
- metadata:
- name: read-secrets
- # RoleBinding 的名字空间决定了访问权限的授予范围。
- # 这里隐含授权仅在 "development" 名字空间内的访问权限。
- namespace: development
- subjects:
- - kind: User
- name: dave # 'name' 是区分大小写的
- apiGroup: rbac.authorization.k8s.io
- roleRef:
- kind: ClusterRole
- name: secret-reader
- apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding 示例
要跨整个集群完成访问权限的授予,你可以使用一个 ClusterRoleBinding,ClusterRoleBinding可用于在集群级别和所有命名空间中授予权限,比如下面的 ClusterRoleBinding 允许 "manager" 组内的所有用户访问任何名字空间中的 Secrets。
- 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
创建了绑定之后,你不能再修改绑定对象所引用的 Role 或 ClusterRole。 试图改变绑定对象的 roleRef
将导致合法性检查错误。 如果你想要改变现有绑定对象中 roleRef
字段的内容,必须删除重新创建绑定对象。
在 Kubernetes API 中,大多数资源都是使用对象名称的字符串表示来呈现与访问的。 例如,对于 Pod 应使用 "pods"。 RBAC 使用对应 API 端点的 URL 中呈现的名字来引用资源。 有一些 Kubernetes API 涉及 子资源(subresource),例如 Pod 的日志。 对 Pod 日志的请求看起来像这样:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
在这里,pods
对应名字空间作用域的 Pod 资源,而 log
是 pods
的子资源。 在 RBAC 角色表达子资源时,使用斜线(/
)来分隔资源和子资源。 要允许某主体读取 pods
同时访问这些 Pod 的 log
子资源,你可以这样写
- 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
- 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"]
聚合的 ClusterRole
你可以将若干 ClusterRole 聚合(Aggregate) 起来,形成一个复合的 ClusterRole。 作为集群控制面的一部分,控制器会监视带有 aggregationRule
的 ClusterRole 对象集合。aggregationRule
为控制器定义一个标签选择算符供后者匹配应该组合到当前 ClusterRole 的 roles
字段中的 ClusterRole 对象
- 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 中。
- 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", "endpoints", "pods"]
- verbs: ["get", "list", "watch"]
默认的面向用户的角色使用 ClusterRole 聚合。 这使得作为集群管理员的你可以为扩展默认规则,包括为定制资源设置规则, 比如通过 CustomResourceDefinitions 或聚合 API 服务器提供的定制资源。
例如,下面的 ClusterRoles 让默认角色 "admin" 和 "edit" 拥有管理自定义资源 "CronTabs" 的权限, "view" 角色对 CronTab 资源拥有读操作权限。 你可以假定 CronTab 对象在 API 服务器所看到的 URL 中被命名为 "crontabs"
。
- apiVersion: rbac.authorization.k8s.io/v1
- kind: ClusterRole
- metadata:
- name: aggregate-cron-tabs-edit
- labels:
- # 添加以下权限到默认角色 "admin" 和 "edit" 中
- rbac.authorization.k8s.io/aggregate-to-admin: "true"
- rbac.authorization.k8s.io/aggregate-to-edit: "true"
- rules:
- - apiGroups: ["stable.example.com"]
- resources: ["crontabs"]
- verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- ---
- kind: ClusterRole
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- name: aggregate-cron-tabs-view
- labels:
- # 添加以下权限到 "view" 默认角色中
- rbac.authorization.k8s.io/aggregate-to-view: "true"
- rules:
- - apiGroups: ["stable.example.com"]
- resources: ["crontabs"]
- verbs: ["get", "list", "watch"]
Role 的rules规则示例
- #允许读取在核心 API 组下的 "pods"
- rules:
- - apiGroups: [""]
- # 在 HTTP 层面,用来访问 Pod 资源的名称为 "pods"
- resources: ["pods"]
- verbs: ["get", "list", "watch"]
- #允许在 "apps" API 组中读/写 Deployment(在 HTTP 层面,对应 URL 中资源部分为 "deployments")
- rules:
- - apiGroups: ["apps"]
- #
- # 在 HTTP 层面,用来访问 Deployment 资源的名称为 "deployments"
- resources: ["deployments"]
- verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- #允许读取核心 API 组中的 Pod 和读/写 "batch" API 组中的 Job 资源:
- rules:
- - apiGroups: [""]
- # 在 HTTP 层面,用来访问 Pod 资源的名称为 "pods"
- resources: ["pods"]
- verbs: ["get", "list", "watch"]
- - apiGroups: ["batch"]
- # 在 HTTP 层面,用来访问 Job 资源的名称为 "jobs"
- resources: ["jobs"]
- verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- #允许读取名称为 "my-config" 的 ConfigMap
- rules:
- - apiGroups: [""]
- # 在 HTTP 层面,用来访问 ConfigMap 资源的名称为 "configmaps"
- resources: ["configmaps"]
- resourceNames: ["my-config"]
- verbs: ["get"]
- #允许读取在核心组中的 "nodes" 资源(因为 Node 是集群作用域的,所以需要 ClusterRole 绑定到 ClusterRoleBinding 才生效)
- rules:
- - apiGroups: [""]
- # 在 HTTP 层面,用来访问 Node 资源的名称为 "nodes"
- resources: ["nodes"]
- verbs: ["get", "list", "watch"]
- #允许针对非资源端点 /healthz 和其子路径上发起 GET 和 POST 请求 (必须在 ClusterRole 绑定 ClusterRoleBinding 才生效)
- rules:
- - nonResourceURLs: ["/healthz", "/healthz/*"] # nonResourceURL 中的 '*' 是一个全局通配符
- verbs: ["get", "post"]
对主体的引用
RoleBinding 或者 ClusterRoleBinding 可绑定角色到某 主体(Subject) 上。 主体可以是组,用户或者服务账户。
Kubernetes 用字符串来表示用户名。 用户名可以是普通的用户名,像 "alice";或者是邮件风格的名称,如 "bob@example.com", 或者是以字符串形式表达的数字 ID。
前缀 system:
是 Kubernetes 系统保留的,所以你要确保所配置的用户名或者组名不能出现上述 system:
前缀。除了对前缀的限制之外,RBAC 鉴权系统不对用户名格式作任何要求
服务账户(ServiceAccount) 的用户名前缀为 system:serviceaccount:
,属于前缀为 system:serviceaccounts:
的用户组
- #对于名称为 alice@example.com 的用户:
- subjects:
- - kind: User
- name: "alice@example.com"
- apiGroup: rbac.authorization.k8s.io
- #对于名称为 frontend-admins 的用户组
- subjects:
- - kind: Group
- name: "frontend-admins"
- apiGroup: rbac.authorization.k8s.io
- #对于 kube-system 名字空间中的默认服务账户
- subjects:
- - kind: ServiceAccount
- name: default
- namespace: kube-system
- #对于 "qa" 名称空间中的所有服务账户:
- 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
下面的 ClusterRole 和 RoleBinding 将允许用户 user-1
把名字空间 user-1-namespace
中的 admin
、edit
和 view
角色赋予其他用户:
- 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
1.创建Role kubectl create role
创建 Role 对象,定义在某一名字空间中的权限。例如:
创建名称为 “pod-reader” 的 Role 对象,允许用户对 Pods 执行 get
、watch
和 list
操作:
kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
创建名称为 “pod-reader” 的 Role 对象并指定 resourceNames
:
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
创建名为 “foo” 的 Role 对象并指定 apiGroups
:
kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
创建名为 “foo” 的 Role 对象并指定子资源权限:
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
创建名为 “my-component-lease-holder” 的 Role 对象,使其具有对特定名称的资源执行 get/update 的权限:
kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
2.创建ClusterRole kubectl create clusterrole
创建 ClusterRole 对象。例如:
创建名称为 “pod-reader” 的 ClusterRole 对象,允许用户对 Pods 对象执行 get
、 watch
和 list
操作:
kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
创建名为 “pod-reader” 的 ClusterRole 对象并指定 resourceNames
:
kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
创建名为 “foo” 的 ClusterRole 对象并指定 apiGroups
:
kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
创建名为 “foo” 的 ClusterRole 对象并指定子资源:
kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
创建名为 “foo” 的 ClusterRole 对象并指定 nonResourceURL
:
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
创建名为 “monitoring” 的 ClusterRole 对象并指定 aggregationRule
:
kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
3.创建RoleBinding kubectl create rolebinding
在特定的名字空间中对 Role
或 ClusterRole
授权。例如:
在名字空间 “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
4.创建CllusterRoleBinding kubectl create clusterrolebinding
在整个集群(所有名字空间)中用 ClusterRole 授权。例如:
在整个集群范围,将名为 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
使用清单文件来创建或者更新 rbac.authorization.k8s.io/v1
API 对象。
尚不存在的对象会被创建,如果对应的名字空间也不存在,必要的话也会被创建。 已经存在的角色会被更新,使之包含输入对象中所给的权限。如果指定了 --remove-extra-permissions
,可以删除额外的权限。
已经存在的绑定也会被更新,使之包含输入对象中所给的主体。如果指定了 --remove-extra-permissions
,则可以删除多余的主体。
例如:
测试应用 RBAC 对象的清单文件,显示将要进行的更改:
kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
应用 RBAC 对象的清单文件,保留角色(roles
)中的额外权限和绑定(bindings
)中的其他主体:
kubectl auth reconcile -f my-rbac-rules.yaml
应用 RBAC 对象的清单文件,删除角色(roles
)中的额外权限和绑定中的其他主体:
kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions