水平 Pod 自动扩缩容 (HPA)

OpenTelemetry Operator 管理的 Collector 内置支持水平 Pod 自动扩缩容(Horizontal Pod Autoscaling,HPA)。HPA 可以根据 CPU 和内存使用率自动增加或减少 Collector Pod 的副本数,确保 Collector 能够根据负载自动调整规模,提高资源利用率和系统稳定性。

概述

什么是 HPA?

水平 Pod 自动扩缩容(HPA)是 Kubernetes 的一个功能,它可以根据观察到的 CPU 使用率、内存使用率或其他自定义指标,自动增加或减少 Pod 的副本数。HPA 确保应用能够根据实际负载自动调整规模,既不会因为资源不足而影响性能,也不会因为资源浪费而增加成本。

HPA 的工作原理

┌─────────────────────────────────────────────────────────┐
│ HPA Controller │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 1. 查询 Metrics Server 获取当前指标 │ │
│ │ 2. 计算期望副本数 │ │
│ │ 3. 更新 Deployment/StatefulSet 的副本数 │ │
│ └─────────────────────────────────────────────────┘ │
└────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Metrics Server │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 收集 Pod 的 CPU 和内存使用率 │ │
│ │ 提供 metrics.k8s.io API │ │
│ └─────────────────────────────────────────────────┘ │
└────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Collector Pods │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │ │
│ │ CPU: 60% │ │ CPU: 55% │ │ CPU: 58% │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘

HPA 的优势

  • 自动化:无需手动调整副本数,系统自动响应负载变化
  • 资源优化:根据实际需求动态调整资源,避免资源浪费
  • 高可用性:在负载增加时自动扩容,确保服务可用性
  • 成本控制:在负载降低时自动缩容,降低资源成本
  • 简化运维:减少人工干预,降低运维复杂度

Operator 的 HPA 支持

OpenTelemetry Operator 内置了 HPA 功能,这意味着:

  • 无需手动创建 HPA:Operator 会自动创建和管理 HPA 资源
  • 统一配置:在 OpenTelemetryCollector 资源中配置 HPA 参数
  • 自动管理:Operator 负责 HPA 的创建、更新和删除

前置要求

在使用 HPA 之前,需要确保满足以下要求:

Metrics Server

HPA 需要 Metrics Server 来获取 Pod 的 CPU 和内存使用率。Metrics Server 是 Kubernetes 集群的组件,用于收集和提供资源使用指标。

检查 Metrics Server

# 检查 Metrics Server 是否已安装
kubectl get pods -n kube-system | grep metrics-server
# 检查 Metrics Server API 是否可用
kubectl top nodes
kubectl top pods

如果命令执行成功,说明 Metrics Server 已安装并正常工作。

不同云平台的 Metrics Server 状态

Google Kubernetes Engine (GKE):

  • Metrics Server 在集群创建时自动安装
  • 无需手动安装

Azure Kubernetes Service (AKS):

  • Metrics Server 在集群创建时自动安装
  • 无需手动安装

Amazon Elastic Kubernetes Service (EKS):

  • 默认不安装 Metrics Server
  • 需要手动安装

本地 Kubernetes 集群(如 Minikube、KinD、k0s):

  • 需要手动安装 Metrics Server

安装 Metrics Server

如果您的集群没有 Metrics Server,可以按以下步骤安装:

在 EKS 上安装:

# 下载 Metrics Server 清单
curl -L https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -o metrics-server.yaml
# 修改配置以支持 EKS(如果需要)
# 在 args 中添加:--kubelet-insecure-tls
# 应用配置
kubectl apply -f metrics-server.yaml
# 验证安装
kubectl get pods -n kube-system | grep metrics-server

在本地集群安装:

# Minikube
minikube addons enable metrics-server
# KinD 或其他集群
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

验证 Metrics Server:

# 等待 Metrics Server 就绪
kubectl wait --for=condition=ready pod -l k8s-app=metrics-server -n kube-system --timeout=300s
# 测试 Metrics API
kubectl top nodes
kubectl top pods --all-namespaces

部署模式要求

HPA 只适用于 Deployment 和 StatefulSet 模式。如果 Collector 使用 DaemonSet 模式,则不支持 HPA。

确保 Collector 的 spec.mode 设置为 deployment 或 statefulset:

spec:
mode: deployment # 或 statefulset

配置资源请求和限制

在配置 HPA 之前,必须先为 Collector 配置资源请求(requests)和限制(limits)。HPA 使用这些值来计算资源使用率。

