【问题标题】:How to reduce CPU limits of kubernetes system resources?如何降低 Kubernetes 系统资源的 CPU 限制?
【发布时间】:2023-03-24 22:11:01
【问题描述】:

我希望将 GKE 集群中的核心数保持在 3 以下。如果 K8s 复制控制器和 pod 的 CPU 限制从 100m 减少到最多 50m,这将变得更加可行。否则,仅 K8s pod 就占用了一个内核的 70%。

我决定不增加节点的 CPU 能力。在我看来,这在概念上是错误的,因为 CPU 限制被定义为以内核为单位来衡量。相反,我做了以下事情:

  • 将 limitranges/limits 替换为默认 CPU 限制为“50m”的版本(不是必需的,但我认为更简洁)
  • 修补 kube-system 命名空间中的所有复制控制器以将 50m 用于所有容器
  • 删除他们的 pod
  • 将 kube-system 命名空间中的所有非 rc pod 替换为所有容器使用 50m 的版本

这是一项繁重的工作,而且可能很脆弱。即将发布的 K8s 版本的任何进一步更改,或 GKE 配置的更改,都可能会破坏它。

那么,有没有更好的办法呢?

【问题讨论】:

    标签: kubernetes limits google-kubernetes-engine


    【解决方案1】:

    更改默认命名空间的 LimitRange spec.limits.defaultRequest.cpu 应该是更改新 Pod 的默认值的合法解决方案。请注意,LimitRange 对象是命名空间的,因此如果您使用额外的命名空间,您可能需要考虑它们的合理默认值是什么。

    正如您所指出的,这不会影响 kube-system 命名空间中的现有对象或对象。

    kube-system 命名空间中的对象大多是根据经验确定大小的——基于观察到的值。更改这些可能会产生不利影响,但如果您的集群非常小,则可能不会。

    我们有一个未解决的问题 (https://github.com/kubernetes/kubernetes/issues/13048) 可以根据集群总大小调整 kube-system 请求,但这还没有实现。我们还有另一个未解决的问题 (https://github.com/kubernetes/kubernetes/issues/13695) 可能对某些 kube 系统资源使用较低的 QoS,但同样 - 尚未实现。

    其中,我认为#13048 是实现您所要求的正确方法。目前,“有没有更好的方法”的答案很遗憾是“没有”。我们为中型集群选择了默认值 - 对于非常小的集群,您可能需要执行您正在执行的操作。

    【讨论】:

      【解决方案2】:

      我发现在 GKE 集群上减少系统资源请求的最佳方法之一是使用 vertical autoscaler

      以下是我使用的 VPA 定义:

      apiVersion: autoscaling.k8s.io/v1beta2
      kind: VerticalPodAutoscaler
      metadata:
        namespace: kube-system
        name: kube-dns-vpa
      spec:
        targetRef:
          apiVersion: "extensions/v1beta1"
          kind: Deployment
          name: kube-dns
        updatePolicy:
          updateMode: "Auto"
      
      ---
      
      apiVersion: autoscaling.k8s.io/v1beta2
      kind: VerticalPodAutoscaler
      metadata:
        namespace: kube-system
        name: heapster-vpa
      spec:
        targetRef:
          apiVersion: "extensions/v1beta1"
          kind: Deployment
          name: heapster-v1.6.0-beta.1
        updatePolicy:
          updateMode: "Initial"
      
      ---
      
      apiVersion: autoscaling.k8s.io/v1beta2
      kind: VerticalPodAutoscaler
      metadata:
        namespace: kube-system
        name: metadata-agent-vpa
      spec:
        targetRef:
          apiVersion: "extensions/v1beta1"
          kind: DaemonSet
          name: metadata-agent
        updatePolicy:
          updateMode: "Initial"
      
      ---
      
      apiVersion: autoscaling.k8s.io/v1beta2
      kind: VerticalPodAutoscaler
      metadata:
        namespace: kube-system
        name: metrics-server-vpa
      spec:
        targetRef:
          apiVersion: "extensions/v1beta1"
          kind: Deployment
          name: metrics-server-v0.3.1
        updatePolicy:
          updateMode: "Initial"
      
      ---
      
      apiVersion: autoscaling.k8s.io/v1beta2
      kind: VerticalPodAutoscaler
      metadata:
        namespace: kube-system
        name: fluentd-vpa
      spec:
        targetRef:
          apiVersion: "extensions/v1beta1"
          kind: DaemonSet
          name: fluentd-gcp-v3.1.1
        updatePolicy:
          updateMode: "Initial"
      
      ---
      
      apiVersion: autoscaling.k8s.io/v1beta2
      kind: VerticalPodAutoscaler
      metadata:
        namespace: kube-system
        name: kube-proxy-vpa
      spec:
        targetRef:
          apiVersion: "extensions/v1beta1"
          kind: DaemonSet
          name: kube-proxy
        updatePolicy:
          updateMode: "Initial"
      

      Here is a screenshot of what it does to a kube-dns deployment.

      【讨论】:

      • 我们的 kube-dns 最终保留了不到 20% 的 CPU,谢谢!但是(当然)似乎有很高的默认 RAM 请求。现在所有内容都请求 262 MiB,这使得这对所有内容都不太有用。
      • 我在我们的集群上使用了一个修改版本:github.com/ARISEChurch/autoscaler/tree/arise-tweaks 它似乎对我们的工作负载运行得更好,但您的用例可能会有所不同。
      • 非常感谢您的配置@TimSmart,您能否详细说明使用“自动”和有时使用“初始”的原因?此外,您是否在系统资源上使用 VPA 时遇到过任何问题,或者您是否更新了配置?谢谢!
      • @fiws vpa-recommender 默认将cmd flag --pod-recommendation-min-memory-mb 设置为250。我已将以下内容添加到 deploy/recommender-deployment.yamlrecommender 容器中:args: ["--pod-recommendation-min-cpu-millicores=5", "--pod-recommendation-min-memory-mb=40", "--v=4", "--stderrthreshold=info", "--prometheus-address=http://prometheus.monitoring.svc"]
      【解决方案3】:

      正如@Tim Hockin 所述,附加组件的默认配置适用于典型集群。但可以通过更改资源限制规范进行微调。

      在调整插件大小之前,请记住您还可以禁用不必要的插件以供您使用。这可能会有所不同,具体取决于附加组件、其版本、kubernetes 版本以及提供者。 Google has a page covering some options,同样的概念也可以在其他提供者中使用

      @Tim Hockin 回答中的the solution to the issue linked第一个被接受的方法是使用addon-resizer。它基本上找出最佳限制和要求,修补 Deployment/Pod/DaemonSet 并重新创建相关联的 pod 以匹配新限制,但比手动完成所有这些工作更省力。

      但是,另一种更强大的实现方式是使用 Vertical Pod Autoscaler,如 @Tim Smart 回答所述。 VPA 完成了 addon-resizer 的功能,但它有很多好处:

      • VPA 是插件本身的自定义资源定义,使您的代码比使用插件调整器更紧凑。
      • 作为自定义资源定义,使实现保持最新也更容易。
      • 一些提供商 (as google) 在 control-plane 进程上运行 VPA 资源,而不是在您的工作节点上部署。做到这一点,即使addon-resizer is simplier,VPA 也不会使用您的任何资源,而 addon-resizer 会。

      更新的模板是:

      apiVersion: autoscaling.k8s.io/v1
      kind: VerticalPodAutoscaler
      metadata:
        name: <addon-name>-vpa
        namespace: kube-system
      spec:
        targetRef:
          apiVersion: "apps/v1"
          kind:       <addon-kind (Deployment/DaemonSet/Pod)>
          name:       <addon-name>
        updatePolicy:
          updateMode: "Auto"
      

      检查当前集群中使用的插件很重要,因为它们可能因提供商(AWS、Google 等)及其 kubernetes 实施版本而有很大差异

      确保您的集群中安装了 VPA 插件(大多数 kubernetes 服务都将其作为一个简单的检查选项)

      Update policy 可以是 Initial(仅在创建新 pod 时应用新限制),重新创建(强制不符合规范的 pod 死亡并应用于新 pod) 、关闭(创建推荐但不应用)或自动(当前匹配 Recreate,can change in the future

      @Tim Smart 答案示例的唯一区别是当前 api 版本是 autoscaling.k8s.io/v1,目标的当前 api 版本是 apps/v1,并且某些提供程序的较新版本使用 FluentBit 代替 Fluentd。他的回答可能更适合早期的 kubernetes 版本

      例如,如果您使用的是 Google Kubernetes Engine,目前一些“最重”的需求插件是:

      • fluentbit-gke (DaemonSet)
      • gke-metadata-server (DaemonSet)
      • kube-proxy (DaemonSet)
      • kube-dns(部署)
      • stackdriver-metadata-agent-cluster-level(部署)

      通过在其上应用 VPA,我的插件资源需求从 1.6 降至 0.4。

      【讨论】:

      • 看起来不错,但仍然无法获取 kube-system pod 以减少对 GKE 的请求。对分析我的问题有什么建议吗?
      • (1) kube-dns & fluentbit-gke:看起来我需要强行杀死这些 pod (2) kube-proxy:vpa 无法选择 pod,因为 kube-proxy 似乎“直接”在节点上运行,而不是在 DaemonSet 内
      【解决方案4】:

      顺便说一下,以防万一您想在 Google Cloud GCE 上尝试一下。如果您尝试更改 kube-dns 等核心服务的 CPU 限制,您将收到类似这样的错误。

      规范:禁止:Pod 更新不得更改除 spec.containers[*].imagespec.initContainers[*].imagespec.activeDeadlineSecondsspec.tolerations 以外的字段(仅对现有容忍度的补充

      在 Kubernetes 1.8.7 和 1.9.4 上试过。

      所以此时你需要部署的最小节点是n1-standard-1。此外,只要你有几个 pod 和 helm,Kubernetes 本身就会几乎不断地吃掉大约 8% 的 cpu。即使您没有运行任何主要负载。我认为有很多轮询正在进行,为了确保集群响应,他们不断刷新一些统计数据。

      【讨论】:

      • 所以我基本上至少需要一个 n1-standard-1 来管理我的 kubernetes?
      • 基本上是的。 :-( 至少在谷歌上你不需要为主节点付费。在 AWS 上你必须自己为主节点付费。
      • 我认为在 google 上你也需要为 master 付费——至少如果你使用的是 google kubernetes 引擎
      • 不,你没有。您只需为您的工作节点付费。他们前段时间释放了主节点。
      • 你是对的——谢谢。在他们的定价页面上没有正确传达,但我发现了这篇博文:cloudplatform.googleblog.com/2017/11/… 无论如何,每个节点仍然限制为 110 个 pod,即使您有大型节点,显然也无法增加。所以它仍然对我不起作用:(
      【解决方案5】:

      我确实尝试直接在 google 控制台中进行此更改,但我的更改甚至没有为我自己的应用程序 pod 保存。

      我收到此错误。 禁止:pod 更新可能不会更改除spec.containers[*].image、`spec.i.. 之外的字段。

      我在研究时确实发现了这篇关于这个主题的优秀文章, https://medium.com/@betz.mark/understanding-resource-limits-in-kubernetes-cpu-time-9eff74d3161b

      【讨论】:

      • 您好,欢迎来到 SO!您的答案看起来不完整 - 第二段是否缺少某些内容?
      猜你喜欢
      • 2017-07-08
      • 1970-01-01
      • 2011-04-12
      • 2022-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      相关资源
      最近更新 更多