了解Kubernetes中的RBAC

注意事项 佩雷夫 :本文由来自Bitnami著名Kubernetes社区的工程师Javier Salmeron撰写,并于8月初发布在CNCF博客上。 作者讨论了一年半前出现在Kubernetes中的RBAC(基于角色的访问控制)机制的基本知识。 该材料对于熟悉K8关键部件装置的人特别有用(请参阅最后的其他类似文章的链接)。


Google员工在发布Kubernetes 1.6时所做的演示的幻灯片

许多有经验的Kubernetes用户可能会想起基于Kubernetes 1.6的发布,当时基于角色的访问控制(RBAC)的授权成为beta。 因此出现了一种替代的身份验证机制,该机制对已经存在但难以管理和理解的基于属性的访问控制(ABAC)进行了补充。 每个人都热烈欢迎这项新功能,但与此同时,无数用户对此感到失望。 StackOverflow和GitHub上充斥着RBAC限制的报告,因为大多数文档和示例都没有考虑RBAC(但现在一切都很好)。 参考示例为Helm:仅运行helm init + helm install不再起作用。 突然之间,我们甚至需要在使用WordPress或Redis部署图表之前,需要添加诸如ServiceAccountsRoleBindings类的“怪异”元素(有关更多信息,请参见说明 )。

撇开这些未成功的第一手尝试,不能否认RBAC为将Kubernetes转变为可投入生产的平台所做的巨大贡献。 我们中的许多人都拥有完全的管理员特权,可以使用Kubernetes进行游戏,我们完全理解在实际环境中这是必要的:

  • 使许多具有不同属性的用户提供所需的身份验证机制。
  • 完全控制每个用户或用户组可以执行的操作。
  • 完全控制心脏中每个过程可以执行的操作。
  • 限制名称空间中某些资源的可见性。

在这方面,RBAC是提供急需功能的关键元素。 在本文中,我们将快速讲解基础知识(有关详细信息,请参见此视频 ;请使用英语的1小时Bitnami网络研讨会链接- 大约翻译 ),并深入了解最令人困惑的时刻。

在Kubernetes中了解RBAC的关键


要完全实现RBAC的想法,您需要了解其中涉及三个要素:

  • 主题 -一组想要访问Kubernetes API的用户和流程;
  • 资源 -集群中可用的Kubernetes API对象的集合。 他们的示例(包括PodDeploymentServicesNodesPersistentVolumes等)
  • 动词 (动词)-可以对资源执行的一组操作。 动词有多种(获取,监视,创建,删除等),但它们最终都是来自CRUD类别(创建,读取,更新,删除)的操作。



考虑到这三个要素,RBAC的关键思想是:

“我们希望将主题,API资源和操作联系起来。” 换句话说,我们要为给定的用户指示可以对各种资源执行哪些操作

了解API中的RBAC对象


通过结合这三种类型的实体,Kubernetes API中可用的RBAC对象变得很清楚:

  • Roles连接资源和动词。 它们可以重用于不同的主题。 绑定到一个名称空间(我们不能使用表示多个[名称空间]的模板,但可以将同一角色对象部署到不同的名称空间)。 如果要将角色应用于整个集群,则有一个类似的ClusterRoles对象。
  • RoleBindings连接其余实体实体。 通过指定已经将API对象与动词联系起来的角色,我们现在选择可以使用它们的主题。 集群级别(即不绑定到名称空间)的ClusterRoleBindingsClusterRoleBindings

在下面的示例中,我们赋予用户jsalmeron读取,获取列表以及在测试名称空间中创建壁炉权利。 这意味着jsalmeron将能够执行以下命令:

 kubectl get pods --namespace test kubectl describe pod --namespace test pod-name kubectl create --namespace test -f pod.yaml #      

...但不是那样的:

 kubectl get pods --namespace kube-system #    kubectl get pods --namespace test -w #    watch 



YAML文件的示例:

 kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: pod-read-create namespace: test rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "create"] 

 kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: salme-pods namespace: test subjects: - kind: User name: jsalmeron apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-read-create apiGroup: rbac.authorization.k8s.io 

另一个有趣的一点是:既然用户可以创建吊舱,我们可以限制多少个吊舱吗? 这将需要与RBAC规范不直接相关的其他对象,并允许您配置资源限制: ResourceQuotaLimitRanges 。 在配置如此重要的群集组件(例如创建炉膛)时,绝对值得探索。

