MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kubernetes 的资源配额与限制设置方法

2021-05-116.7k 阅读

Kubernetes 资源配额概述

在 Kubernetes 集群中,资源配额是一种至关重要的机制,它允许集群管理员对命名空间(Namespace)内的资源使用进行限制。这有助于确保各个团队或项目在共享的 Kubernetes 集群资源时,不会因为某个命名空间过度使用资源而影响其他命名空间的正常运行。

资源配额主要针对两种类型的资源进行限制:计算资源(如 CPU 和内存)以及对象数量(如 Pod、Service 等 Kubernetes 对象的数量)。通过设置资源配额,管理员可以更好地规划和分配集群资源,提高资源利用率,并保障集群的稳定性和可靠性。

计算资源配额

  1. CPU 配额:CPU 资源在 Kubernetes 中以核心(Core)为单位进行计量。一个 CPU 核心可以被多个 Pod 共享,Kubernetes 通过一种称为 “CPU 时间片” 的机制来分配 CPU 资源。例如,一个 Pod 申请 0.5 个 CPU 核心,这意味着它在一段时间内将获得半个核心的计算能力。
  2. 内存配额:内存资源以字节为单位进行计量。Pod 声明的内存配额表示该 Pod 在运行过程中最多可以使用的内存量。如果 Pod 使用的内存超过了配额,Kubernetes 可能会根据配置策略采取不同的措施,如杀死该 Pod 以释放内存。

对象数量配额

  1. Pod 数量配额:限制命名空间内可以创建的 Pod 总数。这在一些场景下非常有用,例如防止某个项目创建过多的 Pod 而耗尽集群资源。
  2. Service 数量配额:可以限制命名空间内 Service 的数量,确保不会因为过度创建 Service 而导致集群网络配置变得复杂和混乱。
  3. 其他对象配额:除了 Pod 和 Service,还可以对其他 Kubernetes 对象(如 ReplicaSet、Deployment 等)设置数量配额,具体取决于集群的需求。

资源限制与请求

在 Kubernetes 中,每个容器都可以定义资源请求(Requests)和资源限制(Limits)。资源请求表示容器期望使用的资源量,而资源限制表示容器最多能使用的资源量。

资源请求

  1. CPU 请求:在 Pod 的定义文件中,通过 resources.requests.cpu 字段来指定 CPU 请求。例如:
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
    resources:
      requests:
        cpu: "200m" # 200 毫核心,即 0.2 个核心
  1. 内存请求:通过 resources.requests.memory 字段指定内存请求,例如:
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
    resources:
      requests:
        memory: "512Mi" # 512 兆字节

资源限制

  1. CPU 限制:使用 resources.limits.cpu 字段设置 CPU 限制。例如:
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
    resources:
      limits:
        cpu: "500m" # 500 毫核心,即 0.5 个核心
  1. 内存限制:通过 resources.limits.memory 字段设置内存限制,例如:
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
    resources:
      limits:
        memory: "1Gi" # 1 吉字节

请求与限制的关系

  1. 一般原则:通常情况下,资源请求应该小于或等于资源限制。如果请求大于限制,Kubernetes 在调度 Pod 时可能会遇到问题,因为它需要为 Pod 分配足够的资源以满足请求,但又不能超过限制。
  2. CPU 场景:对于 CPU 资源,如果容器使用的 CPU 超过了请求但未超过限制,Kubernetes 会根据集群的负载情况尽量满足容器对 CPU 的额外需求。但如果超过了限制,容器的 CPU 使用将被限制在设定的上限。
  3. 内存场景:在内存方面,如果容器使用的内存超过了限制,Kubernetes 的 kubelet 会根据 OOM(Out - Of - Memory)策略杀死该容器,以防止它继续消耗过多内存影响其他容器和节点的运行。

创建资源配额

在 Kubernetes 中,通过创建 ResourceQuota 对象来设置命名空间的资源配额。

