共计 9876 个字符,预计需要花费 25 分钟才能阅读完成。
今天就跟大家聊聊有关怎么实现 TKE 及 Kubernetes 访问权限控制,可能很多人都不太了解,为了让大家更加了解,丸趣 TV 小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
下面将会向你介绍腾讯云 TKE 平台侧的访问控制、Kubernetes 访问控制链路,以及演示如何将平台侧账号对接到 Kubernetes 内。
当你在使用腾讯云容器服务 TKE(Tencent Kubernetes Engine)的时候,如果多人共用一个账号的情况下,是否有遇到以下问题呢?
密钥由多人共享,泄密风险高。
无法限制其他人的访问权限,其他人误操作易造成安全风险。
为了解决以上问题,腾讯云 CAM(Cloud Access Management)提供了主账号和子账号的认证体系以及基于角色的权限控制。
而不同的子账号对于 TKE 平台侧资源的控制粒度比较粗(cluster 实例级别),又会遇到以下问题:
同一个集群由多子账号可访问,无法保证集群资源级别、命名空间级别的读写控制。
集群的高权限子账户无法对低权限子账户进行授权管理。
为了解决以上两个问题,TKE 针对平台侧资源、Kubernetes 资源分别进行相应的访问控制管理。
平台侧访问控制
首先介绍下什么是平台侧资源,平台侧资源即 Cluster 资源、CVM 资源、CLB 资源、VPC 资源等腾讯云资源,而访问的用户主要分为用户和服务角色载体。
用户就是我们平时登录控制台的主账号、子账号或者协作者账号
服务角色是一种定义好带有某些权限的角色,可以将这个角色赋予某个载体,可以是某个其他账户,也可以是腾讯云下一个产品的服务提供者,CAM 会默认为产品提供一个预设的载体和默认的角色,例如 TKE 的默认角色就是 TKE_QCSRole,而载体就是 ccs.qcloud.com。
而这个角色有什么用处呢?举个 TKE 的例子,比如 TKE 的 service-controller 会 Watch 集群内的 Service 资源,如果需要创建 LoadBalance 类型的 Service,会通过云 API 购买并创建 CLB 资源,而 service-controller 是 TKE 平台为用户部署的,去访问云 API 需要有身份,这个身份就是 ccs.qcloud.com 载体,而权限则需要用户给载体授予一个角色,即 TKE_QCSRole。只有用户在授权 TKE 载体之后,TKE 才可以通过服务扮演的方式代替用户购买 CLB。下面我会简单为你介绍如何给用户授权,以及如何给 TKE 平台授予角色。
定制策略
TKE 通过接入 CAM,对集群的 API 接口级别进行权限细分,需要您在 CAM 控制台对子账户进行不同的权限授予。同时 TKE 也在 CAM 侧提供了预设的权限,提供您默认选择,例如:
也可以自定义策略,具体策略定制请参考 CAM 产品介绍文档
例如拥有只读权限的子账户尝试修改集群名称,将会在 API 接口时校验 CAM 权限失败
划分用户组
可以依据团队的职责划分好用户组,将之前规划好的自定义策略绑定到一个用户组上,来方便的进行权限管理。例如:有新同学入职时可方便的加入指定用户组(如运维组),就可以获取到该用户组的权限,避免了繁琐的权限配置操作。
授予 TKE 角色权限
使用 TKE 容器服务需要授予 TKE 平台为您操作 CVM\CLB\VPC\CBS 等权限,所以首次访问 TKE 控制台需要确保同意授权,即创建预设角色 TKE_QCSRole,此角色默认授予 TKE 载体,该载体会通过 CAM 获取操作您集群的临时密钥,来进行相应的云 API 操作。
更多
更多丰富的平台侧访问控制用法请访问 CAM 产品说明文档
Kubernetes 访问控制
介绍完平台侧资源的访问控制,我们再来看看 TKE 集群内的资源如何进行权限管理。当不同的子账户都拥有访问同一个 TKE Kubernetes 集群权限之后,如何保证不同的子账户,对于集群内资源拥有不同的角色和权限呢?让我们首先从社区的 Kubernetes 访问链路来分析整个过程,从而向您介绍 TKE 是如何实现容器服务子账户对接 Kubernetes 认证授权体系的。
Overview
首先从宏观的角度看下 Kubernetes 的请求链路是如何进行的。图片来源于 k8s 社区官网。
可以大概了解到一个请求的链路是依次通过 Authentication(认证,简称 Authn)、Authorization(授权,简称 Authz)、AdmissionControl(准入控制),从而获取到后端持久化的数据。
从图中可以看到 Authn、Authz、AdmissionControl 是由多个模块组成的,每个步骤都有多种方式构成的。
在进入认证模块之前会将 HTTP 的 Request 进行构建 context,而 context 中就包含了用户的 RequestInfo,userInfo、Verb、APIGroup、Version、Namespace、Resource、Path 等。
带着这些信息,下面我们来一次看下准入过程中的每个步骤吧。
Kubernetes 认证
认证的过程的证明 user 身份的过程。
Kubernetes 中有两类用户,一类是 ServiceAccount,一类是集群真实的用户。
ServiceAccount 账户是由 Kubernetes 提供 API(资源)进行创建和管理的,ServiceAccount 可以认为是特殊的 Secret 资源,可用户集群内资源访问 APIServer 的认证所用。通过可以通过 mount 的方式挂载到 Pod 内进行使用。
真实的用户通常是从外部发起请求访问 APIServer,由管理员进行管理认证凭证,而 Kubernetes 本身不管理任何的用户和凭证信息的,即所有的用户都是逻辑上的用户,无法通过 API 调用 Kubernetes API 进行创建真实用户。
Kubernetes 认证的方式众多,常见的有 TLS 客户端证书双向认证、BearerToken 认证、BasicAuthorization 或认证代理(WebHook)
所有的认证方式都是以插件的形式串联在认证链路中,只要有一种认证方式通过,即可通过认证模块,且后续的认证方式不会被执行。
在此处参考一点点 Kubernetes APIServer Authentication 模块的代码,可以发现,任何的认证方式都是一下 Interface 的实现方式都是接收 http Request 请求,然后会返回一个 user.Info 的结构体,一个 bool,以及一个 error
// Request attempts to extract authentication information from a request and returns
// information about the current user and true if successful, false if not successful,
// or an error if the request could not be checked.
type Request interface { AuthenticateRequest(req *http.Request) (user.Info, bool, error)
}
user.Info 中包含了用户的信息,包括 UserName、UUID、Group、Extra。
bool 返回了用户是否通过认证,false 的话即返回无法通过认证,即返回 401 错误。
error 则返回了当 Request 无法被检查的错误,如果遇到错误则会继续进行下一种注册的方式进行认证。
如果认证通过,则会把 user.Info 写入到到请求的 context 中,后续请求过程可以随时获取用户信息,比如授权时进行鉴权。
下面我会以 Kubernetes 代码中的认证方式顺序,挑选几项认证方式,并结合 TKE 开启的认证方式来向你介绍 TKE 创建的 Kubernetes 集群默认的认证策略。
Basic Authentication
APIServer 启动参数 –basic-auth-file=SOMEFILE 指定 basic 认证的 csv 文件,在 APIServer 启动之后修改此文件都不会生效,需要重启 APIServer 来更新 basic authentication 的 token。csv 文件格式为:token,user,uid, group1,group2,group3。
请求时,需要指定 HTTP Header 中 Authentication 为 Basic,并跟上 Base64Encode(user:passward) 值。
x509 客户端证书
APIServer 启动参数 –client-ca-file=SOMEFILE 指定 CA 证书,而在 TKE 的 K8s 集群创建过程中,会对集群进行自签名 CA 密钥和证书用于管理,如果用户下发的客户端证书是由此 CA 证书的密钥签发的,那么就可以通过客户端证书认证,并使用客户端证书中的 CommonName、Group 字段分别作为 Kubernetes 的 UserInfo 中 Username 和 Group 信息。
目前 TKE 对接子账户都是通过自签名的 CA 凭证进行签发子账户 Uin 对应 CN 的客户端证书。
Bearer Token
Bearer Token 的认证方式包含很多,比如启动参数指定的、ServiceAccount(也是一种特殊的 BeaerToken)、BootstrapToken、OIDCIssure、WebhookToken
1. 默认指定 Token csv 文件
APIServer 启动参数 –token-auth-file=SOMEFILE 指定 Bearer Token 认证的 csv 文件。和 Basic Authentication 方式相似,只不过请求 APIServer 时,指定的 HTTP 认证方式为 Bearer 方式。此 Bearer 后直接跟 passward 即可。csv 文件格式为:password,user,uid, group1,group2,group3。
请求时,需要指定 HTTP Header 中 Authentication 为 Bearer,并跟上 Base64Encode(user:passward) 值。
2. ServiceAccount
ServiceAccount 也是一种特殊 beaer token,ServiceAccount 在 Kubernetes 中是一种资源,创建一个 ServiceAccount 资源之后默认会创建一个 Secret 资源,而 Secret 资源中就包含了一个 JWT 格式的 Token 字段,以 Bearer Token 的方式请求到 Kube-APIServer,Kube-APIServer 解析 token 中的部分 user 信息,以及 validate 以下 ServiceAccount 是否存在即可进行认证检查。这种方式即之前提到的“两种用户”中常见的集群内认证方式,ServiceAccount,主要用于集群内资源访问 APIServer,但不限于集群内。
3. BootstrapToken
此项开关在 Kubernetes v1.18 版本中才为 stable 版本,此类 Token 是专门用来引导集群安装使用的,需要配合 controller-manager 的 TokenCleaner。
目前 TKE 默认开启此配置。
4. OpenID Connect Tokens
OIDCToken 的认证方式是结合 OAuth3 向身份提供方获取 ID Token 来访问 APIServer。
如需要开启此项功能,需要在 APIServer 的启动参数中指定 oidc 的配置参数,例如 –oidc-issuer-url 指定 oidc 身份提供方的地址,–oidc-client-id 指定身份提供方侧的账户 ID,–oidc-username-claim 身份提供方的用户名。
具体可参考 Kubernetes 官方文档,目前公有云 TKE 没有使用此参数对接腾讯云账户,因为涉及用户需要主动登录授权后才可返回 Id Token,和当前官网交互冲突,可以在后续 CLI 工具中实现。
5. Webhook Token Server
Webhook Token 是一种 hook 的方式来校验是否认证通过。
APIServer 启动参数 –authentication-token-webhook-config-file 及 –authentication-token-webhook-cache-ttl 来分别指定 Webhook 地址以及 token 的 cache ttl。
若 APiServer 开启此方式进行认证校验,则在接受到用户的 Request 之后,会包装 Bearer Token 成一个 TokenReview 发送给 WebHookServer,Server 端接收到之后会进行校验,并返回 TokenReview 接口,在 status 字段中进行反馈是否通过校验通过和 user.Info 信息。
总结
以上即为 Kubernetes APIServer 认证的几种方式,TKE 在每种认证方式都有支持。供用户灵活使用。
目前 TKE 正在推使用 x509 客户端证书方式来进行认证管理,以方便进行对接子账户的创建、授权管理、更新。
Kubernetes 授权
Kubernetes 的授权模式支持一下几种,和认证一样,参考开始说的 RequestInfo context,可知用户 Reqeust 的 context 除了认证需要的 userInfo,还有一些其他的字段例如 Verb、APIGroup、APIVersion、Resource、Namespaces、Path……
授权就是判断 user 是否拥有操作资源的相应权限。
Kubernetes 支持 AlwaysAllow、AlwaysDeny、Node、ABAC、RBAC、Webhook 授权 Mode,和认证一样,只要有一种鉴权模块通过,即可返回资源。
在这里重点介绍下面两种方式
RBAC
RBAC(Role-Based Access Control),Kubernetes 提供 ClusterRole、Role 资源,分别对应集群维度、Namespace 维度角色权限管控,用户可以自定义相应的 ClusterRole、Role 资源,绑定到已经认证的 User 之上。
如下 tke:pod-reader ClusterRole,定义了该角色可以访问 core apigroup 下面对 pods 资源的 get/watch/list 操作
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: tke:pod-reader
rules:
- apiGroups: [ ] # 指定核心 API 组
resources: [pods]
verbs: [get , watch , list]
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定使得用户 alex 能够读取 default 命名空间中的 Pods
kind: ClusterRoleBinding
metadata:
name: alex-ClusterRole
subjects:
- kind: User
name: alex
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tke:pod-reader # 这里的名称必须与你想要绑定的 Role 或 ClusterRole 名称一致
apiGroup: rbac.authorization.k8s.io
通过以上的 yaml 配置,通过认证模块到达授权模块的 requestInfo 中 userInfo 信息是 alex 的请求,在授权模块中走到 RBAC 授权模块时,则会进行查询集群的 ClusterRole/ClusterRoleBinding 信息。进行判断是否拥有 context 相应操作的权限。
TKE 的对接子账户的权限授权策略就是使用的 Kubernetes 原生的 RBAC 进行对子账户资源访问控制,这样符合原生,符合有 K8s 使用习惯的用户。
WebHook
Webhook 模式是一种基于 HTTP 回调的方式,通过配置好授权 webhook server 地址。当 APIServer 接收到 request 的时候,会进行包装 SubjectAccessReview 请求 Webhook Server,Webhook Server 会进行判断是否可以访问,然后返回 allow 信息。
以下是 kubernetes 社区一个例子,以供参考。
{
apiVersion : authorization.k8s.io/v1beta1 ,
kind : SubjectAccessReview ,
spec : {
resourceAttributes : {
namespace : kittensandponies ,
verb : get ,
group : unicorn.example.org ,
resource : pods
},
user : alex ,
group : [
group1 ,
group2
]
}
apiVersion : authorization.k8s.io/v1beta1 ,
kind : SubjectAccessReview ,
status : {
allowed : true
}
}
目前 TKE 没有考虑使用 Webhook 的模式,但是 Webhook 模式提供了强大的灵活性,比如对接 CAM,实现 K8s 权限对接到平台侧,但是也有一定的风险和挑战,比如依赖 CAM 的稳定性;请求延迟、缓存 /TTL 的配置;CAM action 配置与 K8s 权限对应关系。此项授权模式仍然在考虑中,有需求的用户可以反馈。
准入控制
什么是 admission controller?
In a nutshell, Kubernetes admission controllers are plugins that govern and enforce how the cluster is used.
Admission controllers 是 K8s 的插件,用来管理和强制用户如何来操作集群。
Admission controllers 主要分为两个 phase,一个是 mutating,一个是 validating。这两个阶段都是在 authn authz 之后的,mutating 做的变更准入,就是会对 request 的 resource,进行转换,比如填充默认的 requestLimit?而 validating admission 的意思就是验证准入,比如校验 Pod 副本数必须大于 2。
API Server 请求链路:
ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks, both of which are in beta status as of Kubernetes 1.13.
k8s 支持 30 多种 admission control 插件,而其中有两个具有强大的灵活性,即 ValidatingAdmissionWebhooks 和 MutatingAdmissionWebhooks,这两种控制变换和准入以 Webhook 的方式提供给用户使用,大大提高了灵活性,用户可以在集群创建自定义的 AdmissionWebhookServer 进行调整准入策略。
TKE 中 1.10 及以上版本也默认开启了 ValidatingAdmissionWebhooks、MutatingAdmissionWebhooks
了解更多 Admission Controller 参考这里
kubernetes 权限对接子账户
TKE 权限实现对接子账户主要的方案是:x509 客户端认证 +Kubernetes RBAC 授权。
认证
每个子账户都拥有单独的属于自己的客户端证书,用于访问 KubernetesAPIServer。
用户在使用 TKE 的新授权模式时,不同子账户在获取集群访问凭证时,即前台访问集群详情页或调用 DescribeClusterKubeconfig 时,会展示子账户自己的 x509 客户端证书,此证书是每个集群的自签名 CA 签发的。
该用户在控制台访问 Kubernetes 资源时,后台默认使用此子账户的客户端证书去访问用户 Kubernetes APIServer。
支持子账户更新自己的证书。
支持主账户或集群 tke:admin 权限的账户进行查看、更新其他子账户证书。
授权
TKE 控制台通过 Kubernetes 原生的 RBAC 授权策略,对子账户提供细粒度的 Kubernetes 资源粒度权限控制。
提供授权管理页,让主账号和集群创建者默认拥有管理员权限,可以对其他拥有此集群 DescribeCluster Action 权限的子账户进行权限管理。
并提供预设的 ClusterRole。
开发人员(tke:ns:dev):对所选命名空间下控制台可见资源的读写权限,需要选择指定命名空间。
只读用户(tke:ns:ro):对所选命名空间下控制台可见资源的只读权限,需要选择指定命名空间。
管理员(tke:admin):对所有命名空间下资源的读写权限,对集群节点,存储卷,命名空间,配额的读写权限,可子账号和权限的读写权限
运维人员(tke:ops):对所有命名空间下控制台可见资源的读写权限,对集群节点,存储卷,命名空间,配额的读写权限
开发人员(tke:dev):对所有命名空间下控制台可见资源的读写权限
受限人员(tke:ro):对所有命名空间下控制台可见资源的只读权限
用户自定义 ClusterRole
所有命名空间维度:
指定命名空间维度:
所有预设的 ClusterRole 都将带有固定 label:cloud.tencent.com/tke-rbac-generated: true
所有预设的 ClusterRoleBinding 都带有固定的 annotations:cloud.tencent.com/tke-account-nickname: yournickname,及 label:cloud.tencent.com/tke-account: yourUIN
更多
当然,除了 TKE 控制台提供的预设授权策略,管理员也可以通过 kubectl 操作 ClusterRole/Role 来实现自定义角色的灵活配置细粒度权限,以及操作 ClusterRoleBinding/RoleBinding 进行权限绑定,绑定到任意的角色权限之上。
例如你想设置 CAM 侧用户组为 productA 产品的 pod-dev 的用户权限只能够 get/list/watch product- a 命名空间下的 pods 资源,则你可以这样操作:
创建自定义 ClusterRole/Role:dev-pod-reader,yaml 实例如下,文件名为 developer.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole # 这里使用 ClusterRole 可以复用给产品其他命名空间
metadata:
name: pod-dev # pod-dev 此角色为只能读取 pod 的开发
rules:
- apiGroups: [ ] # 指定核心 API 组
resources: [pods]
verbs: [get , watch , list]
使用 kubectl 或者通过 TKE 控制台 YAML 创建资源创建上述 Role
绑定 dev 用户组下的 dev1、dev2、dev3 用户,绑定自定义权限 pod-dev 到 product- a 命名空间下
从此 dev1,dev2,dev3 用户则只能使用 get/list/watch 访问 product- a 下的 pods 资源
$ kubectl --kubeconfig=./dev.kubeconfig get pods
Error from server (Forbidden): pods is forbidden: User 10000001xxxx-1592395536 cannot list resource pods in API group in the namespace default
$ kubectl --kubeconfig=./dev.kubeconfig get pods -n product-a
No resources found.
看完上述内容,你们对怎么实现 TKE 及 Kubernetes 访问权限控制有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注丸趣 TV 行业资讯频道,感谢大家的支持。