为什么需要资源请求和限制?

  • 资源请求(requests):Kubernetes 调度器使用此值来确保 Pod 有足够的资源运行
  • 资源限制(limits):Kubernetes 使用此值来限制 Pod 的最大资源使用
  • HPA 计算:HPA 使用资源使用率(实际使用量 / 请求量)来决定是否需要扩缩容

配置示例

基本配置

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otelcol
spec:
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 64Mi

配置说明

limits(限制):

  • cpu: 100m:最大 CPU 使用量为 100 millicores(0.1 核心)
  • memory: 128Mi:最大内存使用量为 128 mebibytes(约 134 MB)

requests(请求):

  • cpu: 100m:保证的 CPU 资源为 100 millicores
  • memory: 64Mi:保证的内存资源为 64 mebibytes(约 67 MB)

资源单位说明

CPU 单位:

  • 1 = 1 个 CPU 核心
  • 1000m = 1 个 CPU 核心
  • 500m = 0.5 个 CPU 核心
  • 100m = 0.1 个 CPU 核心

内存单位:

  • 1Gi = 1024 MiB = 1,073,741,824 字节
  • 1Mi = 1024 KiB = 1,048,576 字节
  • 128Mi = 134,217,728 字节

资源配置建议

小型部署

适用于低流量场景:

resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi

中型部署

适用于中等流量场景:

resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi

大型部署

适用于高流量场景:

resources:
limits:
cpu: 4000m
memory: 4Gi
requests:
cpu: 1000m
memory: 1Gi

资源配置注意事项

  1. requests 和 limits 的关系:

    • requests 应该小于或等于 limits
    • HPA 使用 requests 作为基准计算使用率
  2. CPU 配置:

    • CPU 是可压缩资源,可以超量分配
    • 建议 requests 和 limits 相同,避免 CPU 节流
  3. 内存配置:

    • 内存是不可压缩资源,不能超量分配
    • limits 应该大于 requests,为突发流量留出空间
  4. 实际需求:

    • 根据实际负载调整资源配置
    • 监控 Collector 的实际资源使用情况
    • 定期调整配置以优化资源利用

配置自动扩缩容规则

配置资源请求和限制后,可以配置 HPA 的自动扩缩容规则。

基本配置

在 OpenTelemetryCollector 资源中添加 autoscaler 配置:

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otelcol
spec:
autoscaler:
minReplicas: 1
maxReplicas: 3
targetCPUUtilization: 50
targetMemoryUtilization: 60

配置参数说明

minReplicas(最小副本数)

  • 类型:整数
  • 默认值:1
  • 说明:Collector 的最小副本数,即使负载很低也不会低于此值
  • 建议:生产环境建议设置为 2 或更高,确保高可用性

maxReplicas(最大副本数)

  • 类型:整数
  • 默认值:无(必须指定)
  • 说明:Collector 的最大副本数,即使负载很高也不会超过此值
  • 建议:根据集群容量和预期负载设置合理值

targetCPUUtilization(目标 CPU 使用率)

  • 类型:整数(百分比)
  • 默认值:无(必须指定)
  • 说明:目标 CPU 使用率,HPA 会尝试将平均 CPU 使用率维持在此值
  • 单位:百分比(例如,50 表示 50%)
  • 建议:通常设置为 50-80%

targetMemoryUtilization(目标内存使用率)

  • 类型:整数(百分比)
  • 默认值:无(必须指定)
  • 说明:目标内存使用率,HPA 会尝试将平均内存使用率维持在此值
  • 单位:百分比(例如,60 表示 60%)
  • 建议:通常设置为 60-80%

配置示例

示例 1:仅基于 CPU

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otelcol
spec:
mode: deployment
resources:
limits:
cpu: 1000m
memory: 512Mi
requests:
cpu: 500m
memory: 256Mi
autoscaler:
minReplicas: 2
maxReplicas: 10
targetCPUUtilization: 70

示例 2:基于 CPU 和内存

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otelcol
spec:
mode: statefulset
resources:
limits:
cpu: 2000m
memory: 1Gi
requests:
cpu: 1000m
memory: 512Mi
autoscaler:
minReplicas: 2
maxReplicas: 10
targetCPUUtilization: 70
targetMemoryUtilization: 80

示例 3:高可用配置

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otelcol
spec:
mode: deployment
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m
memory: 1Gi
autoscaler:
minReplicas: 3
maxReplicas: 20
targetCPUUtilization: 60
targetMemoryUtilization: 70

扩缩容行为