创建 ResourceQuota 对象

  1. 定义 ResourceQuota 配置文件:以下是一个简单的 ResourceQuota 配置示例,用于限制命名空间内的 CPU、内存、Pod 数量和 Service 数量:
apiVersion: v1
kind: ResourceQuota
metadata:
  name: my - quota
spec:
  hard:
    requests.cpu: "2" # 命名空间内所有 Pod 的 CPU 请求总和不能超过 2 个核心
    requests.memory: "4Gi" # 命名空间内所有 Pod 的内存请求总和不能超过 4 吉字节
    limits.cpu: "4" # 命名空间内所有 Pod 的 CPU 限制总和不能超过 4 个核心
    limits.memory: "8Gi" # 命名空间内所有 Pod 的内存限制总和不能超过 8 吉字节
    pods: "10" # 命名空间内最多可以创建 10 个 Pod
    services: "5" # 命名空间内最多可以创建 5 个 Service
  1. 应用 ResourceQuota:使用 kubectl apply -f <quota - file>.yaml 命令将上述配置应用到 Kubernetes 集群中。例如,如果配置文件名为 quota.yaml,则执行 kubectl apply -f quota.yaml

配额作用范围

  1. 命名空间级别:资源配额是在命名空间级别生效的。一旦为某个命名空间创建了 ResourceQuota,该命名空间内的所有资源创建操作都会受到配额的限制。不同命名空间之间的资源配额相互独立,这使得集群管理员可以为不同的团队或项目分配不同的资源额度。
  2. 资源类型作用:资源配额不仅对 Pod 和 Service 等对象数量起作用,对于 Pod 内容器的计算资源请求和限制也同样有效。例如,如果命名空间的 CPU 请求配额为 2 个核心,当创建一个新的 Pod 且其 CPU 请求总和超过剩余配额时,Pod 的创建将失败,并提示资源不足的错误信息。

资源配额管理与监控

在 Kubernetes 集群中,有效地管理和监控资源配额是确保集群资源合理分配和高效运行的关键。

查看资源配额

  1. 使用 kubectl 命令:可以使用 kubectl get resourcequota 命令查看集群中所有的资源配额对象。如果要查看某个特定命名空间的配额,可以使用 kubectl get resourcequota -n <namespace>,例如 kubectl get resourcequota -n my - namespace
  2. 查看配额详情:使用 kubectl describe resourcequota <quota - name> -n <namespace> 命令可以获取资源配额的详细信息,包括已使用的资源量和配额限制。例如,执行 kubectl describe resourcequota my - quota -n my - namespace 后,会显示类似如下信息:
Name:                    my - quota
Namespace:               my - namespace
Resource                Used    Hard
--------                ----    ----
limits.cpu              1000m   4
limits.memory           2Gi     8Gi
pods                    5       10
requests.cpu            500m    2
requests.memory         1Gi     4Gi
services                3       5

监控资源使用情况

  1. 使用 Metrics Server:Metrics Server 是 Kubernetes 集群中用于收集和提供资源使用指标的组件。通过部署 Metrics Server,可以使用 kubectl top 命令查看 Pod 和节点的资源使用情况。例如,kubectl top pod -n my - namespace 可以查看指定命名空间内 Pod 的 CPU 和内存使用情况。
  2. 集成外部监控系统:除了 Metrics Server,还可以将 Kubernetes 集群与外部监控系统(如 Prometheus + Grafana)集成。Prometheus 可以收集 Kubernetes 集群的各种指标数据,包括资源使用情况,而 Grafana 则用于可视化这些数据,通过创建各种图表和仪表盘,可以更直观地了解集群资源的使用趋势和配额占用情况。