主题:用户和... ServiceAccounts?


许多Kubernetes用户在主题上下文中面临的困难之一是常规用户和ServiceAccounts之间的区别。 从理论上讲,一切都很简单:

  • Users -面向群集外人员或流程的全球用户;
  • ServiceAccounts受名称空间限制,适用于在Pod上运行的集群中的进程。

两种类型的相似之处在于需要通过API进行身份验证以对许多资源执行某些操作,并且它们的主题区域看起来非常具体。 它们也可以属于组,因此RoleBinding允许RoleBinding绑定多个主题(尽管ServiceAccounts - system:serviceaccounts只允许一个组)。 但是,主要的区别是造成头痛的原因:用户在Kubernetes API中没有与之相对应的对象。 事实证明存在这样的操作:

 kubectl create serviceaccount test-service-account # OK 

...但是这个消失了:

 kubectl create user jsalmeron # ! 

这种情况产生了严重的后果:如果群集未存储有关用户的信息,则管理员将不得不管理群集外部的帐户。 解决问题的方法有多种:TLS证书,令牌,OAuth2等。

另外,您将需要创建kubectl上下文, kubectl我们可以通过这些新帐户访问集群。 要使用它们创建文件,您可以使用kubectl config命令(不需要访问Kubernetes API,因此任何用户都可以执行它们)。 上面的视频提供了使用TLS证书创建用户的示例。

部署中的RBAC:示例


我们看到了一个示例,其中向指定的用户授予了集群中操作的权限。 但是需要访问Kubernetes API的部署又如何呢? 考虑一个特定的场景以更好地理解。

以流行的基础架构应用程序-RabbitMQ为例。 我们将使用Bitnami的RabbitMQHelm图表 (来自官方helm / charts存储库),该图表使用bitnami / rabbitmq容器 。 容器中内置了Kubernetes插件,该插件负责检测RabbitMQ集群的其他成员。 因此,容器内的进程需要访问Kubernetes API,并且我们需要使用正确的RBAC特权配置ServiceAccount

对于ServiceAccounts ,请遵循以下良好做法:

-使用最小权限集 为每个部署配置ServiceAccounts

对于需要访问Kubernetes API的应用程序,您可能会想创建某种“特权ServiceAccount ”,它几乎可以在集群中执行任何操作。 尽管这似乎是一个更简单的解决方案,但它最终可能会导致一个安全漏洞,该漏洞可能允许不必要的操作。 (该视频观看了一个Tiller [Helm组件]的示例,以及具有非常特权的ServiceAccounts的后果。)

另外,不同的部署在访问API方面会有不同的需求,因此每个部署都有不同的ServiceAccounts是合理的。

牢记这一点,让我们看看哪种RBAC配置对于RabbitMQ的Deployment情况是正确

插件的文档 及其源代码中,您可以看到它正在从Kubernetes API请求端点列表。 这就是检测RabbitMQ集群其余成员的方式。 因此,Bitnami RabbitMQ图表创建:

  • ServiceRabbitMQ的炉膛帐户:

     {{- if .Values.rbacEnabled }} apiVersion: v1 kind: ServiceAccount metadata: name: {{ template "rabbitmq.fullname" . }} labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" {{- end }} 
  • 角色 (我们假设整个RabbitMQ集群都部署在单个名称空间中),从而允许动词获取 Endpoint资源:

     {{- if .Values.rbacEnabled }} kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get"] {{- end }} 
  • RoleBindingServiceAccount连接到角色:

     {{- if .Values.rbacEnabled }} kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" subjects: - kind: ServiceAccount name: {{ template "rabbitmq.fullname" . }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: {{ template "rabbitmq.fullname" . }}-endpoint-reader {{- end }} 



该图显示了我们允许运行在RabbitMQ pod中的进程对Endpoint对象执行get操作。 这是一切正常工作所需的最少一组操作。 同时,我们知道已部署的图表是安全的,不会在Kubernetes集群内部执行不必要的操作。

最后的想法


要在生产中使用Kubernetes,RBAC策略不是可选的。 它们不能被视为只有管理员应该知道的一组API对象。 开发人员实际上需要他们部署安全的应用程序,并充分利用Kubernetes API为云原生应用程序提供的潜力。 在以下链接上可以找到有关RBAC的更多信息:


译者的PS


另请参阅我们的博客:

Source: https://habr.com/ru/post/zh-CN422801/


All Articles