前言

我们使用 kind K8s 创建各种对象时,默认使用的用户是 admin 用户,具有管理集群的全部权限.

现实多用户场景中,我们不可能都使用 admin 用户,需要按情况分配合适的权限给不同的用户.

Authentication(K8s 鉴权)

指用户是否可以登录 k8s,即向 K8s api-server 发送请求

K8s 集群有两大类用户

  • normal users:外部用户,不属于 K8s 管理
  • service accounts:由 K8s 管理

normal users

normal users 独立于 K8s 集群,由外部服务维护,也就是说,normal users 不是在 K8s 内部创建的,K8s 内部也没有与之对应的对象

外部服务可以是

  • 一个可以分发 private keys 的管理员(真人)
  • 一个提供用户服务的第三方厂商,比如 Google Accounts
  • 一个保存了用户名/密码的简单列表

上面这段可能很难理解,如果一个用户不在 K8s 内部存在(K8s 即不保存用户名又不保存密码),那 K8s 如何鉴权用户(Authentication)?

K8s 有几种鉴权用户的方法,对于使用 kubectl 访问 K8s 的情况,K8 可以使用自己 CA(certificate authority)签发的证书鉴权用户

  • 一般应用系统的鉴权用户过程:我们提供用户名和密码,应用在自己数据库里检查用户名和密码是否存在并有效,有的话就通过用户鉴权
  • 而 K8s 的对于使用 Kubectl(证书验证的情况)的 normal users 鉴权用户的流程为:Normal user(即 kubectl)向 K8s 提供证书,K8s 检查此证书是否有效,有效则通过用户鉴权

所以任何用户,只要能提供有效的证书就可以通过 K8s 用户鉴权,并向 K8s 发送请求(当然请求是否可以执行,还要看有没有权限,即授权 Authorization)

通过用户鉴权之后,K8s 会把证书中 CN 作为用户名(比如, 证书中"/CN=tstest",则用户名就是"tstest")

Organization 作为 group,然后由用户名和 group 绑定的 Role 来决定用户的权限(Authorization)

由此可见,当我们在 linux 环境下,用不同的帐号运行同一个 kubectl 命令行时,kubectl 都是把~/.kube/config 文件中的配置的证书发送给 K8s,然后,K8s 从此证书的 CN 中获得用户名,K8s 并不在意是哪个 Linux 帐号运行了 kubectl 命令

service accounts

service accounts 由 K8s 管理,并属于某个指定的 namespace。service accounts 可以由 K8s 自动创建,也可以用 kubectl 命令人工创建。

与 Normal user 不同,service accounts 存在对应的 K8s 对象,并且与 service accounts 相关的密码信息会作为 Secrets 存在 K8s 中。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: eks-cluster-ssm
  namespace: interview-namespace
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::X:role/eks-cluster-ssm

这些 Secrets 会在 Pod 启动时 mount 到 Pod 中,这样 Pod 中的进程就可以以 service account 的名义向 api-server 发送请求。

normal users VS service accounts

Normal users 和 service accounts 的区别主要体现在以下几点
1.Users 用户是给人用的,而 service accounts 是给 Pods 内的进程用的
2.Users 名称在 K8s 集群内是唯一的,而 service accounts 在建在 namespace 中,所以不同 namespaces 中的 service accounts 名称可以相同
3.上面说过,Users 是外部的并不属于 K8s 管理,所以 Users 一般存在于 K8s 集群外的数据库或者 Idp 中。在 K8s 内部,这些用户只有一个名字和 role 绑定,用来提供 Users 所需要的权限
4.每个 namespace 中都会存在一个 service accounts,或者是人工创建,或者是默认的 ServiceAccount "default",这个 service accounts 由此 namespace 中的 Pod 使用。我们通过给 service accounts 授权,使得此 namespace 中的 Pod 有权限调用 K8s 资源

Api Request 分类

当我们使用 kubectl 命令时,其实就是向 api-server 发送请求(request)

Api request 分为以下三种
1.normal user 发送的请求:比如用 kubectl 命令创建 Pod
2.service account 发送的请求:比如一个 Pod 请求访问存储镜像仓库密码的 Secret,由 Pod 内关联的 service account 发送请求
3.anonymous 请求:除以上两种请求之外的所有请求

可以看到,除了用 kubectl 从 k8s 集群外部向 api-server 发送 request 之外,K8s 内部也会向 api-server 发送 request,并且所有 request 都要首先进行鉴权操作(Authentication)

Authentication 策略

K8s有以下几种鉴权方法
1.client certificates(客户证书)
2.bearer tokens(不记名令牌)
3.authenticating proxy(身份认证代理)
4.通过鉴权插件的 HTTP 基本认证机制

当 http 请求发送给 api-server 时,k8s 会从 request 中关联以下信息

  • Username:代表最终用户的一串字符,比如 kube-admin 或者 tstest@elephdev.com
  • UID:一串唯一字符代表一个用户
  • Groups:代表逻辑相关的一组用户,比如 system:masters 或者 devops-team
  • Extra fields:鉴权可能需要的其它信息

需要注意的是,当多种鉴权方法同时启用时,第一个鉴权方法鉴权成功即通过验证,其它方法不再鉴权,同时 api-server 也不保证鉴权方法的顺序

所有鉴权成功的用户都会加到 group “system:authenticated”中。

client certificates(客户证书)

当我们使用 client certificates 鉴权时,我们需要向 K8s 提供有效证书。

这个证书可以是外部的提供的,也可以是由 K8s 自己审批的

