54、Kubernetes Pod 调度与自动伸缩技术详解

Kubernetes Pod 调度与自动伸缩技术详解

1. 理解 Kubernetes 中的静态 Pod

静态 Pod 为 Kubernetes 集群内的 Pod 管理提供了一种不同的方式。与由集群的 Pod 调度器和 API 服务器控制的常规 Pod 不同,静态 Pod 由特定节点上的 kubelet 守护进程直接管理。除了 kubelet 为其创建的镜像 Pod 外,API 服务器并不知道这些 Pod 的存在。

静态 Pod 具有以下关键特性:
- 节点特定性 :静态 Pod 与单个节点绑定,无法在集群内的其他地方移动。
- Kubelet 管理 :指定节点上的 kubelet 负责启动、停止和重启静态 Pod。
- 镜像 Pod :kubelet 在 API 服务器上创建镜像 Pod 以反映静态 Pod 的状态,但这些镜像 Pod 无法通过 API 进行控制。

创建静态 Pod 主要有两种方法:
- 文件系统托管配置 :将 YAML 或 JSON 格式的 Pod 定义文件放置在节点上的特定目录中。kubelet 会定期扫描该目录,并根据其中的文件管理 Pod。
- Web 托管配置 :将 Pod 定义存储在 Web 服务器上的 YAML 文件中。kubelet 配置该文件的 URL,并定期下载以管理静态 Pod。

静态 Pod 常用于在每个节点上引导必要的集群组件,如 API 服务器或控制器管理器。不过,若要在集群的每个节点上运行 Pod,通常建议使用 DaemonSets。静态 Pod 存在一些限制,例如无法引用其他 Kubernetes 对象(如 Secrets 或 ConfigMaps),也不支持临时容器。在需要对单个节点上的 Pod 放置进行严格控制的场景中,了解静态 Pod 会很有用。

2. 扩展 Kubernetes 调度器配置

除了调度器自定义功能外,Kubernetes 还支持一些高级调度配置。

可以使用配置文件自定义调度行为,该文件根据各种标准定义调度器如何为 Pod 对节点进行优先级排序。涉及的关键概念如下:
- 调度配置文件 :配置文件可以指定多个调度配置文件。每个配置文件都有一个独特的名称,并可以配置自己的一组插件。
- 调度插件 :插件就像构建块,在调度过程中执行特定任务。它们可以根据资源可用性、硬件兼容性或其他因素过滤节点。
- 扩展点 :这些是调度过程中的阶段,插件可以在这些阶段插入。不同的插件适用于不同的阶段,例如过滤不合适的节点或对合适的节点进行评分。

Kubernetes 调度器配置文件为管理集群内的 Pod 放置提供了诸多好处,它能灵活地根据需求定制调度行为。例如,可以优先将需要 GPU 的 Pod 调度到具有这些资源的节点上。此外,还可以开发自定义插件来处理默认插件未解决的独特调度需求。最后,定义多个配置文件的能力允许通过为不同类型的 Pod 分配不同的调度配置文件来实现精细控制。

3. 节点隔离和限制

Kubernetes 允许使用节点标签将 Pod 隔离在特定节点上。这些标签可以定义诸如安全要求或法规合规性等属性,确保 Pod 仅调度到满足这些标准的节点上。为防止受损节点为自身利益操纵标签,NodeRestriction 准入插件限制 kubelet 修改具有特定前缀(例如 node-restriction.kubernetes.io/)的标签。

要利用此功能,需要启用 NodeRestriction 插件和节点授权器。然后,可以向节点添加具有受限前缀的标签,并在 Pod 的 nodeSelector 配置中引用这些标签,确保 Pod 仅在预定义的隔离环境中运行。

4. 调整 Kubernetes 调度器性能

在大型 Kubernetes 集群中,高效的调度器性能至关重要。其中一个关键的调整参数是 percentageOfNodesToScore。

percentageOfNodesToScore 设置决定了调度器在为 Pod 寻找合适放置位置时考虑的节点数量。较高的值意味着调度器会检查更多的节点,可能找到更合适的位置,但会花费更长时间;相反,较低的值会使调度更快,但可能导致放置效果不佳。可以在 kube-scheduler 配置文件中配置此值,有效范围是 1% 到 100%,默认值根据集群大小计算(100 个节点时为 50%,5000 个节点时为 10%)。

在 Kubernetes v1.23 之前的版本中,允许通过 kube-scheduler 标志或 ConfigMaps 指定调度策略。这些策略使用谓词(过滤条件)和优先级(评分函数)定义调度器如何为 Pod 选择节点。从 v1.23 版本开始,此功能被调度器配置所取代,新方法为调度行为提供了更多的灵活性和控制。

若要将拥有数百个节点的集群的 percentageOfNodesToScore 设置为 50%,需在调度器文件中包含以下配置:

apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
  provider: DefaultProvider
...
percentageOfNodesToScore: 50

