DockOne微信分享(二七三):Kubernetes集群在企业内部多租户共享场景下的管理


【编者的话】随着容器编排技术的成熟,Kubernetes也逐渐成为云计算的标准,但其使用的场景也各不相同。在Kubernetes集群环境下实现多租户场景下,仍然面临着诸如:权限管理,资源隔离,平台内部网络安全,资源调度等问题。本文主要介绍在公司内部多租户场景下,Kubernetes集群的管理。

RBAC权限管理

企业内部容器平台:

业务可控,组织架构复杂,更加注重权限的细粒度管理。Kubernetes提供namespace作为基础的资源隔离单位和基于RBAC的权限管理方式,可以说Kubernetes多租户的实现离不开这两个核心内容。

RBAC作为一种基于角色的并且灵活的访问控制机制且相较于其他的权限管理插件更加广泛,在Kubernetes集群中默认强制开启。

RBAC中的核心概念:
  • 基于单个名称空间:Role,RoleBinding
  • 整个集群级别:ClusterRole,ClusterRoleBinding


1.png

接下来说下RBAC的授权过程:
  • 创建Role(角色):Role可理解对资源对象拥有的权限,就是给定对资源可以对做什么。例如:公司信息部经理,可以管理公司的信息部。
  • 创建绑定角色的用户。 例如: 李四
  • 绑定角色。例如:李四能力强,让他担任信息部部门经理。


用下面两个集群来说明Role,RoleBinding和ClusterRole,ClusterRoleBinding。
2.png

集群1:为每个名称空间(Namespace)中,定义都定义了一个名称空间的管理员的角色,然后使用RoleBinding将AdminRole关联到用户上,来让指定用户成为此名称空间中的管理员。这样做很显然,非常繁琐。

集群2:在Kubernetes集群级别创建一个AdminRole,然后在使用RoleBinding来引用它,并将它和自己名称空间中的用户关联,这样该用户就成功的拥有了对当前名称空间的管理员权限。

总的来说:
  • RoleBinding即可以绑定名称空间内部的Role,又可以绑定ClusterRole,但RoleBinding绑定后,具体化的Role是具体化成本名称空间的Role。
  • ClusterRoleBinding仅可绑定ClusterRole,它具体化的Role,就可访问整个集群中所有的资源。


由于RBAC的灵活的权限管理能力,更加适用于复杂的多租户厂家下用户的权限管理中,针对不同的需求制定不同的权限管理策略。

如:

  • 集群管理员权限
    • 具有集群的管理权限
    • 为租户创建和分配命名空间
    • 各类策略(RAM/RBAC/NetworkPolicy/quota……)的CRUD

  • 租户管理员权限
    • 拥有管理其在Kubernetes的namespace以及namespace中运行程序的管理权限

  • 普通租户权限
    • 拥有管理其在Kubernetes的namespace中运行的所有资源的只读权限


Pod资源调度

API Server接受客户端提交Pod对象创建的请求后,会由调度器程(kube-scheduler),在当前集群中选择一最佳可用的节点接收并运行,并不是指定的节点。如需要将Pod资源按照需求调度,则就需要指定相关的调度策略。

Kubernetes集群的调度器:Scheduler(默认调度器)。

其核心目标是基于资源的可用性将各Pod资源公平地分布于集群节点之上。完成调度的操作步骤:
  1. 节点预选
  2. 节点优先级排序
  3. 节点优选


3.png

节点预选策略

预选策略就是节点过滤器,执行预选操作时,调度器将对每个节点基于配置适用的预选策略以特定的次序逐一筛查,并根据一票否决制进行节点淘汰,如若预选后不存在任何一个满足条件的节点,则Pod处于pending状态,直至至少一个节点可用为止。

预选策略根据其是否可以接受配置参数,又将预选策略为可配置策略和静态策略,可以配置策略可以在预选过程中结合用户自定义调度逻辑。
如何让Pod在部署时调度至指定的Kubernetes集群中具体Node节点或者带着某一类标签的节点,可以通过节点亲和调度来实现。

节点亲和调度

  • 硬亲和调度,硬亲和度的实现时强制性的,Pod调度时必须要满足的条件,不存满足条件节点时,Pod则处于pending状态。
  • 软亲和调度,软亲和调度是一种柔性调度,倾向于将Pod调度到某类特定节点上运行,调度器尽量满足调度到满足条件的节点,在无法满足需求时,退而求次选择不满足条件的节点上运行。权重weight定义优先级,1-100值越大优先级越高。


requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingI
gnoredDuringExecution名字中的后半段IgnoredDuringExecution隐藏含义所指,在Pod资源基于节点亲和性规则调度至某节点之后,节点标签发生了改变而不在符合此类节点亲和性规则时,调度器不会将Pod对象从此节点移除,因为它仅对新建的Pod对象生效。

在选择节点调度的策略时一般建议选择节点软亲和调度,不会因为目标节点资源不存在导致,适用非特殊的Pod,不会因Pod无法启动,从而导致无法对外提供服务。而在运行特殊的Pod需要运行在特定的计算资源的情况时,此时选择节点硬亲和策略进行调度将Pod调度至特定的节点运行。

Pod资源亲和调度

在出于高效通信的需求,有时需要将一些Pod调度到相近甚至是同一区域位置(比如同一节点、机房)等等,比如业务的前端Pod和后端Pod,此时这些Pod对象之间的关系可以叫做亲和性。同时出于安全性的考虑,也会把一些Pod之间进行隔离,此时这些Pod对象之间的关系叫做反亲和性(anti-affinity)。

调度器把第一个Pod放到任意位置,然后和该Pod有亲和或反亲和关系的Pod根据该动态完成位置编排,这就是Pod亲和性和反亲和性调度的作用。Pod的亲和性定义也存在硬亲和性和软亲和性的区别,其约束的意义和节点亲和性类似。

Pod的亲和性调度要求各相关的Pod对象运行在同一位置,而反亲和性则要求它们不能运行在同一位置。这里的位置实际上取决于节点的位置拓扑,拓扑的方式不同,Pod是否在同一位置的判定结果也会有所不同。
如果基于各个节点的kubernetes.io/hostname标签作为评判标准,那么会根据节点的hostname去判定是否在同一位置区域。

污点和容忍度

污点(taints)是定义在节点上的一组键值型属性数据,其作用与节点亲和调度恰恰相反,用来让节点拒将特定的Pod调度到该节点上,除非该Pod对象具有容纳节点污点的容忍度。而容忍度(tolerations)是定义在Pod对象上的键值型数据,用来配置让Pod对象可以容忍节点的污点。

Kubernetes使用PodToleratesNodeTaints预选策略和TaintTolerationPriority优选函数来完成这种调度方式。

污点容忍度:
  • NoSchedule:不能容忍此污点的新Pod对象不能调度到该节点上,属于强制约束,节点现存的Pod对象不受影响。
  • PreferNoSchedule:NoSchedule属于柔性约束,即不能容忍此污点的Pod对象尽量不要调度到该节点,不过无其他节点可以调度时也可以允许接受调度。
  • NoExecute:不能容忍该污点的新Pod对象不能调度该节点上,强制约束,节点现存的Pod对象因为节点污点变动或Pod容忍度的变动导致无法匹配规则,Pod对象就会被从该节点上去除。


优选函数(节点优选)

预选策略筛选出一个节点列表就会进入优选阶段,在这个过程调度器会向每个通过预选的节点传递一系列的优选函数来计算其优先级分值,优先级分值介于0-10之间,其中0表示不适用,10表示最适合托管该Pod对象。

另外,调度器还支持给每个优选函数指定一个简单的值,表示权重,进行节点优先级分值计算时,它首先将每个优选函数的计算得分乘以权重,然后再将所有优选函数的得分相加,从而得出节点的最终优先级分值。权重可以让管理员定义优选函数倾向性的能力,其计算优先级的得分公式如下:
finalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + ......

实际上我们大多数的时候做的Pod资源调度都是在节点预选策略中的可配置预选策略来实现完成。

Pod服务质量

Kubernetes允许节点资源对limits的过载使用,意味着节点可能无法同时满足其上面所有Pod对象以资源满载的方式运行。在节点内存资源紧张时,是通过Pod的优先来决定Pod对象终止的顺序。根据Pod对象的limits和request属性,Kubernetes将Pod对象归类Guaranteed、Burstable和BestEffort三个服务质量。

对于QoS类为Guaranteed的Pod:
  • Pod中的每个容器必须指定内存请求和内存限制,并且两者要相等。
  • Pod中的每个容器必须指定CPU请求和CPU限制,并且两者要相等。
  • 这类Pod资源具有最高优先级。


如果满足下面条件,将会指定Pod的QoS类为Burstable:当Pod设置的CPU或者内存限制资源与请求资源不相等时,此类Pod具有中等优先级。

对于QoS类为BestEffort的Pod:Pod中的容器必须没有设置内存和CPU限制或请求。此类Pod优先级别为最低级别。
4.png