HPA 会根据以下规则进行扩缩容:

  1. 计算当前使用率:

    • CPU 使用率 = (当前 CPU 使用量 / CPU 请求量) × 100%
    • 内存使用率 = (当前内存使用量 / 内存请求量) × 100%
  2. 计算期望副本数:

    • 期望副本数 = (当前副本数 × 当前使用率) / 目标使用率
    • 如果同时配置了 CPU 和内存,取两者中的较大值
  3. 应用限制:

    • 如果期望副本数 < minReplicas,设置为 minReplicas
    • 如果期望副本数 > maxReplicas,设置为 maxReplicas
  4. 执行扩缩容:

    • 更新 Deployment 或 StatefulSet 的副本数
    • 等待 Pod 创建或删除完成

完整配置示例

以下是一个完整的 OpenTelemetryCollector 配置示例,包含 HPA 配置:

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otelcol
namespace: opentelemetry
spec:
mode: statefulset
image: otel/opentelemetry-collector-contrib:v0.100.0
serviceAccount: otelcontribcol
# 资源请求和限制
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m
memory: 1Gi
# HPA 配置
autoscaler:
minReplicas: 2
maxReplicas: 10
targetCPUUtilization: 70
targetMemoryUtilization: 80
# Collector 配置
config: |
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 75
spike_limit_percentage: 15
batch:
timeout: 1s
send_batch_size: 1024
exporters:
otlp:
endpoint: uptrace-grpc.yodao.cn:4317
tls:
insecure: false
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp]

应用配置

保存配置到文件(例如 collector-with-hpa.yaml),然后应用:

# 应用配置
kubectl apply -f collector-with-hpa.yaml
# 检查 Collector 状态
kubectl get opentelemetrycollector otelcol -n opentelemetry
# 检查 HPA 是否创建
kubectl get hpa -n opentelemetry

验证 HPA

配置 HPA 后,需要验证 HPA 是否正常工作。

检查 HPA 资源

# 查看 HPA 资源
kubectl get hpa -n <namespace>
# 预期输出示例:
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# otelcol-collector OpenTelemetryCollector/otelcol memory: 68%/80%, cpu: 37%/70% 2 10 3 5m

查看 HPA 详细信息

# 查看 HPA 详细信息
kubectl describe hpa <hpa-name> -n <namespace>

预期输出示例:

Name: otelcol-collector
Namespace: opentelemetry
Labels: app.kubernetes.io/component=opentelemetry-collector
app.kubernetes.io/instance=opentelemetry.otelcol
app.kubernetes.io/managed-by=opentelemetry-operator
app.kubernetes.io/name=otelcol-collector
app.kubernetes.io/part-of=opentelemetry
Annotations: <none>
CreationTimestamp: Mon, 02 Jun 2025 17:23:52 +0000
Reference: OpenTelemetryCollector/otelcol
Metrics: ( current / target )
resource memory on pods (as a percentage of request): 71% (95779498666m) / 80%
resource cpu on pods (as a percentage of request): 37% (37m) / 70%
Min replicas: 2
Max replicas: 10
OpenTelemetryCollector pods: 3 current / 3 desired
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True ReadyForNewScale recommended size matches current size
ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from memory resource utilization (percentage of request)
ScalingLimited False DesiredWithinRange the desired replica count is within the acceptable range
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulRescale 2m horizontal-pod-autoscaler New size: 2; reason: memory resource utilization (percentage of request) above target
Normal SuccessfulRescale 1m horizontal-pod-autoscaler New size: 3; reason: memory resource utilization (percentage of request) above target

检查 Pod 副本数

# 查看 Collector Pod 数量
kubectl get pods -l app.kubernetes.io/name=opentelemetry-collector -n <namespace>
# 查看 Deployment 或 StatefulSet 的副本数
kubectl get deployment -n <namespace> | grep collector
# 或
kubectl get statefulset -n <namespace> | grep collector

监控 HPA 行为

实时监控

# 持续监控 HPA 状态
watch kubectl get hpa -n <namespace>
# 持续监控 Pod 数量
watch kubectl get pods -l app.kubernetes.io/name=opentelemetry-collector -n <namespace>

查看 HPA 事件

# 查看 HPA 事件
kubectl describe hpa <hpa-name> -n <namespace> | grep Events -A 10

测试扩缩容

增加负载测试扩容

可以通过增加发送到 Collector 的数据量来测试扩容:

# 使用负载生成工具增加数据量
# 观察 HPA 是否自动增加副本数
watch kubectl get hpa -n <namespace>

减少负载测试缩容

停止负载生成,观察 HPA 是否自动减少副本数:

# 停止负载生成
# 等待一段时间(通常几分钟)
# 观察 HPA 是否自动减少副本数
watch kubectl get hpa -n <namespace>

最佳实践

1. 合理设置最小副本数

  • 生产环境:建议设置为 2 或更高,确保高可用性
  • 开发/测试环境:可以设置为 1