最优值取决于优先级。如果快速调度至关重要,较低的值可能是可以接受的;但如果确保最佳放置位置比速度更重要,则建议使用较高的值。避免将其设置得过低,以免调度器忽略可能更好的节点。

5. Pod 资源请求和限制

在深入探讨 Kubernetes 中的自动伸缩主题之前,需要更深入地了解如何使用 Pod 容器控制 CPU 和内存资源(即计算资源)的使用。控制计算资源的使用很重要,因为这样可以实施资源治理,有助于更好地规划集群容量,最重要的是可以防止单个容器消耗所有计算资源,从而避免其他 Pod 无法处理请求的情况。

创建 Pod 时,可以指定其容器所需的计算资源量以及允许的最大消耗量。Kubernetes 资源模型将资源分为两类:可压缩资源和不可压缩资源。可压缩资源可以轻松节流,而不会产生严重后果,例如 CPU;不可压缩资源在节流时会产生严重后果,例如内存分配。

为控制 Pod 容器的资源,可以在其规范中指定两个值:
- requests :指定系统保证提供的给定资源量,也可以理解为 Pod 容器正常运行所需的资源量。Pod 调度依赖于 requests 值(而非 limits),特别是 PodFitsResources 谓词和 BalancedResourceAllocation 优先级。
- limits :指定系统提供的给定资源的最大量。如果与 requests 一起指定,此值必须大于或等于 requests。根据资源是可压缩还是不可压缩,超过限制会有不同的后果:可压缩资源(CPU)将被节流,而不可压缩资源(RAM)可能导致容器被杀死并重启。

可以通过设置不同的 requests 和 limits 值来允许资源超量使用。系统可以更从容地处理短暂的高资源使用期,同时优化整体资源利用率。这是因为一个节点上的所有容器不太可能同时达到其资源限制。因此,Kubernetes 大部分时间可以更有效地利用可用资源,类似于虚拟机的过度配置或航空公司的超售。

在 Kubernetes 中,CPU 和内存的测量单位如下:
- CPU :基本单位是 Kubernetes CPU(KCU),1 KCU 相当于例如 Azure 上的 1 vCPU、GCP 上的 1 个核心或裸机机器上的 1 个超线程核心。允许使用小数值,例如 0.1 也可以指定为 100m(毫 KCU)。
- 内存 :基本单位是字节,可以使用标准单位前缀,如 M、Mi、G、Gi。

在更高级的场景中,还可以控制大页面和临时存储的请求和限制。

以下是为 nginx Deployment 中的 Pod 容器启用计算资源请求和限制的 YAML 清单示例:

# resource-limit/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-example
spec:
  replicas: 5
  ...<removed for brevity>...
    spec:
      containers:
        - name: nginx
          image: nginx:1.17
          ports:
            - containerPort: 80
          resources:
            limits:
              cpu: 200m
              memory: 60Mi
            requests:
              cpu: 100m
              memory: 50Mi

当使用 kubectl apply -f resource-limit/nginx-deployment.yaml 将清单应用到集群,并描述运行此 Deployment 的 Pod 的其中一个节点时,可以看到计算资源配额和分配的详细信息:

$ kubectl describe node minikube-m03
...<removed for brevity>...
Non-terminated Pods:          (5 in total)
  Namespace                   Name                                         CPU 
Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                         ----
--------  ----------  ---------------  -------------  ---
  default                     nginx-deployment-example-6d444cfd96-f5tnq    100m 
(5%)     200m (10%)  50Mi (2%)        60Mi (3%)      23s
  default                     nginx-deployment-example-6d444cfd96-k6j9d    100m 
(5%)     200m (10%)  50Mi (2%)        60Mi (3%)      23s
  default                     nginx-deployment-example-6d444cfd96-mqxxp    100m 
(5%)     200m (10%)  50Mi (2%)        60Mi (3%)      23s
  kube-system                 calico-node-92bdc                            250m 
(12%)    0 (0%)      0 (0%)           0 (0%)         6d23h
  kube-system                 kube-proxy-5cd4x                             0 
(0%)        0 (0%)      0 (0%)           0 (0%)         6d23h
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                550m (27%)  600m (30%)
  memory             150Mi (7%)  180Mi (9%)
  ephemeral-storage  0 (0%)      0 (0%)
  hugepages-2Mi      0 (0%)      0 (0%)
Events:              <none>

基于此信息,可以进行实验,将容器的 CPU requests 设置为高于集群中单个节点的容量。例如,在 resource-limit/nginx-deployment.yaml 中修改值如下:

...
          resources:
            limits:
              cpu: 2000m
              memory: 60Mi
            requests:
              cpu: 2000m
              memory: 50Mi
...

应用配置:

$ kubectl apply -f resource-limit/nginx-deployment.yaml
deployment.apps/nginx-deployment-example configured

检查 Pod 状态时,会发现新的 Pod 处于 Pending 状态,因为它们无法调度到匹配的节点:

$ kubectl get pod
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-deployment-example-59b669d85f-cdptx   1/1     Running   0          52s
nginx-deployment-example-59b669d85f-hdzdf   1/1     Running   0          54s
nginx-deployment-example-59b669d85f-ktn59   1/1     Running   0          54s

通过这些操作,可以更好地理解和控制 Kubernetes 中 Pod 的资源使用和调度。

Kubernetes Pod 调度与自动伸缩技术详解

6. Kubernetes 中的自动伸缩功能概述

在云环境中运行应用程序时,具备自动伸缩能力被视为理想状态。自动伸缩指的是根据终端用户的活动和需求,自动动态调整应用程序可用的计算资源(如 CPU 和内存)的方法。其目标是根据实际情况添加或移除资源,既能为用户提供高可用性的服务,又能降低业务成本。

Kubernetes 作为成熟的容器编排系统,拥有多种内置的自动伸缩功能,部分功能在每个 Kubernetes 集群中都原生支持,部分则需要安装或特定的集群部署类型。自动伸缩主要有以下几个维度:
| 伸缩维度 | 描述 | 实现方式 |
| ---- | ---- | ---- |
| 垂直 Pod 伸缩 | 调整 Pod 可用的 CPU 和内存资源量,防止资源过度消耗,并可自动调整资源限制 | VerticalPodAutoscaler (VPA) |
| 水平 Pod 伸缩 | 动态更改 Deployment 或 StatefulSet 的 Pod 副本数量 | HorizontalPodAutoscaler (HPA) |
| 水平节点伸缩 | 在 Kubernetes 节点级别进行水平扩展,通过添加或移除节点来扩展整个集群 | Cluster Autoscaler (CA),部分云供应商可用 |

7. 垂直 Pod 自动伸缩(VPA)

垂直 Pod 自动伸缩(VPA)用于调整 Pod 可用的 CPU 和内存资源。Pod 可以在指定的 CPU 和内存限制下运行,但这些限制可能需要自动调整,而不是由人工猜测。

VPA 的工作流程如下:

graph LR
    A[监控 Pod 资源使用情况] --> B[分析资源需求]
    B --> C[调整 Pod 资源限制]
    C --> D[应用新的资源配置]

要使用 VPA,需要满足以下技术要求:
- 部署一个 Kubernetes 集群,建议使用多节点集群。
- 一个多节点 Google Kubernetes Engine (GKE) 集群,这是 VPA 和集群自动伸缩的先决条件。
- 在本地机器上安装并配置 Kubernetes CLI (kubectl) 以管理集群。

8. 水平 Pod 自动伸缩(HPA)

水平 Pod 自动伸缩(HPA)用于动态更改 Deployment 或 StatefulSet 的 Pod 副本数量。这些对象本身具有良好的伸缩功能,但可以使用 HPA 自动调整副本数量。

以下是创建 HPA 的步骤:
1. 确保你有一个运行中的 Deployment 或 StatefulSet。
2. 创建一个 HPA 配置文件,例如:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  1. 使用 kubectl apply -f <hpa-config-file.yaml> 应用 HPA 配置。

HPA 会根据指定的指标(如 CPU 利用率)自动调整 Pod 副本数量,以确保应用程序能够应对不同的负载。

9. 水平节点自动伸缩(CA)

水平节点自动伸缩(CA)用于在 Kubernetes 节点级别进行水平扩展,通过添加或移除节点来扩展整个集群。这需要在支持动态机器供应的环境(如云环境)中运行的 Kubernetes 部署。

CA 的工作原理如下:

graph LR
    A[监控集群资源使用情况] --> B[判断是否需要添加或移除节点]
    B -- 需要添加节点 --> C[请求云供应商创建新节点]
    B -- 需要移除节点 --> D[删除空闲节点]
    C --> E[新节点加入集群]
    D --> F[节点从集群中移除]

要使用 CA,需要确保你的云供应商支持该功能,并按照其文档进行配置。

10. 替代自动伸缩器

除了 Kubernetes 内置的自动伸缩功能外,还有一些替代自动伸缩器可供选择,它们可能提供额外的功能或更好地适应特定的使用场景。这些替代自动伸缩器通常具有不同的特点和配置方式,在选择时需要根据具体需求进行评估。

总结

本文详细介绍了 Kubernetes 中 Pod 调度和自动伸缩的相关技术。首先介绍了静态 Pod 的概念、特性和创建方法,以及扩展调度器配置、节点隔离和限制、调度器性能调整等高级调度功能。接着深入探讨了 Pod 资源请求和限制的设置,以及不同类型的自动伸缩功能,包括垂直 Pod 自动伸缩、水平 Pod 自动伸缩和水平节点自动伸缩。

通过合理使用这些技术,可以更好地管理 Kubernetes 集群中的资源,提高应用程序的可用性和性能,同时降低成本。在实际应用中,需要根据具体需求和场景选择合适的调度和自动伸缩策略,并进行适当的配置和调整。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值