内存资源紧缺时,BestEffort类别的Pod将首当其冲地被终止,因为系统不为其提供任何级别的资源保证,换来的好处是在用时做到尽可能的占用资源。当BestEffort类别的Pod不存在时,Burstable类别的Pod将会被终止。Guaranteed类别的Pod拥有最高优先级,它们不会被杀死,除非其内存资源需求超限,或者OOM时没有其他更低优先级的Pod资源存在。

每个运行状态容器都有其OOM得分,得分越高越会被优先杀死。OOM得分主要根据两个维度来计算:由QoS类别继承而来的默认分值和容器可用内存资源比例。

同等级优先级的Pod资源在OOM时,与自身的requests属性相比,其内存占用比例最大的Pod对象将首先被杀死。OOM是内存耗尽时的处理机制,与可压缩资源CPU无关,CPU资源无法获得保证时,Pod仅仅时暂时获取不到相应资源而已。因此,在针对Pod的QOS等级,调整部署时Pod相应的服务等级,可在计算资源紧缺时保证服务的可用性。

集群内部网络访问策略&流量控制

Kubernetes基于namespace实现环境隔离,但是namespace不能对不同的namespace之间的网络层访问做出有效的网络隔离,因此需要做出有效的网络访问策略来阻断集群内不同的namespace中的服务,未发生或已发生的未经允许的访问。

默认情况下Pod对象可以接受来自任何源的流量,也向外部发出期望的所有流量,Kubernetes集群部署Canal网络插件,网络策略也位于特定的命名空间中,NetworkPolicy对象资源使用标签选择Pod,并定义选定Pod所允许的通信规则。在附加网络策略机制后,Pod对象会因NetPolicy对象的选定而被隔离。

Network Policy提供了基于策略的网络控制,用于隔离应用并减少攻击面。使用标签选择器模,并通过策略控制他们之间的流量以及来自外部的流量。
  • 设置Ingress策略,可以允许或拒绝哪些流量访问哪些Pod。
  • 设置Egress策略,可以拒绝Pod的流量对外进行访问。


配置实例:

功能:通过使用标签选择器(包括namespaceSelector和podSelector)来控制Pod之间的流量

要决定三件事:
  • 控制对象:通过spec字段,podSelector等条件筛选
  • 流方向:Ingress(入Pod流量)+from,Egress(出Pod流量)+to
  • 流特征:对端(通过name/pod Selector),IP段(ipBlock),协议(protocol),端口(port)


Q&A

Q:如何实现各租户之间数据隔离和共享?如何实现各租户的需求个性化定制?
A:不同项目程序运行在不同namespace中+Netpolicy实现数据的隔离,反之则可实现数据共享的需求。

Q:我们需要在同一个Kubernetes Cluster上部署dev和qa两套环境。是用namespace隔离好,还是label隔离好?
A:用namespace隔离好,namespace是Kubernetes提出的作为基础隔离资源的的单位,而label标签,是用来做资源标记的,需要进行资源选择时使用。

Q:多租户场景下,如何让用户Pod强制只能在指定一组Node上部署?我们要求用户使用nodeselector,还用了污点,但这样都是靠自觉,用户还是总有办法绕过,并在别人的Node上部署。
A:这种目前据我所知还没有很好的办法开业进行管控,只能通过部署时人为干预。

Q:请问RBAC中的ServiceAccount和User区别是什么?它们有什么区别和应用场景呢?谢谢。
A:ServiceAccount是集群内部服务账号,用于集群内表明要执行的具体操作,如创建,删除,修改,查看等;User是常规用户,用来管理使用。

Q:RABC可以实现权限管理某种角色只能管理某些Pod吗?比如这个产品线只管自己产品线的Pod?是在同一个ns的。
A:RABC权限管理支持Role和ClusterRole两类角色,其中Role作用于名称空间级别(namespace),ClusterRole作用于整个集群。RABC可以用户授权对名称空间内的Pod资源进行管理。

Q:你们开发对线上Kubernetes是什么权限,怎么管理?
A:开发对线上Kubernetes只有只读权限, 通过Rbac进行权限控制。

Q:关于网络选择,Ingress策略和Egress适用场景该怎么选择?
A:Ingress适用为流量入站时的网络控制策略,而Egress适用于流量出站时的网络控制策略

Q:关于Pod资源分配request&limit 1:1,是否都是Guaranteed类型比较好,生产环境?
A:不是,一般建议运行重要性高的服务的Pod使用Guaranteed类型比较好。

以上内容根据2020年11月8日晚微信群分享内容整理。 分享人Fjt ,现任某科技公司运维工程师,负责公司内部Kubernetes集群上项目业务部署以及资源管控。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesf,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册