配额调整与优化

  1. 根据业务需求调整配额:随着业务的发展和变化,命名空间内的资源需求可能会发生改变。集群管理员需要定期评估各个命名空间的资源使用情况,根据实际需求调整资源配额。例如,如果某个命名空间的业务量增长,导致 Pod 的 CPU 和内存使用经常接近或超过配额限制,可以适当增加该命名空间的 CPU 和内存配额。
  2. 优化资源分配:通过监控资源使用情况,还可以发现哪些 Pod 的资源请求设置不合理。对于资源请求设置过高的 Pod,可以适当降低请求值,以提高集群资源的整体利用率。同时,对于资源使用经常超过限制的 Pod,需要分析其业务逻辑,看是否可以通过优化代码或调整配置来降低资源消耗,从而避免因 OOM 等问题导致 Pod 被杀死。

资源配额的高级应用

在复杂的 Kubernetes 集群环境中,资源配额还有一些高级应用场景,可以进一步优化集群资源管理。

资源配额与优先级

  1. Pod 优先级类:Kubernetes 支持为 Pod 定义优先级类(PriorityClass)。通过将资源配额与 Pod 优先级相结合,可以确保高优先级的 Pod 在资源紧张时优先获得资源。例如,对于一些关键业务的 Pod,可以将其优先级设置为较高,当命名空间内资源不足时,低优先级的 Pod 可能会被驱逐,以保证高优先级 Pod 的正常运行。
  2. 优先级类配置:首先需要创建一个 PriorityClass 对象,例如:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high - priority
value: 1000000
globalDefault: false
description: "This priority class should be used for high priority pods."

然后在 Pod 的定义文件中引用该优先级类:

apiVersion: v1
kind: Pod
metadata:
  name: high - priority - pod
spec:
  priorityClassName: high - priority
  containers:
  - name: my - container
    image: my - image

跨命名空间资源配额

  1. 集群级资源管理:在一些大型的 Kubernetes 集群中,可能需要对多个命名空间进行统一的资源配额管理,以实现更高效的资源分配。虽然 Kubernetes 原生不直接支持跨命名空间的资源配额,但可以通过一些第三方工具或自定义脚本实现。
  2. 第三方工具示例:例如,使用 Cluster Resource Management (CRM) 工具,可以在集群级别定义资源配额策略,并将其应用到多个命名空间。CRM 工具通过与 Kubernetes API Server 进行交互,收集各个命名空间的资源使用情况,并根据预定义的策略进行资源分配和限制。

动态资源配额调整

  1. 基于指标的动态调整:传统的资源配额是静态设置的,而在实际应用中,集群的资源需求可能会随时间动态变化。可以通过结合 Kubernetes 的自定义指标 API 和一些自动化工具,实现资源配额的动态调整。例如,根据 CPU 使用率、内存使用率等指标,当某个命名空间的资源使用达到一定阈值时,自动增加或减少该命名空间的资源配额。
  2. 实现方案:可以使用 Prometheus 收集指标数据,通过自定义的控制器(如基于 Operator 模式开发的控制器)监听这些指标,并根据预定义的规则动态调整 ResourceQuota 对象。当命名空间内的 CPU 使用率连续 10 分钟超过 80% 时,控制器自动将该命名空间的 CPU 配额增加 20%,以满足业务需求。

资源配额常见问题与解决方法

在使用 Kubernetes 资源配额的过程中,可能会遇到一些常见问题,下面介绍这些问题及相应的解决方法。

Pod 创建失败提示资源不足

  1. 原因分析:当创建 Pod 时,如果提示资源不足,可能是因为命名空间内的资源配额已用尽,或者 Pod 的资源请求超过了剩余配额。例如,命名空间的 CPU 请求配额为 2 个核心,而新创建的 Pod 请求 1 个核心,但当前命名空间已使用的 CPU 请求总和为 1.5 个核心,剩余 0.5 个核心,此时创建该 Pod 就会失败。
  2. 解决方法:首先,通过 kubectl describe resourcequota -n <namespace> 命令查看命名空间的资源使用情况,确定是哪种资源不足。如果是配额用尽,可以考虑调整资源配额;如果是 Pod 的资源请求不合理,可以适当降低 Pod 的资源请求值,然后重新创建 Pod。

