暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

K8s 降本增效之 VPA 上篇

k8s技术圈 2022-12-05
979
VPA全称VerticalPodAutoscaler,即Pod的横向扩缩,其根据容器资源使用率自动设置CPU和内存的requests及limit,从而允许在节点上进行适当的调度,以便为每个 Pod 提供适当的资源。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源不足的容量。


编辑|阎锡山

接受范围|中度

VPA使用户无需为pod中的容器设置资源请求。配置后,它将根据资源(cpu 与内存)使用情况自动设置 requests。在对 pod 的调度过程中,使得每个 pod 都可以使用适当的资源量从而分配到适合的节点上。它既可以缩小资源请求过多的 pod,也可以根据一段时间内的使用情况扩大资源请求不足的 pod。


使用场景


自动资源配置提升管理效率



提高集群资源利用率



社区现状


目前,Kubernetes并不支持pod的in-place-update,因此vpa的auto等同recreate,目前版本的in-place-update还在review当中,并有望在未来的版本中提供,当前版本兼容如下所示。


版本

K8s release

0.12

1.25+

0.11

1.22-1.24

0.10

1.22+

0.9

1.16+




架构简介

VPA主要由三个组件组成,分别为recommender、updater、admission-controller

1)recommender:引入VerticalPodAutoscaler对象, Pod 的标签选择器、资源策略(控制 VPA 如何计算资源)、更新策略(控制如何将更改应用于 Pod)和推荐的 Pod 资源组成,其根据metric-server获取到的容器指标并观测 OOM 事件,计算推荐指标,最终更新VerticalPodAutoscaler对象

2)updater:其是负责Pod更新的组件。如果 Pod 在 "Auto" 模式下使用 VPA,则 Updater 可以决定使用推荐器资源对其进行更新。这只是通过驱逐Pod以便使用新资源重新创建它来实现的。简单来说,其是根据pod的request中设置的指标和recommend计算的推荐指标,在一定条件下驱逐pod,

3)admission-controller:这是一个webhook组件,所有 Pod 创建请求都通过 VPA Admission Controller如果Pod与VerticalPodAutoscaler 对象匹配,把recommend计算出的指标应用到pod的request和limit,如果 Recommender 不可用,它会回退到 VPA 对象中缓存的推荐。




相关资源

涉及到的自定义资源主要有两个:VerticalPodAutoscaler 、VerticalPodAutoscalerCheckpoint

VerticalPodAutoscaler


该资源由用户创建,用于设置纵向扩容的目标对象和存储recommend组件计算出的推荐指标。

VerticalPodAutoscalerCheckpoint


该资源由recommend组件创建和维护,用于存储指标相关信息。一个vpa对应的多个容器,每个容器创建一个该资源。





VPA实践

VPA部署


