云原生:使用HPA和VPA实现集群扩缩容

1 背景

我们之前介绍过,随着业务流量上涨之后,我们的系统需要适时的进行扩容。

数据存储层我们也介绍过MySQL的扩容 Scale UP(纵向扩展) 和 Scale Out(横向扩展)

  • 垂直拆分(Scale Up 纵向扩展):包括垂直分库、垂直分表
  • 水平拆分(Scale Out 横向扩展):包括库内分表、分库分表

详细可以参考笔者这几篇:

MySQL全面瓦解28:分库分表

MySQL全面瓦解29:分库分表之Partition功能详解

数据库系列:数据库高可用及无损扩容

存储层有高效动态的扩缩容机制,那计算服务也应该同步有这种能力,这样才能保证流量上涨时能够快速扩容。

如下图, 蓝色部件是扩容的部分,每一分层都有自己的扩容机制。

现在服务大都为云上服务,所以接下来我们详细介绍下Kubernetes中的HPA和VPA。

2 容器扩缩容介绍

2.1 先看下 HPA 和 VPA 的概念

VPA(Vertical Pod Autoscaler)和HPA(Horizontal Pod Autoscaler)都是Kubernetes中的自动扩展功能,但它们的作用对象和扩展方式不同。

HPA(纵向)的作用对象是Pod的数量。 它通过监控CPU使用率、内存使用率等指标,根据预设的阈值自动调整Pod的数量(即当个集群副本的数量)。当Pod的CPU和内存使用率超过阈值时,HPA会自动增加Pod的数量;当使用率下降时,HPA会自动减少Pod的数量。

VPA的作用对象是Pod的资源需求,如CPU、内存等。 它通过监控Pod的资源使用情况,根据实际的资源需求自动调整Pod的资源限制和请求。当Pod的资源使用率高于资源请求时,VPA会自动增加Pod的资源Request和Limit;当资源使用率下降时,VPA会自动减少Pod的资源Requist和Limit。这种方式可以帮助优化资源利用率,避免资源浪费。

2.2 HPA实现详解

HPA(纵向)的作用对象是Pod的数量。可针对CPU使用率、内存使用率进行扩缩容配置,会根据期望指标,会触发扩容或者缩容,若同时有多个指标,会取Max值。

如下图:

解读下:

  1. 设计HPA资源,包含实现扩容的条件
  2. 策略Yaml应用到HPA控制器中
  3. HPA控制器监听Prometheus,获取多个Metrix指标,如内存、CPU、连接数等
  4. 当监听的数据值大于等于扩容条件的阈值的时候,执行扩容操作
  5. 修改 replication controller, deployment, replica set, stateful set 中的pod数量
  6. 控制器定期调整 副本控制器(replica set) 或 部署(deploy) 中副本的数量

算法解析:

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

即 (当前指标值 ➗ 期望指标值) ✖️ 当前副本数 ,结果再向上取整,最终结果就是期望的副本数量

举例说明:

apiVersion: autoscaling/v2beta2  
kind: HorizontalPodAutoscaler  
metadata:  
  name: hpa-example  
spec:  
  scaleTargetRef:  
    apiVersion: apps/v1  
    kind: Deployment  
    name: hpa-example  
  minReplicas: 10  # Pod副本数下限
  maxReplicas: 20  # Pod副本数上限
  metrics:  
  - type: Resource  
    resource:  
      name: cpu  
      target:  
        type: Utilization  
        averageUtilization: 60  # 当CPU利用率大于60%或者内存占用大于60%的时候,执行调整
  1. 假设当前指标:CPU利用率 70%
  2. 期望指标:CPU利用率60%
  3. 假设当前副本数:10
  4. 期望副本数:ceil(10*(70/60))=12
  5. 最终总的Pod副本数应该是12,即扩容数量为2
  6. 注意扩容和缩容幅度不能超过 HorizontalPodAutoscaler 资源中的副本上下限

2.3 VPA实现详解

因为VPA影响的是Pod的Request和Limit这两个参数,所以我们先了解下这两个属性的含义。
1. Request表示容器在运行过程中所需的最小资源量,即容器启动时的资源保证。

当Pod被调度到节点上时,Kubernetes会确保该节点上至少有足够的资源来满足Pod中所有容器的Request值。如果节点的可用资源无法满足Pod的Request值,则不会被调度到该节点上,而是保持在Pending状态,直到找到满足条件的节点为止。
因此,合理设置Request值可以确保Pod的稳定性和可靠性。

