本文永久链接: https://www.xtplayer.cn/kubernetes/k8s-automatic-elastic-expansion/

Kubernetes 自动弹性伸缩可以根据业务流量,自动增加或减少服务。这一功能在实际的业务场景中十分重要。在本文中,我们将了解 Kubernetes 如何针对应用产生的自定义指标实现自动伸缩。

为什么需要自定义指标?

应用程序的 CPU 或 RAM 的消耗并不一定能够正确表明是否需要进行扩展。例如,如果你有一个消息队列 consumer,它每秒可以处理 500 条消息而不会导致崩溃。一旦该 consumer 的单个实例每秒处理接近 500 条消息,你可能希望将应用程序扩展到两个实例,以便将负载分布在两个实例上。测量 CPU 或 RAM 对于扩展这样的应用程序来说有点矫枉过正了,你需要寻找一个与应用程序性质更为密切相关的指标。一个实例在特定时间点处理的消息数量能更贴切地反映该应用的实际负载。同样,可能有一些应用的其他指标更有意义。这些可以使用 Kubernetes 中的自定义指标进行定义。

Metrics 流水线

Metrics Server 和 API

最初,这些指标会通过 Heapster 暴露给用户,Heapster 可以从每个 kubelet 中查询指标。Kubelet 则与 localhost 上的 cAdvisor 对话,并检索出节点级和 pod 级的指标。Metric-server 的引入是为了取代 heapster,并使用 Kubernetes API 来暴露指标从而以 Kubernetes API 的方式提供指标。Metric server 仅提供核心的指标,比如 pod 和节点的内存和 CPU,对于其他指标,你需要构建完整的指标流水线。构建流水线和 Kubernetes 自动伸缩的机制将会保持不变。

Aggregation Layer

能够通过 Kubernetes API 层暴露指标的关键部分之一是 Aggregation Layer。该 aggregation layer 允许在集群中安装额外的 Kubernetes 格式的 API。这使得 API 像任何 Kubernetes 资源一样可用,但 API 的实际服务可以由外部服务完成,可能是一个部署到集群本身的 Pod(如果没有在集群级别完成,你需要启用 aggregation layer)。那么,这到底是如何发挥作用的呢?作为用户,用户需要提供 API Provider(比如运行 API 服务的 pod),然后使用 APIService 对象注册相同的 API。

让我们以核心指标流水线为例来说明 metrics server 如何使用 API Aggregation layer 注册自己。APIService 对象如下:

apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.metrics.k8s.io
spec:
service:
name: metrics-server
namespace: kube-system
group: metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100

部署使用 APIService 注册 API 的 metrics server 之后,我们可以看到 Kubernetes API 中提供了指标 API:

Metrics 流水线:核心部分和完整流水线

我们已经了解了基本组件,让我们把它们放在一起组成核心 metrics 流水线。在核心流水线中,如果你已经恰当地安装了 metrics server,它也将创建 APIService 将自己注册到 Kubernetes API server 上。正如我们在上一节中所了解到的那样,这些指标将在/apis/metrics.k8s.io 中暴露,并被 HPA 使用。

大部分复杂的应用程序需要更多的指标,而不仅仅是内存和 CPU,这也是大多数企业使用监控工具的原因,最常见的监控工具有 Prometheus、Datadog 以及 Sysdig 等。而不同的工具所使用的格式也有所区别。在我们可以使用 Kubernetes API 聚合来暴露 endpoint 之前,我们需要将指标转换为合适的格式。此时需要使用小型的 adapter(适配器)——它可能是监控工具的一部分,也可能作为一个单独的组件,它在监控工具和 Kubernetes API 之间架起了一座桥梁。例如,Prometheus 有专门的 Prometheus adapter 或者 Datadog 有 Datadog Cluster Agent — 它们位于监控工具和 API 之间,并从一种格式转换到另一个种格式,如下图所示。这些指标在稍微不同的 endpoint 都可以使用。

Demo:Kubernetes 自动伸缩

我们将演示如何使用自定义指标自动伸缩应用程序,并且借助 Prometheus 和 Prometheus adapter。你可以继续阅读文章,或者直接访问 Github repo 开始构建 demo:

https://github.com/infracloudio/kubernetes-autoscaling

设置 Prometheus

