乐趣区

关于云计算:Kubernetes-的自动伸缩你用对了吗

本文翻译自 learnk8s 的 Architecting Kubernetes clusters — choosing the best autoscaling strategy,<u> 有增删局部内容 </u>。

TL;DR: 在默认设置下,扩大 Kubernetes 集群中的 pod 和节点可能须要几分钟工夫。理解如何调整集群节点的大小、配置程度和集群主动缩放器以及适度配置集群以放慢扩大速度。

主动扩展器

在 Kubernetes 中,常说的“自用扩大”有:

  • HPA:Pod 程度缩放器
  • VPA:Pod 垂直缩放器
  • CA:集群主动缩放器

不同类型的主动缩放器,应用的场景不一样。

HPA

HPA 定期检查内存和 CPU 等指标,主动调整 Deployment 中的正本数,比方流量变动:

VPA

有些时候无奈通过减少 Pod 数来扩容,比方数据库。这时候能够通过 VPA 减少 Pod 的大小,比方调整 Pod 的 CPU 和内存:

CA

当集群资源有余时,CA 会主动配置新的计算资源并增加到集群中:

主动缩放 Pod 出错时

比方一个利用须要 1.5 GB 内存和 0.25 个 vCPU。一个 8GB 和 2 个 vCPU 的节点,能够包容 4 个这样的 Pod,完满!

做如下配置:

  1. HPA:每减少 10 个并发,减少一个正本。即 40 个并发的时候,主动扩大到 4 个正本。(这里应用自定义指标,比方来自 Ingress Controller 的 QPS)
  2. CA:在资源有余的时候,减少计算节点。

当并发达到 30 的时候,零碎是上面这样。完满!HPA 工作失常,CA 没工作。

当减少到 40 个并发的时候,零碎是上面的状况:

  1. HPA 减少了一个 Pod
  2. Pod 挂起
  3. CA 减少了一个节点

为什么 Pod 没有部署胜利?

节点上的操作系统过程和 kubelet 也会耗费一部分资源,8G 和 2 vCPU 并不是全都能够提供给 Pod 用的。并且还有一个驱赶阈值:在节点零碎残余资源达到阈值时,会驱赶 Pod,防止 OOM 的产生。

当然下面的这些都是可配置的。

那为什么在创立该 Pod 之前,CA 没有减少新的节点呢?

CA 如何工作?

CA 在触发主动缩放时,不会查看可用的内存或 CPU。

CA 是面向事件工作的,并每 10 秒查看一次是否存在不可调度(Pending)的 Pod。

当调度器无奈找到能够包容 Pod 的节点时,这个 Pod 是不可调度的。

此时,CA 开始创立新节点:CA 扫描集群并查看是否有不可调度的 Pod。

当集群有多种节点池,CA 会通过抉择上面的一种策略:

  • random:默认的扩展器,随机抉择一种节点池
  • most-pods:可能调度最多 Pod 的节点池
  • least-waste:抉择扩大后,资源闲暇起码的节点池
  • price:抉择老本最低的节点池
  • priority:抉择用户调配的具备最高优先级的节点池

确定类型后,CA 会调用相干 API 来创立资源。(云厂商会实现 API,比方 AWS 增加 EC2;Azure 增加 Virtual Machine;阿里云减少 ECS;GCP 减少 Compute Engine)

计算资源就绪后,就会进行节点的初始化。

留神,这里须要肯定的耗时,通常比较慢。

摸索 Pod 主动缩放的前置工夫

四个因素:

  1. HPA 的响应耗时
  2. CA 的响应耗时
  3. 节点的初始化耗时
  4. Pod 的创立工夫

默认状况下,kubelet 每 10 秒抓取一次 Pod 的 CPU 和内存占用状况。

每分钟,Metrics Server 会将聚合的指标凋谢给 Kubernetes API 的其余组件应用。

