一文带你掌握Kubernetes VPA(Pod纵向自动扩缩)

2023-09-11 11:25:02 浏览数 (1)

简介

之前的文章我们介绍了HPA(Horizontal Pod Autoscaler)的实现,HPA一般被称为横向扩展,与HPA不同的Vertical Pod Autoscaler ( VPA ) 会自动调整 Pod 的 CPU 和内存属性,被称为纵向扩展。VPA可以给出服务运行所适合的CPU和内存配置,省去估计服务占用资源的时间,更合理的使用资源。当然,VPA也可根据资源的使用情况“调整”pod的资源。这里的调整我们用了双引号,因为他的实现机制是重建而不是动态增加。下面是一个实际的例子:假设我的memory limits是100Mi,但是现在已经用到了98Mi,如果再大的话就oom了,此时vpa会在垂直方向上提升你的memory limits的大小。这种vpa比较适合一些资源消耗比较大的应用,例如es,你给大了资源浪费,给小了,又不够。所以vpa就派上用场了。当然,vpa不像hpa默认集成在k8s里面的,需要你自己去配置的。

VPA 与 HPA

从根本上来说,VPA 和 HPA 之间的区别在于它们的扩展方式。HPA 通过添加或删除pod进行扩展,从而水平扩展容量。然而,VPA 通过增加或减少现有 Pod 容器内的 CPU 和内存资源来进行扩展,从而垂直扩展容量。下表更详细地解释了 Kubernetes VPA 和 HPA 之间的差异。

需要调整容量

水平缩放 (HPA)

垂直缩放 (VPA)

更多资源

添加更多 Pod

增加现有 pod 容器的 CPU 或内存资源

资源较少

删除 Pod

减少现有 Pod 容器的 CPU 或内存资源

工作原理

VPA 的组成部分

VPA 部署具有三个主要组件:VPA Recommender、VPA Updater和VPA Admission Controller。让我们看一下每个组件的作用。VPA Recommender:

  • 监控资源利用率并计算目标值。
  • 查看指标历史记录、OOM 事件和 VPA 部署规范并建议公平请求。根据定义的限制请求比例提高/降低限制。

VPA 更新程序:

  • 驱逐那些需要新资源限制的 Pod。
  • 如果定义了“updateMode: Auto”,则实现推荐器建议的任何内容。

VPA 准入控制器:

  • 每当 VPA 更新程序逐出并重新启动 Pod 时,都会在新 Pod 启动之前更改 CPU 和内存设置(使用 Webhook)。
  • 当 Vertical Pod Autoscaler 设置为“Auto”的 updateMode 时,如果需要更改 Pod 的资源请求,则驱逐 Pod。由于 Kubernetes 的设计,修改正在运行的 pod 的资源请求的唯一方法是重新创建 pod。

Kubernetes VPA 工作模式

  1. 用户配置VPA。
  2. VPA Recommender 从指标服务器读取 VPA 配置和资源利用率指标。
  3. VPA Recommender 提供 Pod 资源推荐。
  4. VPA Updater 读取 Pod 资源建议。
  5. VPA Updater 启动 Pod 终止。
  6. 部署意识到 Pod 已终止,并将重新创建 Pod 以匹配其副本配置。
  7. 当 Pod 处于重新创建过程中时,VPA 准入控制器会获取 Pod 资源推荐。由于 Kubernetes 不支持动态更改正在运行的 pod 的资源限制,因此 VPA 无法使用新的限制更新现有 pod。它会终止使用过时限制的 pod。当 Pod 的控制器向 Kubernetes API 服务请求替换时,VPA 准入控制器会将更新的资源请求和限制值注入到新 Pod 的规范中。
  8. 最后,VPA 准入控制器会覆盖对 Pod 的建议。在我们的示例中,VPA 准入控制器向 Pod 添加了一个“250m”CPU。

最佳实践

既然你知道了大致原理,让我们开始动手操作你吧

代码语言:javascript复制
克隆代码
# git clone https://github.com/kubernetes/autoscaler.git

由于某些原因拉不到镜像,改yaml修改优先使用本地镜像
# cd autoscaler/vertical-pod-autoscaler/deploy
# sed -i 's/Always/IfNotPresent/g'  recommender-deployment.yaml
# sed -i 's/Always/IfNotPresent/g'  admission-controller-deployment.yaml
# sed -i 's/Always/IfNotPresent/g'  updater-deployment.yaml

# 拉取镜像
# docker pull giantswarm/vpa-admission-controller:0.14.0
# docker pull giantswarm/vpa-recommender:0.14.0
# docker pull giantswarm/vpa-updater:0.14.0


# 修改tag
# docker tag giantswarm/vpa-updater:0.14.0 registry.k8s.io/autoscaling/vpa-updater:0.14.0
# docker tag giantswarm/vpa-recommender:0.14.0 registry.k8s.io/autoscaling/vpa-recommender:0.14.0
# docker tag giantswarm/vpa-admission-controller:0.14.0 registry.k8s.io/autoscaling/vpa-admission-controller:0.14.0

# cd autoscaler/vertical-pod-autoscaler/hack

# 安装脚本安装之前保证你的K8S集群的metrics-server已安装,并且openssl升级到1.1.1或更高版本
# ./vpa-up.sh

等待安装完成