为了让适配器可以使用指标,我们将使用 Prometheus Operator 来安装 Prometheus。它创建 CRD 来在集群中部署 Prometheus 的组件。CRD 是扩展 Kubernetes 资源的一种方式。使用 Operator 可以“以 Kubernetes 的方式”(通过在 YAML 文件中定义对象)轻松配置和维护 Prometheus 实例。由 Prometheus Operator 创建的 CRD 有:

  • AlertManager
  • ServiceMonitor
  • Prometheus

你可以根据下方链接的指导设置 Prometheus:

https://github.com/infracloudio/kubernetes-autoscaling#installing-prometheus-operator-and-prometheus

部署 Demo 应用程序

为了生成指标,我们将部署一个简单的应用程序 mockmetrics,它将在/metrics 处生成 total_hit_count 值。这是一个用 Go 写的网络服务器。当 URL 被访问时,指标 total_hit_count 的值会不断增加。它使用 Prometheus 所要求的展示格式来显示指标。

根据以下链接来为这一应用程序创建 deployment 和服务,它同时也为应用程序创建 ServiceMonitor 和 HPA:

https://github.com/infracloudio/kubernetes-autoscaling#deploying-the-mockmetrics-application

ServiceMonitor

ServiceMonitor 为 Prometheus 创建了一个配置。它提到了服务的标签、路径、端口以及应该在什么时候抓取指标的时间间隔。在服务 label 的帮助下,选择了 pods。Prometheus 会从所有匹配的 Pod 中抓取指标。根据你的 Prometheus 配置,ServiceMonitor 应该放在相应的命名空间中。在本例中,它和 mockmetrics 在同一个命名空间。

部署和配置 Prometheus Adapter

现在要为 HPA 提供 custom.metrics.k8s.io API endpoint,我们将部署 Prometheus Adapter。Adapter 希望它的配置文件在 Pod 中可用。我们将创建一个 configMap 并将其挂载在 pod 内部。我们还将创建 Service 和 APIService 来创建 API。APIService 将/api/custom.metrics.k8s.io/v1beta1endpoint 添加到标准的 Kubernetes APIs。你可以根据以下教程来实现这一目标:

https://github.com/infracloudio/kubernetes-autoscaling#deploying-the-custom-metrics-api-server-prometheus-adapter

接下来,我们看一下配置:

  • seriesQuery 用于查询 Prometheus 的资源,标签为“default“和”mockmetrics-service“。
  • resources 部分提到标签如何被映射到 Kubernetes 资源。针对我们的情况,它将“namespace“标签与 Kubernetes 的”namespace“进行映射,服务也是如此。
  • metricsQuery 又是一个 Prometheus 查询,它可以将指标导入 adapter。我们使用的查询是获取 2 分钟内所有匹配 regexmockmetrics-deploy-(.*)的 pods 的平均 total_hit_count 总和。

Kubernetes 自动伸缩实践

一旦你根据下文中的步骤进行,指标值会不断增加。我们现在就来看 HPA:

https://github.com/infracloudio/kubernetes-autoscaling#scaling-the-application

kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
mockmetrics-app-hpa Deployment/mockmetrics-deploy 0/100 1 10 1 11h
mockmetrics-app-hpa Deployment/mockmetrics-deploy 56/100 1 10 1 11h
mockmetrics-app-hpa Deployment/mockmetrics-deploy 110/100 1 10 1 11h
mockmetrics-app-hpa Deployment/mockmetrics-deploy 90/100 1 10 2 11h
mockmetrics-app-hpa Deployment/mockmetrics-deploy 126/100 1 10 2 11h
mockmetrics-app-hpa Deployment/mockmetrics-deploy 306/100 1 10 2 11h
mockmetrics-app-hpa Deployment/mockmetrics-deploy 171/100 1 10 4 11h

你可以看到当该值达到目标值时,副本数如何增加。

工作流程

自动伸缩的整体流程如下图所示:

结 论

你可以从下方链接中了解更多相关项目和参考资料。在过去的几个版本中,Kubernetes 中的监控流水线已经大有发展,而 Kubernetes 的自动伸缩主要基于该流水线工作。如果你不熟悉这个环境,很容易感到困惑和迷茫。

https://github.com/infracloudio/kubernetes-autoscaling#other-references-and-credits