2. Limit则表示容器在运行过程中可以使用的最大资源量,即容器可以消耗的资源上限。

如果容器的实际资源使用量超过了Limit值,Kubernetes会采取相应的措施来限制容器的资源使用,例如限制CPU使用率、杀死进程等,以确保不会因资源不足而导致系统崩溃或性能下降。
通过设置Limit值,可以有效地防止单个容器或整个Pod占用过多的资源,从而影响整个集群的性能和稳定性。

apiVersion: v1
kind: Pod
  - apiVersion: v1
  name: xx-default-756gh8588cc
  namespace: xx-ns
spec:  
  containers:    
    name: xx-default
    resources:
      limits:  # 对应上限最大值
        cpu: "2"
        memory: 8G
      requests:  # 对应下限最小值
        cpu: 200m
        memory: 500Mi

而 VPA 是Kubernetes的一种自动调整Pod资源请求(Request)配额的工具。通过VPA,您可以根据Pod的实际资源使用情况动态地调整其CPU和内存资源请求(Request),以实现更精细的资源管理和更好的资源利用率。
简单理解就是 取服务一定周期内(如8天内) CPU 和内存资源用量的 TP90 分位数据作为推荐值,可以参考kubernetes的算法

举例说明:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: myapp-vpa-default
  namespace: xx-ns
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp-vpa-default
  updatePolicy:
    updateMode: "Off"  # 不直接进行修改
status:
  recommendation:
    containerRecommendations:
    - containerName: msg-index-default
      lowerBound: # 下限值
        cpu: 480m
        memory: "7117753323"
      target:  # 推荐值
        cpu: 930m
        memory: "8701517761"
      uncappedTarget:
        cpu: 930m
        memory: "8701517761"
      upperBound: # 上限值
        cpu: 1100m
        memory: "8841153193"

在这个配置中,我们定义了一个名为myapp-vpa的VPA,它将调整名为myapp的Deployment中的Pod的资源。

从输出信息可以看出,VPA对Pod给出了推荐值:Cpu: 930m,Memory: 8Gi,因为 updatePolicy 策略设置了updateMode: "Off",所以不会主动更新Pod。

上面的案例可以通过下面的图进行演进:通过VPA的推荐,我们将Request值从 200m的CPU 和 500Mi 的内存,调整为 1 Core 的CPU 和 8Gi 的内存。

调优完成之后,资源分配更加合理,资源更充足,性能、稳定性更高。

3 总结

总的来说,HPA是通过自动调整Pod的数量来应对负载压力,而VPA是通过自动调整Pod的资源需求来优化资源利用率。它们可以配合使用,实现更加精细的自动扩展策略。保证流量动态变化的业务场景中实现资源的弹性伸缩,实现资源的最优合理性利用。

相关推荐
Elastic 中国社区官方博客13 小时前
使用 Ollama 和 Kibana 在本地为 RAG 测试 DeepSeek R1
大数据·数据库·人工智能·elasticsearch·ai·云原生·全文检索
Linux运维老纪1 天前
windows部署deepseek之方法(The Method of Deploying DeepSeek on Windows)
linux·人工智能·分布式·云原生·运维开发·devops
Elastic 中国社区官方博客1 天前
Elastic Cloud Serverless 获得主要合规认证
大数据·数据库·elasticsearch·搜索引擎·云原生·serverless·全文检索
超级阿飞1 天前
在K8s中部署动态nfs存储provisioner
云原生·容器·kubernetes·nfs
赵渝强老师2 天前
【赵渝强老师】K8s中Pod探针的TCPSocketAction
云原生·容器·kubernetes
努力的小T2 天前
Linux二进制部署K8s集群的平滑升级教程
linux·运维·服务器·云原生·容器·kubernetes·云计算
2的n次方_2 天前
Eureka 服务注册和服务发现的使用
spring boot·spring cloud·云原生·eureka·服务发现
赵渝强老师3 天前
【赵渝强老师】K8s中Pod探针的ExecAction
云原生·容器·kubernetes
vibag3 天前
Kubernetes(一)
java·云原生·容器·kubernetes
阿猿收手吧!3 天前
【Docker】Docker入门了解
linux·运维·服务器·docker·云原生·容器·eureka