弹性之舞 - 自动伸缩 HPA、VPA 与 Cluster Autoscaler 详解

阅读 36

07-22 09:00

弹性之舞 - 自动伸缩 HPA、VPA 与 Cluster Autoscaler 详解

想象一下经营一家餐厅:如果总是按照最大客流量来配备厨师和服务员(静态资源配置),那么在客人少的时候就会有大量人力闲置浪费。反之,如果人手不足,高峰期客人就会等待过久,体验下降。理想的餐厅经理(自动伸缩机制)应该能根据客流量自动增减人手,甚至在长期爆满时考虑扩建餐厅(增加节点)。

Kubernetes 的自动伸缩就是为了解决类似的资源匹配问题。

1\. Pod 水平自动伸缩:Horizontal Pod Autoscaler (HPA)

  • 作用: HPA 根据观察到的指标(最常见的是 CPU 或内存使用率,也可以是自定义指标)自动增加或减少 Deployment、ReplicaSet 或 StatefulSet 中 Pod 的副本数量
  • 工作原理 (简化版):
  1. HPA 控制器定期从 Metrics Server(针对 CPU/内存)或自定义/外部指标 API 获取目标工作负载下所有 Pod 的指标数据。
  2. 将当前指标的平均值(或原始值,取决于目标类型)与 HPA 配置中设定的目标值进行比较。
  3. 根据比较结果,计算出期望的 Pod 副本数量(例如,如果当前 CPU 平均利用率是 80%,目标是 50%,HPA 可能会尝试增加副本数来降低平均利用率)。
  4. HPA 更新目标工作负载(如 Deployment)的 .spec.replicas 字段。Deployment Controller 接着会调整实际的 Pod 数量。
  • 指标来源:
  • 资源指标 (Resource Metrics):最常用的是基于 Pod 的平均 CPU 利用率 (target.type: Utilization) 或平均内存使用量 (target.type: AverageValue)。这需要集群中安装 Metrics Server 组件
  • 自定义指标 (Custom Metrics):基于应用程序自身暴露的、更能反映业务负载的指标(例如,每秒处理的队列任务数、每个 Pod 的活跃用户数)。通常需要通过 Prometheus Adapter 或其他自定义指标 API 服务器将这些指标暴露给 HPA。
  • 外部指标 (External Metrics):基于集群外部系统的指标(例如,云消息队列中的消息数量、外部负载均衡器的 QPS)。
  • 配置示例 (HPA YAML):

apiVersion: autoscaling/v2 # 推荐使用 v2 或 v2beta2,功能更全
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
  namespace: my-app-namespace
spec:
  scaleTargetRef: # 指向要伸缩的工作负载
    apiVersion: apps/v1
    kind: Deployment
    name: my-app-deployment
  minReplicas: 2     # 最小副本数
  maxReplicas: 10    # 最大副本数
  metrics:
  - type: Resource  # 基于资源指标
    resource:
      name: cpu
      target:
        type: Utilization # 目标类型为平均利用率
        averageUtilization: 70 # 目标平均 CPU 利用率为 70%
  # - type: Resource # 也可以基于内存
  #   resource:
  #     name: memory
  #     target:
  #       type: AverageValue # 目标类型为平均值 (更推荐 Utilization)
  #       averageValue: 500Mi # 目标平均内存使用量 (注意: 内存伸缩比 CPU 复杂,因为内存是不可压缩资源)
  # - type: Pods # 基于 Pod 暴露的自定义指标
  #   pods:
  #     metric:
  #       name: http_requests_per_second # Pod 暴露的自定义指标名
  #     target:
  #       type: AverageValue
  #       averageValue: "100" # 每个 Pod 平均处理 100 QPS

  • 关键字段: scaleTargetRef (指向目标工作负载), minReplicas, maxReplicas, metrics (列表,可定义多个伸缩指标,HPA 会分别计算并取最大的期望副本数)。
  • 效果: 创建 HPA后 (kubectl apply -f ...),K8s 会根据负载自动调整 my-app-deployment 的副本数。可以通过 kubectl get hpakubectl describe hpa my-app-hpa 查看 HPA 的状态、当前副本数、目标值和事件。
  • 对 SRE 的意义: HPA 是实现成本优化(低峰期自动缩容)和保障服务性能/可用性(高峰期自动扩容)的关键工具。SRE 需要配置、监控和调优 HPA 的参数。