如果是外部提供的,我们需要在启动 api-server 时,用--client-ca-file=SOMEFILE 参数引入外部证书的 CA 等信息,来验证客户端上传证书的有效性。

当客户端上传证书有效性时,K8s 会把证书的 Subject CN 中作为用户名,Organization 作为 Group

bearer tokens(不记名令牌)

bearer tokens 简单理解就是一串字符。

客户端向服务端发送 http 请求时,把 bearer tokens 放在 request 的 header “Authorization”中,服务端通过验证 bearer tokens 的有效性来判断请求是否有效。

在 K8s 中有几种使用 bearer tokens 方法,我们这里只简单说明其中的三种
1.Static Token File

api-server 通过--token-auth-file=SOMEFILE 参数,从一个外部文件(csv)中获得有效的 Token 列表及对应的用户和组

当客户端发来的请求时,api-server 把请求 header 中的 bearer tokens 和文件中的 token 比较,就可以判断请求是否有效

2.Service Account Tokens
当手工或自动创建 Service Account 时,Service Account Tokens 会被自动创建,并作为 K8s 对象“serect”存储在相应的 namespace 中

上面说过 Service Account 主要是为 Pods 提供访问 api-server 的功能,所以 Service Account Tokens 创建好之后会自动 mount 相关的 Pods 中, 这样 Pods 就可以利用这个 Service Account Tokens 对 api-server 发送请求

除了用在 Pods 上,也可以用在 K8s 外部的请求

运行下列命令获取 secret token(Service Account Tokens)

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-cluster-ssm | awk '{print $1}')

image.png

如果拥有访问Dashboard的Service Account则可以直接用TOKEN登录

image.png

这其实就是在 K8s 外部利用 Service Account Tokens 对 api-server 进行访问的实际应用例子

3.OpenID Connect Tokens

K8s 可以利用 OAuth2 token response 中的 ID Token 作为 bearer token 进行验证访问

这样就可以利用支持 OpenID 的第三方的 Idp 来管理 K8s 外部用户

使用 OpenID Connect Tokens 时的主要差别在于——用户先要登录 Idp 并从 Idp 中获取 ID Token 作为 bearer token

K8s Authorization(授权)

1.授权流程

发送到 K8s 的请求首先经过鉴权(Authentication),然后进入到授权(Authorization)阶段。

在授权阶段,K8s 会检查请求是否有权限访问需要的资源,有权限则开始执行请求,无权限则报错返回。

K8s 通过 Api-server,利用请求中的附带信息(包括上面提到的 Username,UID,Group 等)来授权请求(具体授权控制由相应的 Admission Controllers 来执行)。

Api-server 会查找所有的 policy 来检查是否存在 policy 允许请求中的动作,存在则允许请求执行,否则会拒绝执行并返回 403 错误。

当配置了多个授权模块时,请求会按顺序通过每个模块的检查。如果任意模块允许或者拒绝了请求,则这就是最终授权结果,其它授权模块不再继续检查授权。

K8s 在授权时会检查请求中以下信息,部分信息与鉴权时使用的相同

  • user:同鉴权中检查的信息相同
  • group:同鉴权中检查的信息相同
  • extra:同鉴权中检查的信息相同
  • API:是否为 Api 资源
  • Request path:非资源(API 资源)endpoint,比如/healthz
  • API request verb:API 动作,比如 get, list, create, update, patch,对某个资源的具体动作,比如,列出所有的 pod
  • HTTP request verb:用于非资源的请求中的 HTTP 动作,比如 get, post, put
  • Resource:请求访问的资源名字或 ID
  • Subresource:请求访问的子资源名字或 ID
  • Namespace:资源所在的名字空间
  • API group:请求访问的 API group,API group 指控制相关资源的一组 * Api,如果未指定则代表 core API group

2.授权模块

K8s api-server 有如下几种授权模块

1.Node:一种特殊的授权模块,基于 node 上运行的 Pod 授权 kubelets
2.ABAC:基于属性的访问控制
3.RABC:基于角色的访问控制
4.Webhook:HTTP 请求回调,通过一个 web 应用来返回是否有权限进行某项操作

RBAC 授权

Role-based access control (RBAC)通过用户绑定的 role 来控制用户权限

RBAC 有四种 K8s 对象
1.Role:设置对 K8s 资源访问的具体权限,与某个 namesapce 相关联
2.ClusterRole:与 Role 类似,区别是不与某个 namepsace 相关联,针对整个 Cluster
3.RoleBinding:把用户和 Role 绑定,使用户获得具体权限
4.ClusterRoleBinding:与 RoleBinding 类似,区别是不与某个 namepsace 相关联

ClusterRole 有几种用途
1.定义对某个 namespace 中对象的权限,然后授权给其它某些 namespace 中的用户
2.定义对某个 namespace 中对象的权限,然后授权给全部 namespaces 中的用户
3.定义对集群范围的对象的权限

示例:为登录 Dashboard 创建了 serviceaccount admin-user并绑定 Clusterrole cluster-admin

这个 ClusterRole 为 ServiceAccount 提供了访问 Cluster 的全部权限

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system

总结

K8s 用户为两种
1.内部用户(service accounts)主要为 Pod 提供访问 api-server 的服务,有对应的 K8 对象,当然也可以利用其 token 从外部访问
2.外部普通用户(normal user),由 K8s 外部的第三方服务管理,没有对应的 K8s 对象

K8s 通过证书,bearer tokens 等方式鉴权,不通过一般的用户/密码方式鉴权。

K8s 授权的方法有几种,对于 RBAC 方式来说,就是用户,role,role 绑定,三个元素组合在一起进行授权。

点赞(200)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部