a.获取metrics-server manifest

    wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.2/components.yaml

    b.执行部署

      kubectl apply -f components.yaml


      c.验证结果

        [root@master ~]# kubectl  get po -n kube-system
        NAME READY STATUS RESTARTS AGE
        metrics-server-3358ad021s-wqmc9            1/1     Running   0          5m


        [root@master ~]# kubectl top nodes
        NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
        master         528m         5%       4385Mi           13%



        d.获取vpa项目
          git clone https://github.com/kubernetes/autoscaler.git

          e.部署vpa
            [root@master vertical-pod-autoscaler]#  cd autoscaler/vertical-pod-autoscaler
            [root@master vertical-pod-autoscaler]# ./hack/vpa-up.sh

            f.验证vpa
              [root@master ~]# kubectl  get po -n kube-system
              NAME READY STATUS RESTARTS AGE
              metrics-server-3358ad021s-wqmc9             1/1     Running   0          15m
              vpa-admission-controller-78e7f86645-67897   1/1     Running   0          3m
              vpa-recommender-tq4f7fb9db-32776            1/1     Running   0          3m
              vpa-updater-53er87q7qt-5p889                1/1     Running   0          3m



              测试 updateMode为off

              a.部署应用
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                labels:
                app: test
                  name: nginx
                spec:
                  replicas: 1
                selector:
                matchLabels:
                app: test
                template:
                metadata:
                labels:
                app: test
                spec:
                containers:
                - image: nginx
                name: nginx
                resources:
                requests:
                            cpu: 200m
                memory: 250Mi
                b.查看结果
                  [root@master examples]# kubectl  get po
                  NAME READY STATUS RESTARTS AGE
                  pod/nginx-5334b745w3-qwew3   1/1     Running   0          1m
                  c.创建服务
                    [root@master ~]# cat  nginx-test-svc.yaml
                    apiVersion: v1
                    kind: Service
                    metadata:
                      name: nginx
                    spec:
                    type: NodePort
                    ports:
                    - port: 80
                    targetPort: 80
                    selector:
                    app: test


                    [root@master examples]# kubectl  get svc
                    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
                    nginx   NodePort   10.99.106.213   <none>        80:31496/TCP   55s


                    [root@k8s-node001 examples]# curl -I 10.99.106.213:31496
                    HTTP/1.1 200 OK
                    d. 创建vpa

                    使用updateMode: "Off"模式,其仅计算资源的推荐而不应用Pod



                      [root@master ~]# cat   nginx-vpa-test.yaml
                      apiVersion: autoscaling.k8s.io/v1beta2
                      kind: VerticalPodAutoscaler
                      metadata:
                        name: nginx-vpa-test
                      spec:
                      targetRef:
                      apiVersion: "apps/v1"
                      kind: Deployment
                      name: nginx
                      updatePolicy:
                      updateMode: "Off"
                      resourcePolicy:
                      containerPolicies:
                      - containerName: "nginx"
                      minAllowed:
                      cpu: "250m"
                      memory: "100Mi"
                      maxAllowed:
                      cpu: "2000m"
                      memory: "2048Mi"
                            controlledResources: ["cpu", "memory"]


                      e.查看结果
                        [root@master ~]# kubectl  describe  vpa nginx-vpa-test
                        Name:         nginx-vpa-test
                        ...
                        Update Policy:
                        Update Mode: Off
                        Status:
                        Conditions:
                            Last Transition Time:  2022-11-28T03:21:14Z
                        Status: True
                        Type: RecommendationProvided
                        Recommendation:
                        Container Recommendations:
                        Container Name: nginx
                        Lower Bound:
                        Cpu: 250m
                                Memory:  262027k
                        Target:
                        Cpu: 250m
                        Memory: 262027k
                        Uncapped Target:
                                Cpu:     50m
                        Memory: 262027k
                        Upper Bound:
                                Cpu:     717m
                                Memory:  650210341
                        Events:          <none>

                        观察到推荐有四部分组成,其中lower为下限值,target为推荐值,而upper为上限值,其中uncap为实际值,250m为vpa单独配置的兜底。

                        f.压测
                        可以通过两种方式进行压测:内部及外部
                          for i in $(seq $(getconf _NPROCESSORS_ONLN)); do yes > /dev/null & done
                          或者通过ab进行外部压测
                            [root@master ~]# ab -c 200 -n 10000000 http://10.99.106.213:31496/
                            ...
                            Benchmarking 10.99.106.213 (be patient)
                            Completed 1000000 requests
                            Completed 2000000 requests
                            Completed 3000000 requests

                            g.观测结果
                              [root@master ~]# kubectl  describe  vpa nginx-vpa |tail -n 20 
                              Conditions:
                                  Last Transition Time:  2022-11-28T04:14:21Z
                              Status: True
                              Type: RecommendationProvided
                              Recommendation:
                              Container Recommendations:
                              Container Name: nginx
                              Lower Bound:
                              Cpu: 250m
                              Memory: 262027k
                              Target:
                                      Cpu:     673m
                              Memory: 262027k
                              Uncapped Target:
                                      Cpu:     673m
                              Memory: 262027k
                              Upper Bound:
                              Cpu: 2
                              Memory: 650210341
                              Events: <none>
                              从上述信息可以得知,VPA对Pod给出了推荐值:Cpu:673m,因为设置updateMode:"Off",所以不会应用Pod。




                              小结

                              局限性


                              1.不要将VPA与HPA一起使用,后者基于相同的资源指标(例如CPU和MEMORY使用率)进行缩放。这是因为当指标(CPU/MEMORY)达到其定义的阈值时,VPA和HPA将同时发生缩放事件,这可能会产生未知的副作用并可能导致问题,该处可以进行优化

                              2. VPA 可能会推荐比集群中可用的资源更多的资源,从而导致 pod 未分配给节点(由于资源不足),因此永远不会运行。为了克服这个限制,最好将LimitRange 设置为最大可用资源。这将确保 pod 不会要求超过 LimitRange 定义的资源,这里会导致资源碎片或节点热点

                              3.VPA不会驱逐不在控制器下运行的pod,驱逐可以单独处理



                              优化方向


                              1.对于非原生workload的优化,针对非原生工作负载,VPA使用scale方式获取,效率较低

                              2.VPA跟其他controller一样,使用selector模式,可以进行适当优化

                              3.VPA的历史数据加载只在启动时才会进行,且效率跟性能较低

                              4.多种推荐算法的支持

                              5.VPA对象更新瓶颈等


                              由于笔者时间、视野、认知有限,本文难免出现错误、疏漏等问题,期待各位读者朋友、业界专家指正交流。


                              参考文献

                                  1.https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler

                              2. https://github.com/containerd/containerd/pull/6965


                              真诚推荐你关注

                               点击上方卡片关注K8s技术圈,掌握前沿云原生技术



                              文章转载自k8s技术圈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                              评论