CA 每 10 秒排查不可调度的 Pod。

  • 少于 100 个节点,且每个节点最多 30 个 Pod,工夫不超过 30s。均匀提早大概 5s。
  • 100 到 1000 个节点,不超过 60s。均匀提早大概 15s。

节点的配置工夫,取决于云服务商。通常在 3~5 分钟。

容器运行时创立 Pod:启动容器的几毫秒和 下载镜像的几秒钟。如果不做镜像缓存,几秒到 1 分钟不等,取决于层的大小和梳理。

对于小规模的集群,最坏的状况是 6 分 30 秒。对于 100 个以上节点规模的集群,可能高达 7 分钟。

HPA delay:          1m30s +
CA delay:           0m30s +
Cloud provider:     4m    +
Container runtime:  0m30s +
=========================
Total               6m30s

突发状况,比方流量激增,你是否违心等这 7 分钟?

这 7 分钟,如何优化压缩?

  • HPA 的刷新工夫,默认 15 秒,通过 --horizontal-pod-autoscaler-sync-period 标记管制。
  • Metrics Server 的指标抓取工夫,默认 60 秒,通过 metric-resolution 管制。
  • CA 的扫描距离,默认 10 秒,通过 scan-interval 管制。
  • 节点上缓存镜像,比方 kube-fledged 等工具。

即便调小了上述设置,仍然会受云服务商的工夫限度。

那么,如何解决?

两种尝试:

  1. 尽量避免被动创立新节点
  2. 被动创立新节点

为 Kubernetes 抉择最佳规格的节点

这会对扩大策略产生微小影响。

这样的场景

应用程序须要 1GB 内存和 0.1 vCPU;有一个 4GB 内存和 1 个 vCPU 的节点。

排除操作系统、kubelet 和阈值保留空间后,有 2.5GB 内存和 0.7 个 vCPU 可用。

最多只能包容 2 个 Pod,扩大正本时最长耗时 7 分钟(HPA、CA、云服务商的资源配置耗时)

如果节点的规格是 64GB 内存和 16 个 vCPU,可用的资源为 58.32GB 和 15.8 个 vCPU。

这个节点能够托管 58 个 Pod。只有扩容第 59 个正本时,才须要创立新的节点。

这样触发 CA 的机会更少。

抉择大规格的节点,还有另外一个益处:资源的利用率会更高。

节点上能够包容的 Pod 数量,决定了效率的峰值。

物极必反!更大的实例,并不是一个好的抉择:

  1. 爆炸半径(Blast radius):节点故障时,少节点的集群和多节点的集群,前者影响更大。
  2. 主动缩放的老本效益低:减少一个大容量的节点,其利用率会比拟低(调度过来的 Pod 数少)

即便抉择了正确规格的节点,配置新的计算单元时,提早依然存在。怎么解决?

是否提前创立节点?

为集群适度配置节点

即为集群减少备用节点,能够:

  1. 创立一个节点,并留空(比方 SchedulingDisabled)
  2. 一旦空节点中有了一个 Pod,马上创立新的空节点

这种会产生额定的老本,然而效率会晋升。

CA 并不反对此性能 — 总是保留一个空节点。

然而,能够伪造。创立一个只占用资源,不应用资源的 Pod 占用整个 Node 节点。

一旦有了真正的 Pod,驱赶占位的 Pod。

待后盾实现新的节点配置后,将“占位”Pod 再次占用整个节点。

这个“占位”的 Pod 能够通过永恒休眠来实现空间的保留。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: overprovisioning
spec:
  replicas: 1
  selector:
    matchLabels:
      run: overprovisioning
  template:
    metadata:
      labels:
        run: overprovisioning
    spec:
      containers:
        - name: pause
          image: k8s.gcr.io/pause
          resources:
            requests:
              cpu: '1739m'
              memory: '5.9G'

应用优先级和抢占,来实现创立真正的 Pod 后驱赶“占位”的 Pod。

应用 PodPriorityClass 在配置 Pod 优先级:

apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
  name: overprovisioning
value: -1 #默认的是 0,这个示意比默认的低
globalDefault: false
description: 'Priority class used by overprovisioning.'

为“占位”Pod 配置优先级:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: overprovisioning
spec:
  replicas: 1
  selector:
    matchLabels:
      run: overprovisioning
  template:
    metadata:
      labels:
        run: overprovisioning
    spec:
      priorityClassName: overprovisioning #HERE
      containers:
        - name: reserve-resources
          image: k8s.gcr.io/pause
          resources:
            requests:
              cpu: '1739m'
              memory: '5.9G'

曾经做完适度配置,应用程序是否须要优化?

为 Pod 抉择正确的内存和 CPU 申请

Kubernetes 是依据 Pod 的内存和 CPU 申请,为其调配节点。

如果 Pod 的资源申请配置不正确,可能会过晚(或过早)触发主动缩放器。

这样一个场景:

  • 应用程序均匀负载下耗费 512MB 内存和 0.25 个 vCPU。
  • 顶峰时,耗费 4GB 内存 和 1 个 vCPU。(即资源限度,Limit)

有三种申请的配置抉择:

  1. 远低于均匀使用量
  2. 匹配均匀使用量
  3. 尽量靠近限度

第一种的问题在于 超卖重大,适度应用节点。kubelet 负载高,稳定性差。

第三种,会造成资源的利用率低,浪费资源。这种通常被称为 QoS:Quality of Service class 中的 Guaranteed 级别,Pod 不会被终止和驱赶。

如何在稳定性和资源使用率间做衡量?

这就是 QoS:Quality of Service class 中的 Burstable 级别,即 Pod 偶然会应用更多的内存和 CPU。

  1. 如果节点中有可用资源,应用程序会在返回基线(baseline)前应用这些资源。
  2. 如果资源有余,Pod 将竞争资源(CPU),kubelet 也有可能尝试驱赶 Pod(内存)。

GuaranteedBurstable 之前如何做抉择?取决于:

  1. 想尽量减少 Pod 的从新调度和驱赶,应该是用 Guaranteed
  2. 如果想充分利用资源时,应用 Burstable。比方弹性较大的服务,Web 或者 REST 服务。

如何做出正确的配置?

应该剖析应用程序,并测算闲暇、负载和峰值时的内存和 CPU 耗费。

甚至能够通过部署 VPA 来主动调整。

如何进行集群缩容?

每 10 秒,当申请(request)利用率低于 50% 时,CA 才会决定删除节点。

CA 会汇总同一个节点上的所有 Pod 的 CPU 和内存申请。小于节点容量的一半,就会思考对以后节点进行缩减。

须要留神的是,CA 不思考理论的 CPU 和内存应用或者限度(limit),只看申请(request)。

移除节点之前,CA 会:

  1. 查看 Pod 确保能够调度到其余节点上。
  2. 查看节点,防止节点被过早的销毁,比方两个节点的申请都低于 50%。

查看都通过之后,才会删除节点。

为什么不依据内存或 CPU 进行主动缩放?

基于内存和 CPU 的主动缩放器,不关怀 pod。

比方配置缩放器在节点的 CPU 达到总量的 80%,就主动减少节点。

当你创立 3 个正本的 Deployment,3 个节点的 CPU 达到了 85%。这时会创立一个节点,但你并不需要第 4 个正本,新的节点就闲暇了。

不倡议应用这种类型的主动缩放器。

总结

定义和施行胜利的扩大策略,须要把握以下几点:

  • 节点的可分配资源。
  • 微调 Metrics Server、HPA 和 CA 的刷新距离。
  • 设计集群和节点的规格。
  • 缓存容器镜像到节点。
  • 应用程序的基准测试和剖析。

配合适当的监控工具,能够重复测试扩大策略并调整集群的缩放速度和老本。

文章对立公布在公众号 云原生指北

退出移动版