2\. Pod 垂直自动伸缩:Vertical Pod Autoscaler (VPA)

  • 作用: 与 HPA 调整 Pod 数量不同,VPA 专注于自动调整单个 Pod 的资源请求 (requests) 和限制 (limits),主要是 CPU 和内存,使其更接近实际使用量,实现“量体裁衣”。
  • 工作原理 (简化版): VPA 通常包含几个组件:
  • Recommender: 监控 Pod 的历史资源使用情况,并给出新的 CPU 和内存 requests 的推荐值。
  • Updater: 如果 VPA 的 updateMode 设置为自动应用推荐值,当推荐值与当前值差异较大时,Updater 会驱逐 (evict) Pod,以便其控制器(如 Deployment)能够使用新的资源请求值来重建该 Pod。
  • Admission Controller: 在新 Pod 创建时(或被 Updater 驱逐重建时),根据 VPA 的推荐值(或配置的策略)修改 Pod 的资源请求。
  • 更新模式 (updateMode):
  • "Off" (或旧版中的 "None"): VPA 只会生成推荐值,不自动应用任何变更。适合初期观察和获取优化建议。
  • "Initial": 只在 Pod 创建时设置资源请求,之后不再更改。
  • "Recreate" (或新版中 "Auto" 通常默认行为): VPA 会根据推荐值自动更新 Pod 的资源请求,这通常需要重启 Pod
  • 配置示例 (VPA YAML):

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
  namespace: my-app-namespace
spec:
  targetRef: # 指向要垂直伸缩的工作负载
    apiVersion: "apps/v1"
    kind:       Deployment
    name:       my-app-deployment
  updatePolicy:
    updateMode: "Auto" # 或 "Recreate", "Initial", "Off"
  # resourcePolicy: # (可选) 控制 VPA 调整的资源范围和上下限
  #   containerPolicies:
  #   - containerName: '*' # 应用于所有容器
  #     minAllowed:
  #       cpu: "100m"
  #       memory: "128Mi"
  #     maxAllowed:
  #       cpu: "2"
  #       memory: "2Gi"
  #     controlledResources: ["cpu", "memory"] # 控制哪些资源
  #     controlledValues: RequestsAndLimits # 或 RequestsOnly (更安全)

  • 关键字段: targetRef (指向目标工作负载), updatePolicy.updateMode (更新模式), resourcePolicy (可选,用于限制 VPA 的调整范围,防止推荐值过高或过低)。
  • 效果: VPA 会持续监控目标 Pod 的资源使用,并在 kubectl describe vpa my-app-vpa 中给出推荐的 requests 值。如果 updateMode"Auto""Recreate",当推荐值与当前值有显著差异时,Pod 会被重启并应用新的资源请求。
  • 对 SRE 的意义: VPA 有助于提高资源利用率(避免资源浪费)、减少因资源不足导致的 OOMKilled 或 CPU 节流重要提示VPA 和 HPA(如果 HPA 基于 CPU/内存指标)通常不应同时作用于同一个工作负载的相同指标。因为它们一个调整资源请求,一个调整副本数,可能会互相干扰导致不可预测的行为。通常做法是:
  • 要么选择 HPA(更常见),要么选择 VPA(如果应用本身不适合水平扩展,或者副本数固定)。
  • 或者,VPA 运行在 "Off" 模式(只提供推荐),然后人工参考 VPA 的推荐值来调整 Pod 的 requests 和 HPA 的 targetAverageUtilization/Value
  • 较新版本的 HPA (autoscaling/v2) 可以配置为使用 VPA 推荐作为其伸缩目标的基础(较高级用法)。