代码语言:javascript复制
# kubectl get pods -n kube-system | grep vpa
kube-system     vpa-admission-controller-75bffbf8d8-6hxqq          1/1     Running     0               5m9s
kube-system     vpa-recommender-748c55b5bf-kqqjc                   1/1     Running     0               4m34s
kube-system     vpa-updater-679d5dcdd6-lslc7                       1/1     Running     0               4m15s

使用VPA,您需要为要自动计算资源需求的每个控制器插入一个Vertical Pod Autoscaler资源。这将是最常见的Deployment。VPA有四种运行模式

  • "Auto":VPA 在创建 pod 时分配资源请求,并使用首选更新机制在现有 pod 上更新它们。目前这相当于"Recreate"(见下文)。一旦 pod 请求的免重启(“就地”)更新可用,它可能会被该"Auto"模式用作首选的更新机制。注意:VPA 的此功能是实验性的,可能会导致您的应用程序停机,当目前运行的pod的资源达不到VPA的推荐值,就会执行pod驱逐,重新部署新的足够资源的服务
  • "Recreate":VPA 在创建 Pod 时分配资源请求,并在现有 Pod 上更新它们,当请求的资源与新建议有很大差异时(尊重 Pod 中断预算,如果定义)。这种模式应该很少使用,只有当您需要确保在资源请求发生变化时重新启动 Pod 时。否则,更喜欢这种"Auto"模式,一旦它们可用,就可以利用重新启动免费更新。注意:VPA 的此功能是实验性的,可能会导致您的应用程序停机
  • "Initial":VPA 仅在创建 pod 时分配资源请求,以后不会更改它们
  • "Off":VPA 不会自动更改 Pod 的资源需求。这些建议是经过计算的,并且可以在 VPA 对象中进行检查。这种模式仅获取资源推荐值,但是不更新Pod

创建一个updateMode: Auto 的VPA

代码语言:javascript复制
# 将updateMode中的requests 改为 CPU:50m,Memory: 50Mi,同时将updateMode修改为Auto

# 创建一个pod和svc
# kubectl get pods -n vpa
NAME                     READY   STATUS    RESTARTS   AGE
nginx-8454bb78d8-67pth   1/1     Running   0          9s
nginx-8454bb78d8-6efsh   1/1     Running   0          9s
# kubectl get svc -n vpa
NAME    TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.0.200.5   <none>        80:45425/TCP   15s

# 进行压测,压测到一半时,突然连接断了,说明POD被重新创建了
# ab -c 1000 -n 100000 http://192.168.0.191:45425/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.191 (be patient)
apr_socket_recv: Connection reset by peer (104)
Total of 187078 requests completed

# 查看vpa
# kubectl describe vpa nginx-vpa -n vpa | tail -n 20
  Conditions:
    Last Transition Time:  2023-09-07T15:41:32Z
    Status:                True
    Type:                  RecommendationProvided
  Recommendation:
    Container Recommendations:
      Container Name:  nginx
      Lower Bound:               #容器的最小估计值
        Cpu:     100m
        Memory:  262144k
      Target:                   #目标估计是我们用于设置资源请求的估计
        Cpu:     350m
        Memory:  262144k
      Uncapped Target:          #无上限目标估计是在没有minAllowed和maxAllowed限制的情况下产生的目标估计
        Cpu:     350m
        Memory:  262144k
      Upper Bound:              #上限是容器的最大建议资源估计
        Cpu:     2
        Memory:  405160855
Events:          <none>

# 查看pod被重新创建了 稍高的配置
# kubectl get pods -n vpa
NAME                     READY   STATUS    RESTARTS   AGE
nginx-daecsfv8d8-see8h   1/1     Running   0          4m
nginx-daecsfv8d8-fsise   1/1     Running   0          3m

已知的限制

  • 每当 VPA 更新 Pod 资源时,都会重新创建 Pod,这会导致重新创建所有正在运行的容器。Pod 可以在不同的节点上重新创建。
  • VPA 无法保证它驱逐或删除以应用建议(在Auto和Recreate模式下配置时)的 pod 将成功重新创建。通过将 VPA 与Cluster Autoscaler结合使用可以部分解决这个问题。
  • VPA 不会更新不在控制器下运行的 Pod 的资源。
  • 目前,Vertical Pod Autoscaler不应与CPU 或内存上的Horizontal Pod Autoscaler (HPA)一起使用。但是,您可以在自定义和外部指标上将 VPA 与 HPA结合使用。
  • VPA 准入控制器是一个准入 Webhook。如果您将其他准入 Webhook 添加到集群中,则分析它们如何交互以及它们是否可能相互冲突非常重要。准入控制器的顺序由 API 服务器上的标志定义。
  • VPA 会对大多数内存不足事件做出反应,但并非在所有情况下都会做出反应。
  • VPA 性能尚未在大型集群中进行测试。
  • VPA 建议可能会超出可用资源(例如节点大小、可用大小、可用配额)并导致Pod 处于挂起状态。通过将 VPA 与Cluster Autoscaler结合使用可以部分解决这个问题。
  • 与同一 Pod 匹配的多个 VPA 资源具有未定义的行为。

总结

在本文中,我们使用VPA实现了基于POD对配置进行横向扩展,合理的使用可以提高对K8S的利用率,实现降本增效。但是目前的VPA也存在一些问题,我个人觉得VPA最大的问题是会对服务进行重建,重建过程中可能会有流量损失,但是好消息是从1.27 版本动态调整容器CPU和内存资源限制,无需重启应用程序,在可见的将来,会实现动态扩容更加顺滑,让我们一起期待~

0 人点赞