访问控制概述
用户使用 kubectl
、客户端库或构造 REST 请求来访问 Kubernetes API。 人类用户和 Kubernetes 服务账户都可以被鉴权访问 API。 当请求到达 API 时,它会经历多个阶段,如下图所示:
访问流程
api-server 是访问和管理资源对象的唯一入口。任何一个请求访问 api-server,都要经过下面的三个流程:
-
- ① Authentication(认证):身份鉴别,只有正确的账号才能通过认证。
-
- ② Authorization(授权):判断用户是否有权限对访问的资源执行特定的动作。
-
- ③ Admission Control(准入控制):用于补充授权机制以实现更加精细的访问控制功能。
用户分类
所有 Kubernetes 集群都有两类用户:由 Kubernetes 管理的服务账号(Service Account )和普通用户(User Accounts)。
Kubernetes 假定普通用户是由一个与集群无关的服务通过以下方式之一进行管理的:
- 负责分发私钥的管理员
- 类似 Keystone 或者 Google Accounts 这类用户数据库
- 包含用户名和密码列表的文件
有鉴于此,Kubernetes 并不包含用来代表普通用户账号的对象。 普通用户的信息无法通过 API 调用添加到集群中。
尽管无法通过 API 调用来添加普通用户, Kubernetes 仍然认为能够提供由集群的证书机构签名的合法证书的用户是通过身份认证的用户。 基于这样的配置,Kubernetes 使用证书中的 ‘subject’ 的通用名称(Common Name)字段 (例如,“/CN=bob”)来确定用户名。 接下来,基于角色访问控制(RBAC)子系统会确定用户是否有权针对某资源执行特定的操作
与此不同,服务账号是 Kubernetes API 所管理的用户。它们被绑定到特定的名字空间, 或者由 API 服务器自动创建,或者通过 API 调用创建。服务账号与一组以 Secret 保存的凭据相关,这些凭据会被挂载到 Pod 中,从而允许集群内的进程访问 Kubernetes API。
Service Account 在不指定时,会自动帮我们创建一个default账号。它下面有三个组件管理:
Service Account Admission Controller
:通过 Admission Controller 插件来实现对 pod 修改,它是 apiserver 的一部分。创建或更新 pod 时会同步进行修改 pod。当插件处于激活状态(在大多数发行版中都默认情况)创建或修改 pod 时,会按以下操作执行:- 如果 pod 没有设置 ServiceAccount,则将 ServiceAccount 设置为 default。
- 确保 pod 引用的 ServiceAccount 存在,否则将会拒绝请求。
- 如果 pod 不包含任何 ImagePullSecrets,则将ServiceAccount 的 ImagePullSecrets 会添加到 pod 中。
- 为包含 API 访问的 Token 的 pod 添加了一个 volume。
- 把 volumeSource 添加到安装在 pod 的每个容器中,挂载在 /var/run/secrets/kubernetes.io/serviceaccount。
Token Controller
:TokenController 作为 controller-manager 的一部分运行。异步行为:- 观察 serviceAccount 的创建,并创建一个相应的 Secret 来允许 API 访问。
- 观察 serviceAccount 的删除,并删除所有相应的ServiceAccountToken Secret
- 观察 secret 添加,并确保关联的 ServiceAccount 存在,并在需要时向 secret 中添加一个 Token。
- 观察 secret 删除,并在需要时对应 ServiceAccount 的关联
Service Account Controller
:Service Account Controller 在 namespaces 里管理ServiceAccount,并确保每个有效的 namespaces 中都存在一个名为 “default” 的 ServiceAccount。
认证方式
Kubernetes 集群安全的关键点在于如何识别并认证客户端身份,它提供了 3 种客户端身份认证方式:
① HTTP Base 认证:
-
- 通过
用户名+密码
的方式进行认证。
- 通过
-
- 这种方式是把
用户名:密码
用 BASE64 算法进行编码后的字符串放在 HTTP 请求中的 Header 的 Authorization 域里面发送给服务端。服务端收到后进行解码,获取用户名和密码,然后进行用户身份认证的过程。
- 这种方式是把
② HTTP Token 认证:
-
- 通过一个 Token 来识别合法用户。
-
- 这种认证方式是用一个很长的难以被模仿的字符串–Token 来表明客户端身份的一种方式。每个 Token 对应一个用户名,当客户端发起 API 调用请求的时候,需要在 HTTP 的 Header 中放入 Token,API Server 接受到 Token 后会和服务器中保存的 Token 进行比对,然后进行用户身份认证的过程。
③ HTTPS 证书认证:
-
- 基于 CA 根证书签名的双向数字证书认证方式。
-
- 这种认证方式是安全性最高的一种方式,但是同时也是操作起来最麻烦的一种方式。
授权
Kubernetes 使用 API 服务器对 API 请求进行鉴权。 它根据所有策略评估所有请求属性来决定允许或拒绝请求。 一个 API 请求的所有部分都必须被某些策略允许才能继续。 这意味着默认情况下拒绝权限。
当系统配置了多个鉴权模块时,Kubernetes 将按顺序使用每个模块。 如果任何鉴权模块批准或拒绝请求,则立即返回该决定,并且不会与其他鉴权模块协商。 如果所有模块对请求没有意见,则拒绝该请求。 被拒绝响应返回 HTTP 状态代码 403。
授权策略
-
AlwaysDeny:表示拒绝所有请求,一般用于测试。
-
AlwaysAllow:允许接收所有的请求,相当于集群不需要授权流程(Kubernetes 默认的策略)。
-
ABAC:基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制。
-
Webhook:通过调用外部REST服务对用户进行授权。
-
Node:是一种专用模式,用于对 kubelet 发出的请求进行访问控制。
-
RBAC:基于角色的访问控制( kubeadm 安装方式下的默认选项)。
RBAC
RBAC(Role Based Access Control):基于角色的访问控制,主要是在描述一件事情:给哪些对象授权了哪些权限。
RBAC 模型:
Kubernetes 中的 RBAC 也是基于 RBAC 模型扩展的,涉及到如下的概念:
-
- 对象:User、Group、ServiceAccount。
-
- 角色:代表一组定义在资源上的可操作的动作(权限)的集合。
-
- 绑定:将定义好的角色和用户绑定在一起,也可以理解为分配角色。
RBAC 引入了 4 个顶级资源对象:
-
- Role:角色,用于指定一组权限,限定名称空间下的权限。
-
- ClusterRole:集群角色,用于指定一组权限,限定集群范围下的权限。
-
- RoleBinding:角色绑定,用于将角色 Role(权限的集合)赋予给对象(User、Group、ServiceAccount)。
-
- ClusterRoleBinding:集群角色绑定,用于将集群角色 Role(权限的集合)赋予给对象(User、Group、ServiceAccount)。
说明:为什么 Kubernetes 要设计 Role 、 ClusterRole ?
答:有些资源对象本身就不是 namespace(名称空间)的 ,所以 Kubernetes 增加了 ClusterRole,并且 ClusterRole 也可以管理名称空间下的资源对象。
Role 和 ClusterRole资源清单
一个角色就是一组权限的集合,这里的权限都是许可形式的(白名单)。
Role 的资源清单文件:
# 名称空间角色
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: xudaxian-role
namespace: default # 所属的名称空间
rules: # 当前角色的规则
- apiGroups: [""] # "" 标明 core API 组,默认留空即可。
resources: ["pods"] # 资源类型
verbs: ["get", "watch", "list"] # 资源的动作类型
说明:
- Role 只能对名称空间(namespace)进行授权,所以需要指定名称空间(namespace)
- resources:支持的资源对象列表,通过
kubectl api-resources
查看 - verbs:对资源对象的操作方法列表,通过
kubectl api-resources -o wide
查看
ClusterRole 的资源清单文件:
# 集群角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: xudaxian-clusterrole
rules:
- apiGroups: [""] # "" 标明 core API 组,默认留空即可。
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
注意:ClusterRole 不需要设置 namespace。
RoleBinding 和 ClusterRoleBinding 资源清单
角色绑定用来把一个角色绑定到一个目标对象上,绑定目标可以是 User、Group 或者 ServiceAccount。
RoleBinding 资源清单文件:
# 账号和角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: xudaxian-rolebinding
namespace: default
subjects:
- kind: ServiceAccount # 账户类型
name: xudaxian # 账户名字,"name" 是区分大小写的
roleRef:
kind: Role
name: xudaxian-role # Role的名字
apiGroup: rbac.authorization.k8s.io # Api组
ClusterRoleBinding 资源清单文件:
# 账号和集群角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: xudaxian-clusterrolebinding
subjects:
- kind: ServiceAccount
name: xudaxian # "name" 是区分大小写的
namespace: default # 如果资源是某个 namespace 下的,那么就需要设置 namespace
roleRef:
kind: ClusterRole
name: xudaxian-clusterrole
apiGroup: rbac.authorization.k8s.io
示例
创建 ServiceAccount 的时候,系统会在底层默认一个含 ServiceAccount 名称的 Secret 。
# 名称空间角色
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: xudaxian-role
namespace: default # 所属的名称空间
rules: # 当前角色的规则
- apiGroups: [""] # "" 标明 core API 组,默认留空即可。
resources: ["pods"] # 指定能操作的资源 ,通过 kubectl api-resources 查看即可。
# resourceNames: [""] # 指定只能操作某个名字的资源
verbs: ["get", "watch", "list"] # 操作动作,通过 kubectl api-resources -o wide 查看即可。
---
# 集群角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: xudaxian-clusterrole
rules:
- apiGroups: [""] # "" 标明 core API 组,默认留空即可。
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
---
# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: xudaxian # ServiceAccount 的名称
namespace: default
---
# 账号和角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: xudaxian-rolebinding
namespace: default
subjects:
- kind: ServiceAccount
name: xudaxian # "name" 是区分大小写的
roleRef:
kind: Role
name: xudaxian-role
apiGroup: rbac.authorization.k8s.io
---
# 账号和集群角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: xudaxian-clusterrolebinding
subjects:
- kind: ServiceAccount
name: xudaxian # "name" 是区分大小写的
namespace: default # 如果资源是某个 namespace 下的,那么就需要设置 namespace
roleRef:
kind: ClusterRole
name: xudaxian-clusterrole
apiGroup: rbac.authorization.k8s.io
参考:
https://www.yuque.com/fairy-era/yg511q/by6f82#c5351a01