容器因 OOM 被杀死

  1. 原因分析:容器因 OOM(Out - Of - Memory)被杀死,通常是因为容器使用的内存超过了其设置的内存限制。这可能是由于容器内的应用程序存在内存泄漏问题,或者内存限制设置过低,无法满足应用程序的正常运行需求。
  2. 解决方法:对于内存泄漏问题,需要对容器内的应用程序进行调试和优化,找出内存泄漏的代码段并进行修复。如果是内存限制设置过低,可以适当增加容器的内存限制。同时,可以通过监控工具(如 Prometheus + Grafana)持续观察容器的内存使用情况,以便及时发现和解决类似问题。

资源配额设置未生效

  1. 原因分析:资源配额设置未生效可能有多种原因。可能是 ResourceQuota 对象的配置有误,例如字段名称拼写错误、资源类型不支持等;也可能是命名空间的标签选择器配置不正确,导致 ResourceQuota 没有正确应用到目标命名空间;另外,Kubernetes 版本兼容性问题也可能导致资源配额设置不生效。
  2. 解决方法:首先,仔细检查 ResourceQuota 的配置文件,确保字段和语法正确。使用 kubectl describe resourcequota -n <namespace> 命令查看资源配额的状态,确认是否正确应用到了目标命名空间。如果怀疑是版本兼容性问题,可以查阅 Kubernetes 官方文档,了解当前版本对资源配额的支持情况,并考虑升级或降级 Kubernetes 版本。

资源配额与其他 Kubernetes 特性的集成

Kubernetes 的资源配额并不是孤立存在的,它与其他一些 Kubernetes 特性紧密集成,共同提升集群的资源管理能力。

与节点亲和性和反亲和性的集成

  1. 节点亲和性:节点亲和性允许将 Pod 调度到满足特定条件的节点上。当结合资源配额时,可以更好地控制资源在不同节点上的分配。例如,通过节点亲和性将高资源需求的 Pod 调度到配置较高的节点上,同时利用资源配额确保这些节点上的资源使用不会超过限制。
  2. 节点反亲和性:节点反亲和性则用于避免将 Pod 调度到某些节点上。与资源配额集成后,可以防止某些命名空间的 Pod 过度集中在特定节点,从而导致该节点资源耗尽。例如,通过设置节点反亲和性,确保某个命名空间的 Pod 均匀分布在多个节点上,再结合资源配额限制每个命名空间在各个节点上的资源使用,提高集群整体的资源利用率和稳定性。

与 Horizontal Pod Autoscaler (HPA) 的集成

  1. HPA 概述:Horizontal Pod Autoscaler (HPA) 可以根据 Pod 的 CPU 使用率或其他自定义指标自动调整 Pod 的副本数量,以适应业务负载的变化。
  2. 与资源配额集成:当 HPA 与资源配额集成时,需要确保在自动扩展 Pod 副本数量的过程中,不会超出命名空间的资源配额限制。例如,当业务负载增加,HPA 尝试增加 Pod 副本时,它会首先检查命名空间内的剩余资源配额是否足够。如果剩余配额不足,HPA 可能会暂停或部分暂停扩展操作,以避免违反资源配额。这种集成方式既保证了业务能够根据负载动态调整资源,又确保了资源使用在可控范围内。

与 NetworkPolicy 的集成

  1. NetworkPolicy 作用:NetworkPolicy 用于定义命名空间内 Pod 之间以及 Pod 与外部网络之间的网络访问策略。
  2. 与资源配额集成:在设置资源配额时,考虑到网络资源的使用也是很重要的。例如,通过 NetworkPolicy 限制某些命名空间的 Pod 与外部网络的连接数量,防止因大量网络连接导致网络资源耗尽。同时,资源配额也可以反过来影响 NetworkPolicy 的配置。如果某个命名空间的计算资源配额较低,为了保证该命名空间内 Pod 的正常运行,可以适当放宽其网络策略,允许使用更高效的网络连接方式(如直接连接而非代理),以减少计算资源在网络处理上的消耗。这种集成有助于在资源限制的情况下,优化网络资源的使用,提高应用程序的整体性能。