当客户端发起API Server调用时,API Server内部要先进行用户认证,然后执行用户授权流程,即通过授权策略(Authorization Policy)决定一个API调用是否合法。对合法用户进行授权并随后在用户访问时进行鉴权,是权限与安全系统中的重要一环。简单地说,授权就是授予不同的用户不同的访问权限。API Server目前支持以下授权策略。
◎ AlwaysDeny:表示拒绝所有请求,仅用于测试。
◎ AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略。
◎ ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户的请求进行匹配和控制。
◎ RBAC:Role-Based Access Control,是基于角色的访问控制。
◎ Webhook:通过调用外部的REST服务对用户进行授权。
◎ Node:是一种对kubelet进行授权的特殊模式。
AlwaysDeny因为缺乏实际意义,已于Kubernetes 1.13版本之后被废弃。AlwaysAllow基本不会被用于实际生产中。ABAC是Kubernetes 1.6版本之前的默认授权模式,功能强大,但存在理解和配置复杂、修改后需要重启API Server等硬伤,因此从Kubernetes 1.6版本开始,已被全新的RBAC授权模式替代。如果RBAC仍然不满足某些特定需求,则用户还可以自行编写授权逻辑并通过Webhook方式注册为Kubernetes的授权服务,以实现更加复杂的授权规则。
通过API Server的启动参数--authorization-mode可配置多种授权策略,用逗号分隔即可。在通常情况下,我们会设置授权策略为Node,RBAC,API Server在收到请求后,会读取该请求中的数据,生成一个访问策略对象,API Server会将这个访问策略对象和配置的授权模式逐条进行匹配,第一个被满足或拒绝的授权策略决定了该请求的授权结果,如果匹配的结果是禁止访问,则API Server会终止API调用流程,并返回客户端的错误调用码。
Node授权策略用于对kubelet发出的请求进行访问控制,与用户的应用授权无关,属于Kubernetes自身安全的增强功能。简单来说,就是限制每个Node只访问它自身运行的Pod及相关的Service、Endpoints等信息;也只能受限于修改自身Node的一些信息,比如Label;也不能操作其他Node上的资源。而之前用RBAC这种通用权限模型其实并不能满足Node这种特殊的安全要求,所以将其剥离出来定义为新的Node授权策略。
在API Server启用ABAC模式时,集群管理员需要指定授权策略文件的路径和名称(--authorization-policy-file=SOME_FILENAME),授权策略文件里的每一行都以一个Map类型的JSON对象进行设置,它被称为“访问策略对象”。在授权策略文件中,集群管理员需要设置访问策略对象中的apiVersion、kind、spec属性来确定具体的授权策略,其中,apiVersion的当前版本为abac.authorization.kubernetes.io/v1beta1;kind被设置为Policy;spec指详细的策略设置,包括主体属性、资源属性、非资源属性这三个字段。
(1)对主体属性说明如下。
◎ user(用户名):字符串类型,该字符串类型的用户名来源于Token文件(--token-auth-file参数设置的文件)或基本认证文件中用户名称段的值。
◎ group(用户组):在被设置为“system:authenticated”时,表示匹配所有已认证请求;在被设置为“system:unauthenticated”时,表示匹配所有未认证请求。
(2)对资源属性说明如下。
◎ apiGroup(API组):字符串类型,表明匹配哪些API Group,例如extensions或*(表示匹配所有API Group)。
◎ namespace(命名空间):字符串类型,表明该策略允许访问某个Namespace的资源,例如kube-system或*(表示匹配所有Namespace)。
◎ resource(资源):字符串类型,表明要匹配的API资源对象,例如pods或*(表示匹配所有资源对象)。
(3)对非资源属性说明如下。
◎ nonResourcePath(非资源对象类路径):非资源对象类的URL路径,例如/version或/apis,*表示匹配所有非资源对象类的请求路径,也可以将其设置为子路径,/foo/*表示匹配所有/foo路径下的所有子路径。
◎ readonly(只读标识):布尔类型,当它的值为true时,表明仅允许GET请求通过。下面对ABAC授权算法、使用kubectl时的授权机制、常见的ABAC授权示例及如何对Service Account进行授权进行说明。
API Server进行ABAC授权的算法为:在API Server收到请求之后,首先识别出请求携带的策略对象的属性,然后根据在策略文件中定义的策略对这些属性进行逐条匹配,以判定是否允许授权。如果有至少一条匹配成功,这个请求就通过了授权(不过还是可能在后续的其他授权校验中失败)。常见的策略配置如下。
◎ 要允许所有认证用户做某件事,则可以写一个策略,将group属性设置为system:authenticated。
◎ 要允许所有未认证用户做某件事,则可以把策略的group属性设置为system:unauthenticated。
◎ 要允许一个用户做任何事,则将策略的apiGroup、namespace、resource和nonResourcePath属性设置为“*”即可。
kubectl使用API Server的/api和/apis端点来获取版本信息。要验证kubectl create/update命令发送给服务器的对象,kubectl则需要向OpenAPI查询,对应的URL路径为/openapi/v2。
使用ABAC授权模式时,以下特殊资源必须显式地通过nonResourcePath属性设置。
◎ API版本协商过程中的/api、/api/*、/apis和/apis/*。
◎ 通过kubectl version命令从服务器中获取版本时的/version。
◎ create/update操作过程中的/swaggerapi/*。
使用kubectl操作时,如果需要查看发送到API Server的HTTP请求,则可以将日志级别设置为8,例如:

下面通过几个授权策略文件(JSON格式)示例说明ABAC的访问控制用法。
(1)允许用户alice对所有资源做任意操作:

(2)kubelet可以读取任意Pod:

(3)kubelet可以读写Event对象:

(4)用户bob只能读取projectCaribou中的Pod:

(5)任意用户都可以对非资源类路径进行只读请求:

如果添加了新的ABAC策略,则需要重启API Server以使其生效。
Service Account会自动生成一个ABAC用户名(username),用户名按照以下命名规则生成:

创建新的命名空间时,会产生一个如下名称的Service Account:

如果希望kube-system命名空间中的Service Account“default”具有全部权限,就需要在策略文件中加入如下内容:

Webhook定义了一个HTTP回调接口,实现Webhook的应用会在指定事件发生时向一个URL地址发送(POST)通知信息。启用Webhook授权模式后,Kubernetes会调用外部REST服务对用户访问资源进行授权。
Webhook模式用参数--authorization-webhook-config-file=SOME_FILENAME来设置远端授权服务的信息。
配置文件使用的是kubeconfig文件的格式,文件里users一节的内容设置的是API Server的信息。相对于远程授权服务来说,API Server是客户端,也就是用户;clusters一节的内容设置的是远程授权服务器的信息。下面是一个使用HTTPS客户端认证的配置示例:


在授权开始时,API Server会生成一个API版本为“authorization.k8s.io/v1beta1”的SubjectAccessReview资源对象,用于描述操作信息,在进行JSON序列化之后以HTTP POST方式发送给远程Webhook授权服务。在SubjectAccessReview资源对象中包含用户尝试访问资源的请求动作的描述,以及需要访问的资源信息。
SubjectAccessReview资源对象和其他API对象一样,遵循同样的版本兼容性规则,在实现时要注意apiVersion字段的版本,以实现正确的反序列化操作。另外,API Server必须启用authorization.k8s.io/v1beta1 API扩展(--runtime-config=authorization.k8s.io/v1beta1=true)。
下面是一个希望获取Pod列表的请求报文示例:

远程Webhook授权服务需要填充SubjectAccessReview资源对象的status字段,返回允许访问或者不允许访问的结果。应答报文中的spec字段是无效的,也可以省略。
一个返回“允许访问”(allowed=true)的应答报文示例如下:

返回“不允许访问”的应答有两种方法。
(1)仅返回“不允许访问”(allowed=false),但配置的其他授权者仍有机会对请求进行授权,这也是多数情况下的通用做法,示例如下:

(2)返回“不允许访问”(allowed=false),同时立刻拒绝其他授权者再对请求进行授权(denied=true),这要求Webhook服务了解集群的详细配置以能够做出准确的授权判断,示例如下:

除了对资源对象的访问进行授权,还可以对非资源对象的请求路径进行授权。
非资源的请求路径包括/api、/apis、/metrics、/logs、/debug、/healthz、/livez、/openapi/v2、/readyz和/version。客户端需要访问/api、/api/*、/apis、/apis/*和/version等路径,用于发现服务端提供的API资源列表和版本信息,通常应授权为“允许访问”。对于其他非资源的访问一般可以禁止,以限制客户端对API Server进行不必要的访问。
查询/debug的请求报文示例如下:

RBAC(Role-Based Access Control,基于角色的访问模式控制)从Kubernetes 1.5版本开始引入,在1.6版本时升级为Beta版本,在1.8版本时升级为GA稳定版本。作为kubeadm安装方式的默认选项,足见其重要性。
相对于其他访问控制方式,RBAC授权具有如下优势。
◎ 对集群中的资源和非资源权限均有完整的覆盖。
◎ RBAC的权限配置通过几个API对象即可完成,同其他API对象一样,可以用kubectl或API进行操作。
◎ 可以在运行时进行调整,无须重新启动API Server。
要使用RBAC授权模式,首先需要在kube-apiserver服务的启动参数authorization-mode(授权模式)的列表中加上RBAC,例如--authorization-mode=...,RBAC。
本节对RBAC的原理和应用进行详细说明。
在RBAC管理体系中,Kubernetes引入了4个资源对象:Role、ClusterRole、RoleBinding和ClusterRoleBinding。同其他API资源对象一样,用户可以使用kubectl或者API调用等方式操作这些资源对象。
一个角色就是一组权限的集合,在Role中设置的权限都是许可(Permissive)形式的,不可以设置拒绝(Deny)形式的规则。Role设置的权限将会局限于命名空间(namespace)范围内,如果需要在集群级别设置权限,就需要使用ClusterRole了。
下面是一个Role定义示例,该角色具有在命名空间default中读取(get、watch、list)Pod资源对象信息的权限:

Role资源对象的主要配置参数都在rules字段中进行设置,如下所述。
◎ resources:需要操作的资源对象类型列表,例如"pods"、"deployments"、"jobs"等。
◎ apiGroups:资源对象API组列表,例如""(Core)、"extensions"、"apps"、"batch"等。
◎ verbs:设置允许对资源对象操作的方法列表,例如"get"、"watch"、"list"、"delete"、"replace"、"patch"等。
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下授权应用场景中。
◎ 对集群范围内资源的授权,例如Node。
◎ 对非资源型的授权,例如/healthz。
◎ 对包含全部namespace资源的授权,例如pods(用于kubectl get pods--all-namespaces这样的操作授权)。
◎ 对某个命名空间中多种权限的一次性授权。
下面是一个ClusterRole定义示例,该集群角色有权访问一个或所有namespace的secrets(根据其被RoleBinding还是ClusterRoleBinding绑定而定)的权限:

角色绑定或集群角色绑定用来把一个角色绑定到一个目标主体上,绑定目标可以是User(用户)、Group(组)或者Service Account。RoleBinding用于某个命名空间中的授权,ClusterRoleBinding用于集群范围内的授权。
RoleBinding可以与属于相同命名空间的Role或者某个集群级别的ClusterRole绑定,完成对某个主体的授权。
下面是与相同命名空间中的Role进行绑定的示例,通过这个绑定操作,就完成了以下授权规则:允许用户jane读取命名空间default的Pod资源对象信息:


RoleBinding也可以引用ClusterRole,对目标主体在其所在命名空间授予在ClusterRole中定义的权限。一种常见的用法是集群管理员预先定义好一组ClusterRole(权限设置),然后在多个命名空间中重复使用这些ClusterRole。
例如,在下面的例子中为用户“dave”授权一个ClusterRole“secret-reader”,虽然secret-reader是一个集群角色,但因为RoleBinding的作用范围为命名空间development,所以用户dave只能读取命名空间development中的secret资源对象,而不能读取其他命名空间中的secret资源对象:

图6.2展示了上述对Pod的get、watch、list操作进行授权的Role和RoleBinding的逻辑关系。

图6.2 Role和RoleBinding的逻辑关系
ClusterRoleBinding用于进行集群级别或者对所有命名空间都生效的授权。下面的例子允许manager组的用户读取任意命名空间中的secret资源对象:

注意,在集群角色绑定(ClusterRoleBinding)中引用的角色只能是集群级别的角色(ClusterRole),而不能是命名空间级别的Role。
一旦通过创建RoleBinding或ClusterRoleBinding与某个Role或ClusterRole完成了绑定,用户就无法修改与之绑定的Role或ClusterRole了。只有删除了RoleBinding或ClusterRoleBinding,才能修改Role或ClusterRole。Kubernetes限制roleRef字段中的内容不可更改,主要有以下两个原因。
◎ 从逻辑上来说,与一个新的Role进行绑定实际上是一次全新的授权操作。通过删除或重建的方式更改绑定的Role,可以确保给主体授予新角色的权限(而不是在不验证所有现有主体的情况下去修改roleRef)。
◎ 使roleRef不变,可以授予某个用户对现有绑定对象(Binding object)的更新(update)权限,以便其管理授权主体(subject),同时禁止更改角色中的权限设置。
在Kubernetes系统中,大多数资源对象都可以用其名称字符串来表达,例如pods、services、deployments等,在RBAC的权限设置中引用的就是资源对象的字符串名称。
某些Kubernetes API还包含下级子资源(subresource),例如Pod日志(log)。Pod日志的API Endpoint是GET/api/v1/namespaces/{namespace}/pods/{name}/log。对于这种资源,在RBAC权限设置中引用的格式是“主资源名称/子资源名称”,中间以“/”分隔,对于Pod的log这个例子来说,需要将其配置为pods/log。
Role中的resources可以引用多个资源对象,以数组的形式表示。
例如,下面的RBAC规则设置的是对资源pods和pods/log授予get和list权限:

仅设置资源对象的名称,作用范围将是此类对象的所有实例。如果希望只授权某种资源对象中的特定实例,则还可以通过资源对象的实例名称(ResourceName)进行设置。在指定ResourceName后,使用get、delete、update和patch的请求就会被限制在这个资源实例范围内。例如,下面的设置让一个主体只能对名为“my-configmap”的ConfigMap资源对象进行get和update操作,而不能操作其他ConfigMap资源对象:


可想而知,resourceName这种用法对list、watch、create或deletecollection操作是无效的,这是因为必须要通过URL进行鉴权,而资源名称在list、watch、create或deletecollection请求中只是请求Body数据的一部分。
Kubernetes支持将多个ClusterRole聚合成一个新的ClusterRole,这在希望将多个ClusterRole的授权规则(例如由CRD或Aggregated API Server提供的资源授权规则)进行合并使用时,可以简化管理员的手工配置工作,完成对系统默认ClusterRole的扩展。
在聚合ClusterRole的定义中,通过aggregationRule字段设置需要包含的ClusterRole,使用Label Selector的形式进行设置,逻辑为包含具有指定标签的ClusterRole。Kubernetes Master中的Controller会根据Label Selector持续监控系统中的ClusterRole,将选中的多个ClusterRole的规则进行合并,形成一个完整的授权规则列表(在rules字段中体现)。
下面是一个聚合ClusterRole示例,其Label Selector设置的条件为包含标签rbac.example.com/aggregate-to-monitoring=true的全部ClusterRole。

如果用户创建了一个包含上述标签的ClusterRole,则系统会自动为聚合ClusterRole设置其rules。例如创建一个查看services、endpoints、pods的ClusterRole:


查看之前创建的聚合ClusterRole,将看到系统自动为其设置的rules:

下面再看看如何使用聚合规则对系统默认的ClusterRole进行扩展。
Kubernetes系统内置了许多ClusterRole,包括admin、edit、view等(完整列表和说明参见下文中的说明),其中的某些ClusterRole本身就是聚合类型的(通过aggregationRule设置了需要聚合的ClusterRole的Label),例如名为“edit”的ClusterRole设置的聚合规则如下:

名为“view”的ClusterRole则包含标签rbac.authorization.k8s.io/aggregate-to-edit=true,说明edit中的规则都将被设置到admin的规则中:

而名为“view”的ClusterRole本身也是聚合类型的,其聚合规则为包含标签rbac.authorization.k8s.io/aggregate-to-view=true:

假设用户希望为其自定义资源对象crontabs设置只读权限,并加入系统内置的名为“view”的ClusterRole中,则基于view设置的聚合规则,用户只需新建一个ClusterRole,并设置其标签为“rbac.authorization.k8s.io/aggregate-to-view=true”,即可将相关授权规则添加到view的权限列表中:

下面对常见的角色(Role)和角色绑定(RoleBinding)内容进行示例说明,在本示例中仅展示关键rules配置的授权规则内容,省略资源对象本身的元数据内容。
(1)允许读取Pod资源对象(属于Core API Group)的信息:

(2)允许读写extensions和apps两个API Group中deployment资源对象的信息:

(3)允许读取Pod资源对象的信息,并允许读写batch和extensions两个API Group中Job资源对象的信息:

(4)允许读取名为“my-config”的ConfigMap资源对象的信息(必须绑定到一个RoleBinding来限制一个命名空间中的特定ConfigMap实例):

(5)读取Node资源对象(属于Core API Group)的信息,由于Node是集群级别的资源对象,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定:

(6)允许对非资源类型的/healthz端点(Endpoint)及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):

在RBAC系统中,通过角色绑定(RoleBinding或ClusterRoleBinding)的定义,将在角色(Role或ClusterRole)中设置的授权规则与某个目标主体(Subject)绑定。授权的目标主体可以是用户(User)、用户组(Group)和ServiceAccount三者之一。
用户名由字符串进行标识,例如人名(alice)、Email地址(bob@example.com)、用户ID(1001)等,通常应该在客户端CA证书中进行设置。需要注意的是,Kubernetes内置了一组系统级别的用户/用户组,以“system:”开头,用户自定义的名称不应该使用这个前缀。
用户组与用户名类似,由字符串进行标识,通常也应该在客户端CA证书中进行设置,并且要求不以“system:”为前缀。
ServiceAccount在Kubernetes系统中的用户名会被设置成以“system:serviceaccount:”为前缀的名称,其所属的组名会被设置成以“system:serviceaccounts:”为前缀的名称。
下面对常见的角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding)进行示例说明,在本示例中仅展示关键subject的授权目标的主体设置,省略资源对象本身的元数据及需要引用的授权规则(Role或ClusterRole)的内容。
(1)为用户alice@example.com授权:

(2)为frontend-admins组授权:

(3)为kube-system命名空间中的默认Service Account授权:

(4)为qa命名空间中的所有Service Account授权:

(5)为所有命名空间中的所有Service Account授权:

(6)为所有已认证用户授权:

(7)为所有未认证用户授权:

(8)为全部用户授权:

API Server会创建一组系统默认的ClusterRole和ClusterRoleBinding对象,其中很多都是以“system:”为前缀的,以表明这些资源被Kubernetes master直接管理,对这些对象的改动可能会造成集群故障。例如system:node这个ClusterRole为kubelet设置了对Node的操作权限,如果这个ClusterRole被改动,kubelet就可能无法正常工作。
所有系统默认的ClusterRole和RoleBinding都会用标签kubernetes.io/bootstrapping=rbac-defaults进行标记。
授权规则的自动恢复(Auto-reconciliation)功能从Kubernetes 1.6版本开始引入。每次集群启动时,API Server都会更新默认的集群角色的缺失权限,也会更新在默认的角色绑定中缺失的主体,这样就防止了一些破坏性的修改,也保证了在集群升级的情况下相关内容能够及时更新。如果不希望使用这一功能,则可以为一个默认的集群角色或者集群角色绑定设置annotation“rbac.authorization.kubernetes.io/autoupdate=false”。该自动恢复功能在启用RBAC授权模式后自动开启。
下面对系统提供的默认授权规则(ClusterRole和ClusterRoleBinding)进行说明。
默认的集群角色绑定(ClusterRoleBinding)为已认证用户(authenticated)和未认证用户(unauthenticated)都授予了读取系统API信息的权限,系统默认访问这些API安全。
如果不希望匿名用户访问API,则可以通过kube-apiserver服务的启动参数设置--anonymous-auth=false。
该默认集群角色(ClusterRole)的名称为“system:discovery”,可以通过kubectl get命令查看其允许访问的各个API路径的授权策略:


API发现相关的系统默认ClusterRole如表6.1所示。
表6.1 API发现相关的默认ClusterRole

有些系统的默认角色不是以“system:”为前缀的,这部分角色是面向用户设置的。其中包含超级用户角色(cluster-admin)、集群级别授权的角色(cluster-status),以及面向命名空间授权的角色(admin、edit、view)。
面向用户的ClusterRole允许管理员使用聚合ClusterRole(Aggretated ClusterRole)机制将多个ClusterRole进行组合,通常用于将用户自定义CRD资源对象的授权补充到系统默认的ClusterRole中进行扩展。对聚合ClusterRole的详细说明请参考前文的说明。
面向用户的系统默认ClusterRole如表6.2所示。
表6.2 面向用户的默认ClusterRole

核心系统组件的默认ClusterRole如表6.3所示。
表6.3 核心系统组件的默认ClusterRole

▼续表

其他组件的默认ClusterRole如表6.4所示。
表6.4 其他组件角色

在Kubernetes Master核心组件Controller Manager中运行了管理各种资源的控制器(Controller)。如果kube-controller-manager服务设置了启动参数--use-service-account-credentials,kube-controller-manager服务就会为每一个Controller都设置一个单独的ServiceAccount。相关的ClusterRole已在系统中默认设置完成,这些ClusterRole的名称以“system:controller:”为前缀。如果kube-controller-manager服务没有设置启动参数--use-service-account-credentials,就会使用它自身的凭据运行所有Controller,这就要求管理员对kube-controller-manager凭据进行全部Controller所需规则的授权。
系统内置控制器(Controller)的默认ClusterRole如表6.5所示。
表6.5 系统内置控制器(Controller)的默认ClusterRole

▼续表

RBAC API防止用户通过编辑Role或者RoleBinding获得权限的提升。这一限制是在API级别生效的,因此即使没有启用RBAC,也仍然有效。
用户要对角色(Role或ClusterRole)进行创建或更新操作,需要满足下列至少一个条件:
(1)用户已拥有Role中包含的所有权限,且与该角色的生效范围一致(如果是集群角色,则是集群范围;如果是普通角色,则可能是同一个命名空间或者整个集群)。
(2)用户被显式授予针对Role或ClusterRole资源的提权(Escalate)操作权限。
例如,用户user-1没有列出集群中所有Secret资源的权限,就不能创建具有这一权限的集群角色。要让一个用户能够创建或更新角色,则需要:
(1)为其授予一个允许创建或更新Role或ClusterRole资源对象的角色。
(2)为其授予允许创建或更新角色的权限,有隐式和显式两种方法。
◎ 隐式:为用户授予这些权限。用户如果尝试使用尚未被授予的权限来创建或修改Role或ClusterRole,则该API请求将被禁止。
◎ 显式:为用户显式授予rbac.authorization.k8s.io API Group中的Role或ClusterRole的提权(Escalate)操作权限。
仅当我们已经拥有被引用的角色(Role或ClusterRole)中包含的所有权限(与角色绑定的作用域相同)或已被授权对被引用的角色执行绑定(bind)操作时,才能创建或更新角色绑定(RoleBinding或ClusterRoleBinding)。例如,如果用户user-1没有列出集群中所有Secret资源的权限,就无法为一个具有这样权限的角色创建ClusterRoleBinding。要使用户能够创建或更新角色绑定,则需要进行以下操作。
(1)为其授予一个允许创建和更新RoleBinding或ClusterRoleBinding的角色。
(2)为其授予绑定特定角色的权限,有隐式或显式两种方法。
◎ 隐式:授予其该角色中的所有权限。
◎ 显式:授予在特定角色或集群角色中执行绑定(bind)操作的权限。
例如,通过下面的ClusterRole和RoleBinding设置,将允许用户user-1为其他用户在user-1-namespace命名空间中授予admin、edit及view角色的权限:

在系统初始化过程中启用第1个角色和角色绑定时,必须让初始用户具备其尚未被授予的权限。要进行初始的角色和角色绑定设置,有以下两种办法。
(1)使用属于system:masters组的凭据,这个组默认具有cluster-admin这个超级用户的权限。
(2)如果API Server以--insecure-port参数运行,则客户端通过这个非安全端口进行接口调用,通过这个非安全端口的访问没有认证鉴权的限制。
除了使用YAML文件创建RBAC角色和角色绑定资源对象,也可以使用kubectl命令行工具管理RBAC相关资源,下面通过示例进行说明。
在Namespace范围内设置授权规则,示例如下。
(1)创建名为“pod-reader”的Role,允许对Pod进行get、watch、list操作:

(2)创建名为“pod-reader”的Role,允许对特定名称(resourceNames)的Pod进行get操作:

(3)创建名为“foo”的Role,允许对API Group“apps”中的replicaset进行get、watch、list操作:

(4)创建名为“foo”的Role,允许对Pod及其子资源“status”进行get、watch、list操作:

(5)创建名为“my-component-lease-holder”的Role,允许对特定名称(resourceNames)的lease资源进行get、list、watch、update操作:

在集群范围内设置授权规则,示例如下。
(1)创建名为“pod-reader”的ClusterRole,允许对所有命名空间中的Pod进行get、watch、list操作:

(2)创建名为“pod-reader”的ClusterRole,允许对特定名称(resourceNames)的Pod进行get操作:

(3)创建名为“foo”的ClusterRole,允许对API Group“apps”中的replicaset进行get、watch、list操作:

(4)创建名为“foo”的ClusterRole,允许对Pod及其子资源“status”进行get、watch、list操作:

(5)创建名为“foo”的ClusterRole,允许对非资源类型的URL进行get操作:

(6)创建名为“monitoring”的ClusterRole,通过aggregationRule设置其聚合规则:

在特定的命名空间中进行授权(为Subject绑定Role),示例如下。
(1)在命名空间acme中为用户“bob”授权ClusterRole“admin”:

(2)在命名空间acme中为ServiceAccount“myapp”授权ClusterRole“view”:

(3)在命名空间acme中为命名空间myappnamespace中的ServiceAccount“myapp”授权ClusterRole“view”:

在集群范围内进行授权(为Subject绑定ClusterRole),示例如下。
(1)在集群范围内为用户root授权ClusterRole“cluster-admin”:

(2)在集群范围内为用户“system:kube-proxy”授权ClusterRole“system:node-proxier”:

(3)在集群范围内为命名空间acme中的ServiceAccount“myapp”授权ClusterRole“view”:

基于YAML文件创建或更新rbac.authorization.k8s.io/v1版本的RBAC相关API资源对象。如有必要,系统则将创建缺失的资源对象,并为设置了命名空间的资源创建缺失的命名空间资源。
已存在的Role将更新为包含输入对象中的全部权限,并且移除多余的权限(需要设置--remove-extra-permissions参数)。
已存在的RoleBinding将更新为包含输入对象中的全部主体(Subject),并且移除多余的主体(需要设置--remove-extra-subjects参数)。
示例如下。
(1)测试运行RBAC规则,显示将要执行的更改:

(2)应用输入配置中的内容,保留任何额外权限(Role)和任何额外主体(Binding):

(3)应用输入配置中的内容,删除任何额外权限和任何额外主体:

此外,可以通过kubectl--help命令在帮助信息中查看使用说明。
默认的RBAC策略为控制平面组件、节点和控制器授予有限范围的权限,但是不会为命名空间kube-system之外的ServiceAccount授予任何权限(除了所有已认证用户都具有的Discovery权限)。这使得管理员可以为特定的ServiceAccount授予所需的权限。细粒度的权限管理能够提供更高的安全性,但也会提高管理成本。粗放的授权方式可能会给ServiceAccount提供不必要的权限,但更易于管理。
按照从最安全到最不安全的顺序,授权的方法如下。
这个应用需要在Pod的定义中指定一个serviceAccountName,并为其创建ServiceAccount(可以通过API、YAML文件、kubectl create serviceaccount命令等方式创建)。例如为my-namespace中的ServiceAccount“my-sa”授予只读权限:

如果一个应用没有指定serviceAccountName,系统则将为其设置名为“default”的ServiceAccount。需要注意的是,授予ServiceAccount“default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限。
例如,在my-namespace命名空间中为ServiceAccount“default”授予只读权限:


另外,许多Kubernetes系统组件都在kube-system命名空间中使用默认的ServiceAccount运行。要让这些管理组件拥有超级用户权限,则可以把集群级别的cluster-admin权限赋予kube-system命名空间中名为default的ServiceAccount。注意,这一操作意味着kube-system命名空间中的应用默认都有超级用户的权限:

如果希望一个命名空间中的所有应用程序都具有一个角色,那么无论它们使用什么ServiceAccount,都可以为这一命名空间中的ServiceAccount组进行授权。
例如,为my-namespace命名空间中的所有ServiceAccount都赋予只读权限:

如果不想为每个命名空间都管理授权,则可以把一个集群级别的角色授权给所有ServiceAccount。例如,为所有命名空间中的所有ServiceAccount都授予只读权限:

如果用户可以完全不关心权限,则可以把超级用户权限分配给每个ServiceAccount。注意,这让所有应用都具有集群超级用户的权限,同时为能够读取Secret或创建Pod权限的用户也授予集群超级用户的权限:

在Kubernetes 1.6版本之前通常使用的是宽松的ABAC策略,包含为所有ServiceAccount授予完全的API访问权限。
默认的RBAC策略为控制平面组件、节点和控制器授予有限范围的权限,但是不会为命名空间kube-system之外的ServiceAccount授予任何权限。
这样一来,尽管更加安全,却可能会对某些希望自动获得API权限的现有工作负载造成影响,以下是管理过渡的两种方法。
RBAC和ABAC同时运行,并包含已使用的ABAC策略文件,将kube-apiserver的启动参数设置如下:

先由RBAC尝试对请求进行鉴权,如果结果是拒绝访问,系统就继续使用ABAC授权机制,这意味着请求只需要满足RBAC或ABAC之一即可工作。
当kube-apiserver服务对RBAC模块设置的日志级别为5或更高(--vmodule=rbac*=5或--v=5)时,就可以在API Server的日志中看到RBAC的拒绝行为(前缀为RBAC)。可以利用这一信息来确定需要为哪些用户、用户组或ServiceAccount授予哪些权限。
等到集群管理员按照RBAC的方式对相关组件进行了授权,并且在日志中不再出现RBAC的拒绝信息时,就可以移除ABAC认证方式了。
可以使用RBAC的角色绑定,复制一个粗放的ABAC策略。
警告:下面的策略让集群中的所有ServiceAccount都具备了集群管理员权限,所有容器运行的应用都会自动接收ServiceAccount的认证,能够对任意API执行任意操作,包括查看Secret和修改授权。它不是一个推荐的过渡策略。

过渡到使用RBAC授权模式之后,管理员应该调整集群的访问控制策略,以确保它们满足信息安全的相关需求。
Node授权模式针对的Subject是Node,不是user或者应用的Service Account,是专门对kubelet发起的API请求进行授权的管理模式。
Node授权者(node authorizer)允许kubelet发起API操作的资源对象如下。
(1)读取操作:Service、Endpoint、Node、Pod、Secret、ConfigMap、PVC,以及绑定到Node的与Pod相关的持久卷。
(2)写入操作:
◎ Node和Node Status(启用NodeRestriction准入控制器,以限制kubelet只能修改自己节点的信息);
◎ Pod和Pod Status(启用NodeRestriction准入控制器,以限制kubelet只能修改绑定到本节点的Pod信息);
◎ Event。
(3)授权相关操作:
◎ 基于TLS启动引导过程中使用的certificationsigningrequest资源对象的读写操作;
◎ 在代理鉴权或授权检查过程中创建tokenreview和subjectaccessreview资源对象。
为了开启Node授权模式,需要为kube-apiserver设置启动参数--authorization-mode=Node。为了限制kubelet可写的API资源对象,需要为kube-apiserver服务启用NodeRestriction准入插件:--enable-admission-plugins=...,NodeRestriction。
为了获取Node授权者的授权,kubelet需要使用一个凭据,以标识它在system:nodes组内,用户名为system:node:<nodeName>,并且该组名和用户名的格式需要与kubelet TLS启动过程中为kubelet创建的标识匹配。
在将来的版本中,Node授权者可能会添加或删除权限,以确保kubelet具有正确操作所需的最小权限集。总之,Node授权模式正在一步步地收紧集群中每个Node的权限,这也是Kubernetes进一步提升集群安全性的一个重要改进措施。