合理选择工作节点数量和大小
- 更少的大节点
- 优势1,更少的管理开销
管理少量机器相比管理大量机器会更省力。对节点进行升级和打补丁的操作能很迅速地完成,节点间的同步保持也更容易。此外,对于很少的机器而言,预期故障的绝对数量也会小于使用大量机器的场景。 - 优势2,更低的单节点成本
虽然高端机器比低端机器更昂贵,但价格上涨不一定是线性的。换句话说,具有 10 个 CPU 和 10GB 内存的单台机器可能比具有 1 个 CPU 和 1GB 内存的 10 台机器便宜。 - 优势3,允许运行资源饥饿型应用
如果您有一个需要 8GB 内存的机器学习应用程序,则无法在仅具有 1GB 内存的节点的集群上运行它。但是,您可以在具有 10GB 内存节点的集群上运行它。 - 劣势1,每个节点会运行大量 Pod
在较少的节点上运行相同的工作负载自然意味着在每个节点上运行更多的 Pod。
每个 Pod 都会为在节点上运行的 Kubernetes 代理程序引入一些开销——例如容器运行时(如 Docker)、kubelet 和 cAdvisor。
随着 Pod 数量的增长,这些问题的聚积可能会开始减慢系统速度,甚至使集群系统变得不可靠。 - 劣势2,有限的副本数量
较少的节点可能会限制应用程序的副本数量。
例如,如果您有一个由 5 个副本组成的高可用应用程序,但您只有 2 个节点,那么应用程序的有效副本数量将减少到 2。这是因为 5 个副本只能分布在 2 个节点上,如果其中一个节点失败,它可能会同时挂掉该节点上的多个副本。相反,如果您有至少 5 个节点,则每个副本可以在单独的节点上运行,并且单个节点的故障最多只会挂掉其中一个副本。 - 劣势,更大的破坏范围
如果您只有几个工作节点,那么节点失败造成的影响比使用大量节点时的影响要大。
例如,如果您只有两个节点,那其中一个节点出现故障,就意味着一半的节点会消失。 - 劣势4,较大的资源伸缩增量
Kubernetes 为云基础架构提供了 Cluster Autoscaler,允许根据当前需求自动添加或删除节点。如果使用大型节点,则会有较大的资源伸缩增量,这会使资源扩缩容更加笨重。
- 更多的小节点
- 优势1,减小破坏范围
如果您有更多节点,则每个节点上的 Pod 自然会更少。
如果您有 100 个 Pod 和 10 个节点,则每个节点平均只包含 10 个 Pod。这样,即便其中一个节点发生故障,它的影响也仅限于总工作负载的较小的一部分。有可能只有部分应用程序受到影响,并且可能只有少量副本挂掉,因此整个应用程序会仍然保持运行状态。
此外,剩余节点上的备用资源很可能足以容纳故障节点的工作负载,因此Kubernetes 可以重新安排所有 Pod,并且您的应用程序可以相对快速地恢复到完全正常的运行状态。 - 优势2,允许更多副本数量
如果您有一个多副本高可用应用程序以及足够的可用节点,Kubernetes 调度程序可以将每个副本分配给不同的节点。
您可以通过节点亲和、Pod 亲和/反亲和以及污点和容忍来影响调度程序对 Pod 的调度。
这意味着如果某个节点出现故障,则最多只有一个副本受影响,且您的应用程序仍然可用。 - 劣势1,较大的节点数量
如果使用较小的节点,则自然需要更多节点来实现给定的集群容量。,
但是大量节点对 Kubernetes 控制平面来说可能是一个挑战。
例如,每个节点都需要能够与其他节点通信,这使得可能的通信路径数量会按照节点数量的平方增长——所有节点都必须由控制平面管理。
Kubernetes controller manager 中的节点控制器定期遍历集群中的所有节点以运行状况检查——更多节点意味着节点控制器的负载更多。
更多节点同时也意味着 etcd 数据库上的负载也更多——每个 kubelet 和 kube-proxy 都会成为一个 etcd 的 watcher 客户端(通过 APIServer),etcd 必须广播对象变化到这些客户端。
通常,每个工作节点都会对主节点上的系统组件施加一些开销。
- 劣势2,更多的系统开销
Kubernetes 在每个工作节点上运行一组系统守护进程——包括容器运行时(如 Docker)、kube-proxy 和包含 cAdvisor 的 kubelet。,
cAdvisor 包含在 kubelet 二进制文件中。
所有这些守护进程一起消耗固定数量的资源。
如果使用许多小节点,则这些系统组件消耗的资源占比会增大。 - 劣势3,更低的资源利用率
如果您使用较小的节点,那么可能会产生大量资源碎片因资源太少而无法分配给任何工作负载,最终保持未使用状态。 - 劣势4,小节点限制 Pod 运行数量
在某些云基础架构上,小节点上允许的最大 Pod 数量比您预期的要限制得更多。
Amazon Elastic Kubernetes Service(EKS)就是这种情况,其中每个节点的最大 Pod 数取决于实例类型。
例如,对于 t2.medium 实例,最大 Pod 数为 17,t2.small 为 11,而 t2.micro为 4。
- 如何选择节点
您应该在集群中使用更少的大节点还是更多的小节点呢?
这没有明确的答案。
您要部署到集群的应用程序类型可能会影响您的决策。
例如,如果您的应用程序需要 10GB 内存,则可能不应使用小节点——集群中的节点应至少具有 10GB 内存。或者,如果您的应用程序需要 10 副本以实现高可用,那么您可能不应该只使用 2 个节点——您的集群应该至少有 10 个节点。
对于中间的所有场景,它取决于您的具体需求。
以上哪项优缺点与您相关?哪项与您不相关?
话虽如此,但没有规则说所有节点必须具有相同的大小。没有什么能阻止您使用不同大小的节点来混合构建集群。Kubernetes 集群的工作节点可以是完全异构的。这可能会让您权衡两种方法的优缺点。
最后,实践是检验真理的唯一标准——最好的方法是反复试验并找到最适合您的资源配置组合!
命名空间限制
当您决定在命名空间中隔离集群时,您应该防止资源滥用。
您不应该允许您的用户使用比您事先同意的更多的资源。
集群管理员可以通过配额和限制范围设置约束来限制项目中使用的对象数量或计算资源数量。
如果您需要复习限制范围,您应该查看官方文档
- 命名空间有 LimitRange
没有限制的容器会导致与其他容器的资源争用和计算资源的未优化消耗。
Kubernetes 有两个限制资源使用的特性:ResourceQuota 和 LimitRange。
使用 LimitRange 对象,您可以为命名空间内的各个容器定义资源请求和限制的默认值。
在该命名空间内创建的任何容器,没有明确指定请求和限制值,都会被分配默认值。 - 命名空间具有 ResourceQuotas
使用 ResourceQuotas,您可以限制 Namespace 内所有容器的总资源消耗。
为命名空间定义资源配额会限制属于该命名空间的所有容器可以消耗的 CPU、内存或存储资源的总量。
您还可以为其他 Kubernetes 对象设置配额,例如当前命名空间中的 Pod 数量。
如果您认为有人可以利用您的集群并创建 20000 个 ConfigMap,那么使用 LimitRange 可以防止这种情况发生。
Pod 安全策略
当一个 Pod 部署到集群中时,应该防范:
- 容器被破坏
- 容器使用节点上不允许的资源,例如进程、网络或文件系统
更一般地说,应该将 Pod 可以做的事情限制在最低限度。
- 启用 Pod 安全策略
例如,可以使用 Kubernetes Pod 安全策略来限制:
- 访问主机进程或网络命名空间
- 运行特权容器
- 容器运行的用户
- 访问主机文件系统
- Linux 功能、Seccomp 或 SELinux 配置文件
选择正确的策略取决于集群的性质。
https://www.whitesourcesoftware.com/resources/blog/kubernetes-pod-security-policy/
- 禁用特权容器
在 Pod 中,容器可以在“特权”模式下运行,并且几乎可以不受限制地访问主机系统上的资源。
虽然在某些特定用例中需要这种级别的访问,但一般而言,让您的容器执行此操作存在安全风险。
特权 Pod 的有效用例包括在节点上使用硬件,例如 GPU。 - 在容器中使用只读文件系统
在您的容器中运行只读文件系统会强制您的容器不可变。
这不仅可以缓解一些旧的(且有风险的)做法,例如热补丁,还可以帮助您防止恶意进程在容器内存储或操纵数据的风险。
使用只读文件系统运行容器听起来很简单,但可能会带来一些复杂性。
如果您需要在临时文件夹中写入日志或存储文件怎么办? - 防止容器以 root 身份运行
在容器中运行的进程与主机上的任何其他进程没有区别,只是它有一小段元数据声明它在容器中。
因此,容器中的 root 与主机上的 root (uid 0) 相同。
如果用户设法突破在容器中以 root 身份运行的应用程序,他们可能能够以相同的 root 用户访问主机。
将容器配置为使用非特权用户,是防止提权攻击的最佳方法。
https://medium.com/@mccode/processes-in-containers-should-not-run-as-root-2feae3f0df3b
- 限制能力Container Capabilities
Linux 功能使进程能够执行许多特权操作中的一些,默认情况下只有 root 用户才能执行。
例如,CAP_CHOWN允许进程“对文件 UID 和 GID 进行任意更改”。
即使您的进程不作为 运行root,进程也有可能通过提升权限来使用这些类似 root 的功能。
换句话说,如果您不想受到损害,您应该只启用您需要的功能。
https://cloud.tencent.com/developer/article/1548565 - 防止权限提升
您应该在关闭权限提升的情况下运行容器,以防止使用setuid或setgid二进制文件提升权限。
网络策略
Kubernetes 网络必须遵守三个基本规则:
- 容器可以与网络中的任何其他容器通信,并且在此过程中没有地址转换——即不涉及 NAT
- 集群中的节点可以与网络中的任何其他容器通信,反之亦然。即使在这种情况下,也没有地址转换——即没有 NAT
- 一个容器的 IP 地址总是相同的,无论是从另一个容器还是它本身来看都是独立的。
如果您计划将集群隔离为较小的块并在命名空间之间进行隔离,则第一条规则无济于事。
想象一下,如果集群中的用户能够使用集群中的任何其他服务。
现在,想象一下如果集群中的恶意用户要获得对集群的访问权限——他们可以向整个集群发出请求。
为了解决这个问题,您可以使用网络策略定义如何允许 Pod 在当前命名空间和跨命名空间中进行通信。
- 启用网络策略
Kubernetes 网络策略指定了 Pod 组的访问权限,就像云中的安全组用于控制对 VM 实例的访问一样。
换句话说,它在 Kubernetes 集群上运行的 Pod 之间创建防火墙。
如果您不熟悉网络策略,您可以阅读保护 Kubernetes 集群网络。 - 每个命名空间中都有一个保守的 NetworkPolicy
此存储库包含 Kubernetes 网络策略的各种用例和示例 YAML 文件以在您的设置中利用。如果您想知道如何删除/限制在 Kubernetes上运行的应用程序的流量,请继续阅读。
基于角色的访问控制 (RBAC) 策略
基于角色的访问控制 (RBAC) 允许您定义有关如何访问集群中资源的策略。
放弃所需的最少权限是常见的做法,但什么是实用的,您如何量化最少权限?
细粒度策略提供更高的安全性,但需要更多的管理工作。
更广泛的授权可以为服务帐户提供不必要的 API 访问权限,但更易于控制。
您是否应该为每个命名空间创建一个策略并共享它?
或者最好将它们放在更细粒度的基础上?
没有一刀切的方法,您应该逐案判断您的需求。
但你从哪儿开始呢?
如果您从一个规则为空的角色开始,您可以一一添加您需要的所有资源,并且仍然确保您不会放弃太多。 - 禁用默认 ServiceAccount 的自动挂载
请注意,默认的 ServiceAccount 会自动挂载到所有 Pod 的文件系统中。
您可能希望禁用它并提供更精细的策略。 - RBAC 策略设置为所需的最少权限
很难找到关于如何设置 RBAC 规则的好建议。在Kubernetes RBAC 的 3 个现实方法中,您可以找到三个实际场景和有关如何开始的实用建议。 - RBAC 策略是细粒度的且不共享
Zalando 有一个简洁的策略来定义角色和 ServiceAccounts。
首先,他们描述了他们的要求:
- 用户应该能够部署,但不应该允许他们读取例如 Secrets
- 管理员应该获得对所有资源的完全访问权限
- 默认情况下,应用程序不应获得对 Kubernetes API 的写访问权限
- 应该可以为某些用途写入 Kubernetes API。
这四个要求转化为五个独立的角色:
- 只读
- 超级用户
- 操作员
- 控制器
- 行政