3\. 集群节点自动伸缩:Cluster Autoscaler (CA)

  • 作用: 当集群中由于资源不足导致某些 Pod 无法被调度(处于 Pending 状态)时,CA 会自动向云服务商申请创建新的 Node。反之,当某些 Node 长时间处于低负载状态,并且其上运行的 Pod 可以被安全地重新调度到其他 Node 时,CA 会自动缩减这些 Node
  • 工作原理 (简化版):
  1. CA 监视那些因为资源不足而 Pending 的 Pod。
  2. 如果 CA 判断通过增加一个新的 Node(从预先配置好的节点组/池中选择实例类型)可以让这些 Pending Pod 成功调度,它就会向云服务商 API 发起创建 Node 的请求。
  3. CA 也会监控 Node 的资源利用率。如果一个 Node 长时间(可配置)利用率很低,并且其上所有 Pod 都可以被安全地驱逐并重新调度到其他 Node 上(会检查 PodDisruptionBudget, Affinity/Anti-affinity, PV 亲和性等),CA 就会先“排空 (drain)”该 Node 上的 Pod,然后向云服务商 API 发起删除 Node 的请求。
  • 与云服务商强相关: CA 的实现与具体的云平台(AWS, GCP, Azure 等)紧密耦合,因为它需要调用云平台的 API 来增删虚拟机实例。
  • 配置: 通常在集群层面进行配置,定义哪些节点池可以被 CA 管理,每个节点池的最小/最大节点数,以及一些伸缩参数。
  • 对 SRE 的意义: CA 是实现集群级别成本效益(按需使用节点资源)和容量保障(在负载增加时自动补充节点)的关键。SRE 需要部署、配置和监控 CA 的行为,理解其决策逻辑,并确保 Pod 的调度约束(如 PDB, 亲和性规则)与 CA 的行为兼容,避免不期望的驱逐。

协同工作与注意事项

  • HPA + CA: 这是最经典和有效的组合。HPA 负责应用层面的 Pod 副本数伸缩。当 HPA 想要增加 Pod 副本但现有 Node 资源不足时,Pending 的 Pod 会触发 CA 来增加新的 Node。当 HPA 缩减 Pod 副本导致某些 Node 空闲时,CA 最终会移除这些 Node。
  • VPA + CA: 也可以协同工作。VPA 负责优化单个 Pod 的资源请求。如果 VPA 增大了 Pod 的资源请求,导致现有 Node 放不下,Pending 的 Pod 可能会触发 CA 增加新的 Node(或更大规格的 Node,如果节点池支持)。
  • HPA + VPA 的谨慎使用: 如前所述,避免它们直接在 CPU/内存这两个指标上同时对同一个工作负载进行自动调整。
  • 调优至关重要: 所有的自动伸缩器都需要仔细调整参数(如目标值、阈值、冷却时间、扫描间隔等),以避免“抖动”(过于频繁地扩缩容)或响应过慢/过快。监控伸缩器的行为和事件是 SRE 的日常工作。

总结

Kubernetes 的自动伸缩三剑客——HPA(Pod 数量)、VPA(Pod 资源)和 Cluster Autoscaler(Node 数量)——为我们提供了强大的自动化能力,以应对动态变化的负载,优化资源利用率和成本,同时保障服务性能。作为 SRE,理解它们各自的职责、工作原理以及它们之间的协同与制约,是构建真正弹性、高效系统的关键。

现在,我们的应用不仅能被智能调度、持久化存储,还能根据负载自动伸缩了。但一个大规模的 K8s 集群本身就是一个复杂的分布式系统,我们如何监控集群自身的状态以及运行在上面的众多应用呢?下一篇,我们将探讨 Kubernetes 集群的监控与日志管理,了解 Metrics Server, kube-state-metrics, cAdvisor 等组件以及常见的日志收集方案。敬请期待!

精彩评论(0)

0 0 举报