autoscaler:
minReplicas: 2 # 生产环境
# minReplicas: 1 # 开发/测试环境

2. 合理设置最大副本数

  • 根据集群容量和预期负载设置
  • 考虑成本因素
  • 预留一定的缓冲空间
autoscaler:
maxReplicas: 10 # 根据实际需求调整

3. 合理设置目标使用率

  • CPU 使用率:通常设置为 50-80%

    • 较低的值(50-60%)提供更多缓冲,但可能增加成本
    • 较高的值(70-80%)提高资源利用率,但可能影响性能
  • 内存使用率:通常设置为 60-80%

    • 内存是不可压缩资源,建议设置较低的值
autoscaler:
targetCPUUtilization: 70
targetMemoryUtilization: 75

4. 同时监控 CPU 和内存

建议同时配置 CPU 和内存目标使用率,HPA 会取两者中的较大值:

autoscaler:
targetCPUUtilization: 70
targetMemoryUtilization: 80

5. 合理配置资源请求

  • requests 应该反映 Collector 的正常负载
  • limits 应该为突发流量留出空间
  • HPA 使用 requests 作为基准,因此 requests 的设置很重要
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m # 正常负载
memory: 1Gi # 正常负载

6. 监控 HPA 行为

定期检查 HPA 的行为:

  • 扩缩容频率是否合理
  • 副本数是否在预期范围内
  • 是否有频繁的扩缩容(抖动)

7. 使用 StatefulSet 模式

对于需要持久化存储或有序部署的场景,使用 StatefulSet 模式:

spec:
mode: statefulset

8. 考虑扩缩容延迟

HPA 有一定的延迟:

  • 指标收集延迟:Metrics Server 收集指标需要时间
  • 决策延迟:HPA 需要一定时间来决定是否扩缩容
  • Pod 创建/删除延迟:Pod 的创建和删除需要时间

因此,HPA 更适合处理逐渐变化的负载,而不是突发流量。

常见问题

1. HPA 不工作?

检查步骤:

# 1. 检查 Metrics Server
kubectl get pods -n kube-system | grep metrics-server
kubectl top nodes
# 2. 检查 HPA 资源
kubectl get hpa -n <namespace>
# 3. 检查 HPA 详细信息
kubectl describe hpa <hpa-name> -n <namespace>
# 4. 检查 Collector 资源请求和限制
kubectl get opentelemetrycollector <name> -o yaml | grep -A 10 resources
# 5. 检查 Collector 部署模式
kubectl get opentelemetrycollector <name> -o yaml | grep mode

常见原因:

  • Metrics Server 未安装或未正常工作
  • 资源请求和限制未配置
  • 部署模式不是 deployment 或 statefulset
  • HPA 配置错误

2. HPA 显示 "unknown" 状态?

可能原因:

  • Metrics Server 未正常工作
  • Pod 刚创建,还没有指标数据

解决方法:

# 检查 Metrics Server
kubectl get pods -n kube-system | grep metrics-server
kubectl logs -n kube-system -l k8s-app=metrics-server
# 等待一段时间后再次检查
kubectl get hpa -n <namespace>

3. HPA 频繁扩缩容(抖动)?

可能原因:

  • 目标使用率设置不合理
  • 负载波动较大
  • 资源请求设置不合理

解决方法:

  • 调整目标使用率,提供更多缓冲
  • 增加资源请求,减少使用率波动
  • 考虑使用自定义指标或外部指标

4. HPA 不缩容?

可能原因:

  • 最小副本数设置过高
  • 实际使用率仍然高于目标
  • HPA 有延迟

解决方法:

# 检查当前使用率
kubectl describe hpa <hpa-name> -n <namespace>
# 检查最小副本数
kubectl get hpa <hpa-name> -n <namespace> -o yaml | grep minReplicas

5. 如何禁用 HPA?

删除 autoscaler 配置或设置为空:

spec:
# autoscaler: {} # 注释掉或删除

然后手动设置副本数:

spec:
replicas: 3

6. HPA 支持自定义指标吗?

当前 Operator 的 HPA 配置只支持 CPU 和内存指标。如果需要使用自定义指标,需要:

  1. 安装 Prometheus Adapter 或其他指标适配器
  2. 手动创建 HPA 资源(不使用 Operator 的 autoscaler 配置)

7. HPA 扩缩容速度如何?

HPA 的扩缩容速度取决于:

  • Metrics Server 的指标收集间隔(通常 15-30 秒)
  • HPA 的评估间隔(通常 15 秒)
  • Pod 的创建/删除时间(通常 30 秒到几分钟)

总体而言,从负载变化到完成扩缩容,通常需要 1-5 分钟。

下一步

参考资源

在Gitlab上编辑本文档