新钛云服已累计为您分享652篇技术干货
通过本文,我们将学习如何从头开始重新创建 Kubernetes RBAC 授权模型,并了解Roles、ClusterRoles、ServiceAccounts、RoleBindings 和 ClusterRoleBindings 之间的关系。
随着集群中应用程序和资源数量的增加,我们可能需要查看并限制他们相关的权限,从而避免一些危险操作。这些危险操作往往会严重影响生产环境,有时候,甚至会引起长时间的停机,比如过大的权限导致正常运行的服务被删除。
正常情况下,我们可能希望限制生产系统仅仅允许少部分人管理以及访问。
或者,我们可能希望向部署在集群中的维护人员授予一组有限的权限。
我们可以通过Kubernetes 中的基于角色的访问控制 (RBAC) 来实现上述的需求。
Kubernetes API
在讨论RBAC之前,让我们看看授权模型在图中的位置。
假设我们希望将以下 Pod 部署到 Kubernetes 集群:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: sise
image: learnk8s/app:1.0.0
ports:
- containerPort: 8080
我们可以使用以下命令将 Pod 部署到集群:
$ kubectl apply -f pod.yaml
当我们输入时kubectl apply
,会触发以下的操作。
kubectl
会:
1、从KUBECONFIG读取配置
2、从 API 中发现 API 和对象
3、验证资源客户端(是否有明显的错误?)
4、将带有有效负载的请求发送到kube-apiserver
当kube-apiserver
收到请求时,它不会立即将其存储在 etcd 中。
首先,它必须验证请求者是否合法。
换句话说,它必须对请求进行身份验证。(https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
一旦通过身份验证,请求者是否有权创建资源?
身份和权限不是一回事。
仅仅因为我们可以访问集群并不意味着我们可以创建或读取所有资源。
授权通常使用基于角色的访问控制 (RBAC)(https://kubernetes.io/docs/reference/access-authn-authz/rbac/)来完成。
借助基于角色的访问控制 (RBAC),我们可以分配精细的权限并限制用户或应用程序可以执行的操作。
在更实际的情况下,API 服务器按顺序执行以下操作:
1、收到请求后,对用户进行身份验证。
a. 当验证失败时,通过返回来拒绝请求401 Unauthorized。
b, 否则,进入下一阶段。
2、用户已通过身份验证,但他们是否有权访问资源
a. 如果他们没有权限,请通过返回来拒绝请求403 Forbidden。
b. 否则,继续。
在本文中,我们将重点关注授权部分。
将用户和权限与 RBAC 角色解耦
RBAC(Role-Based Access Control)即:基于角色的权限控制。通过角色关联用户,角色关联权限的方式间接赋予用户权限。
如下图:
有人会问为什么不直接给用户分配权限,还多此一举的增加角色这一环节呢?
其实是可以直接给用户分配权限,只是直接给用户分配权限,少了一层关系,扩展性弱了许多,适合那些用户数量、角色类型少的平台。
对于通常的系统,比如:存在多个用户拥有相同的权限,在分配的时候就要分别为这几个用户指定相同的权限,修改时也要为这几个用户的权限进行一一修改。有了角色后,我们只需要为该角色制定好权限后,将相同权限的用户都指定为同一个角色即可,便于权限管理。
对于批量的用户权限调整,只需调整用户关联的角色权限,无需对每一个用户都进行权限调整,既大幅提升权限调整的效率,又降低了漏调权限的概率。
要了解它是如何工作的,让我们想象一下,我们必须从头开始设计一个授权系统。
我们该如何确保用户对特定资源具有写入权限?
一个简单的实现可能涉及编写一个如下所示的列表:
| User | Permission | Resource |
| ----- | ---------- | -------- |
| Bob | read+write | app1 |
| Alice | read | app2 |
| Mo | read | app2 |
在这个例子中:
· Bob 有读写权限,可以访问app1但无权访问app2
· Mo 和 Alice对app2有只读权限,但是无权访问app1
上表适用于少数用户和资源,但一旦开始扩展它就会显示一些限制。
让我们假设Mo和Alice在同一个Team中,并且他们被授予对app1的读取权限。
我们必须将以下条目添加到表中:
| User | Permission | Resource |
| --------- | ---------- | -------- |
| Bob | read+write | app1 |
| Alice | read | app2 |
| Mo | read | app2 |
| Alice | read | app1 |
| Mo | read | app1 |
这很好,但Alice和Mo是否有相同的访问权限并不明显,因为他们是同一Team的成员。
在典型的授权系统中我们有用户访问资源
我们可以直接向用户分配权限,并定义他们可以使用的资源
这些权限直接映射资源。注意它们是如何作用于用户的
如果我们决定让第二个用户具有相同的权限,则必须关联相同的权限
我们可以通过在表中添加“Team”列来解决这个问题,但更好的替代方法是分解关系:
1、我们可以为权限定义一个通用属性:角色。
2、我们可以为定义的组织“Team”进行授权,而不是直接将权限分配给用户。
3、最后,我们可以用户加入到定义组织”Team“。
让我们看看这有什么不同。
现在你有两个权限映射关系表:
· 在第一个表中,权限映射到角色
· 在第二个表中,角色与身份相关联
| Role | Permission | Resource |
| -------- | ---------- | -------- |
| admin1 | read+write | app1 |
| reviewer | read | app2 |
| User | Roles |
| ----- | -------- |
| Bob | admin1 |
| Alice | reviewer |
| Mo | reviewer |
当我们希望 Mo 成为 app1 的管理员时那又该如何做了?
我们可以像这样将角色添加到用户:
| User | Roles |
| ----- | ------------------- |
| Bob | admin1 |
| Alice | reviewer |
| M
我们已经可以想象,将用户与权限与角色分离可以促进拥有大量用户和权限的大型组织中的安全管理。
使用 RBAC 时,我们拥有用户、资源和角色
权限不会直接分配给用户。相反,他们被包括在这个角色中
用户通过绑定关联到角色
由于角色是通用的,当新用户需要访问相同资源时,您可以使用现有角色并将其新绑定关联
Kubernetes 中的 RBAC
Kubernetes 实现了一个 RBAC 模型(以及其他几个模型)(https://kubernetes.io/docs/reference/access-authn-authz/authorization/#authorization-modules) 来保护集群中的资源。
基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对 计算机或网络资源的访问的方法。
RBAC 鉴权机制使用 rbac.authorization.k8s.io
API 组 来驱动鉴权决定,允许你通过 Kubernetes API 动态配置策略。
要启用 RBAC,在启动 API 服务器 时将 --authorization-mode
参数设置为一个逗号分隔的列表并确保其中包含 RBAC
。
kube-apiserver --authorization-mode=Example,RBAC --<其他选项> --<其他选项>
因此 Kubernetes 使用了前面解释过的相同的三个概念:身份、角色和绑定。
它只是用稍微不同的名字来称呼它们。
例如,让我们检查以下授予对 Pod、Service等资源的访问权限所需的 YAML 定义:
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount:app1
namespace: demo-namespace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role:viewer
namespace: demo-namespace
rules: # Authorization rules for this role
- apiGroups: # 1st API group
- '' # An empty string designates the core API group.
resources:
- services
- pods
verbs:
- get
- list
- apiGroups: # 2nd API group
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- list
- apiGroups: # 3rd API group
- cilium.io
resources:
- ciliumnetworkpolicies
- ciliumnetworkpolicies/status
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rolebinding:app1-viewer
namespace: demo-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role:viewer
subjects:
- kind: ServiceAccount
name: serviceaccount:app1
namespace: demo-namespace
该文件分为三个部分:
1、ServiceAccount——这是访问资源的用户的身份
2、Role——包含访问资源的权限
3、将身份(ServiceAccount)关联到权限(Role)的 RoleBinding
配置提交到集群后,允许使用服务帐户的应用程序向以下端点发出请求:
# 1. Kubernetes builtin resources
/api/v1/namespaces/{namespace}/services
/api/v1/namespaces/{namespace}/pods
# 2. A specific API extention provided by cilium.io
/apis/cilium.io/v2/namespaces/{namespace}/ciliumnetworkpolicies
/apis/cilium.io/v2/namespaces/{namespace}/ciliumnetworkpolicies/status
结果很成功,但是我们忽略了很多细节。
我们究竟授予了哪些资源访问权限?
什么是服务帐户?身份不只是集群中的“用户”吗?
为什么 Role 包含 Kubernetes 对象列表?
为了理解它们是如何工作的,让我们抛开 Kubernetes RBAC 模型并尝试从头开始重建它。
我们将重点关注三个要素:
1、识别和分配身份
2、’授予权限
3、将身份与权限相关联
分配身份:用户,组,robot账户
假设我们的新同事希望登录 Kubernetes 界面。
在这种情况下,我们应该有一个“帐户”或“用户”的实体,每个实体都有一个唯一的名称或 ID