如何使用Metrics Server配置Kubernetes水平Pod自动缩放器

引言

Kubernetes旨在提供可靠性和可伸缩性。它通过部署具有不同资源分配的多个Pod来为您的应用程序提供冗余。尽管您可以根据自己的需求手动扩大或缩小部署,但Kubernetes提供了一种名为Horizontal Pod Autoscaling的特性,能够提供即时扩展的一流支持。它是一个闭环系统,根据您当前的需求自动增加或减少资源(应用程序Pod)。您为每个需要自动缩放的应用程序部署创建一个HorizontalPodAutoscaler(或HPA)资源,并让它自动处理其余事项。

从较高层面来看,HPA的工作如下:

    1. 通过查询度量服务器,它会监视来自应用工作负载(Pods)的资源请求指标。

 

    1. 它会将您在HPA定义中设置的目标阈值值与观察到的应用工作负载(CPU和内存)的平均资源利用率进行比较。

 

    如果达到目标阈值,HPA将扩展您的应用部署以满足更高的需求。否则,如果低于阈值,则会缩小部署规模。要了解HPA用于扩展您的应用部署的逻辑,请查阅官方文档中的算法详细信息页面。

在底层,HorizontalPodAutoscaler是一个CRD(自定义资源定义),该资源通过集群内的专用控制器实现了Kubernetes控制循环。您可以创建一个针对应用程序部署的HorizontalPodAutoscaler YAML清单,并使用kubectl将HPA资源应用于集群中。

为了工作起来,HPA 需要集群中可用的指标服务器来抓取所需的指标,例如 CPU 和内存利用率。一个简单的选择是 Kubernetes 指标服务器。指标服务器通过从 Kubelets 收集资源指标,并通过 Kubernetes API 服务器向 Horizontal Pod Autoscaler 公开这些指标来工作。如有需要,也可以通过 kubectl top 访问指标 API。

在本教程中,你将会:

  • Deploy Metrics Server to your Kubernetes cluster.
  • Learn how to create Horizontal Pod Autoscalers for your applications.
  • Test each HPA setup, using two scenarios: constant and variable application load.

如果你正在寻找托管的Kubernetes托管服务,请关注我们为增长而构建的简单托管的Kubernetes服务。

先决条件

要按照本教程进行操作,你需要:

  • A Kubernetes cluster with role-based access control (RBAC) enabled. This setup will use a Silicon Cloud Kubernetes cluster, but you could also create a cluster manually. Your Kubernetes version should be between 1.20 and 1.25.
  • The kubectl command-line tool installed in your local environment and configured to connect to your cluster. You can read more about installing kubectl in the official documentation. If you are using a Silicon Cloud Kubernetes cluster, please refer to How to Connect to a Silicon Cloud Kubernetes Cluster to learn how to connect to your cluster using kubectl.
  • The version control tool Git available in your development environment. If you are working in Ubuntu, you can refer to installing Git on Ubuntu 22.04
  • The Kubernetes Helm package manager also available in your development environment. You can refer to how to install software with Helm to install Helm locally.

第一步 – 通过Helm安装Metrics Server

首先,您可以将metrics-server存储库添加到您的helm软件包列表中。您可以使用helm repo add命令。

  1. helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server

 

下一步,使用helm repo update命令来刷新可用的软件包。

  1. helm repo update metrics-server

 

Output

Hang tight while we grab the latest from your chart repositories… …Successfully got an update from the “metrics-server” chart repository Update Complete. ⎈Happy Helming!⎈

既然您已经将存储库添加到Helm中,您现在可以将metrics-server添加到您的Kubernetes部署中。您可以在这里编写自己的部署配置,但本教程将按照Silicon Cloud的Kubernetes入门套件进行,该套件包含了metrics-server的配置。

为了做到这一点,请克隆Kubernetes入门套件的Git仓库。

  1. git clone https://github.com/digitalocean/Kubernetes-Starter-Kit-Developers.git

 

Metrics-Server的配置文件位于Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/metrics-server-values-v3.8.2.yaml。您可以使用nano或您喜欢的文本编辑器查看或编辑它。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/metrics-server-values-v3.8.2.yaml

 

这包含了几个股票参数。请注意,副本是一个固定值,为2。

metrics-server-values-v3.8.2.yaml的指标服务器值为v3.8.2的文件。
## Starter Kit metrics-server configuration
## Ref: https://github.com/kubernetes-sigs/metrics-server/blob/metrics-server-helm-chart-3.8.2/charts/metrics-server
##

# Number of metrics-server replicas to run
replicas: 2

apiService:
  # Specifies if the v1beta1.metrics.k8s.io API service should be created.
  #
  # You typically want this enabled! If you disable API service creation you have to
  # manage it outside of this chart for e.g horizontal pod autoscaling to
  # work with this release.
  create: true

hostNetwork:
  # Specifies if metrics-server should be started in hostNetwork mode.
  #
  # You would require this enabled if you use alternate overlay networking for pods and
  # API server unable to communicate with metrics-server. As an example, this is required
  # if you use Weave network on EKS
  enabled: false

请参考Metrics Server图表页面上的说明,了解metrics-server的可用参数。

Note

注意:在将Kubernetes部署与正在运行的Kubernetes版本匹配时,您需要非常小心,而helm chart本身也具有版本控制以强制执行此操作。当前的上游helm chart版本为3.8.2,可部署0.6.1版本的metrics-server本身。根据Metrics Server兼容性矩阵,您可以看到0.6.x版本支持Kubernetes 1.19+。

在您审查文件并进行任何更改后,您可以继续部署 metrics-server,方法是将此文件与 helm install 命令一起提供。

  1. HELM_CHART_VERSION=“3.8.2”
  2. helm install metrics-server metrics-server/metrics-server –version $HELM_CHART_VERSION \
  3. –namespace metrics-server \
  4. –create-namespace \
  5. -f “Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/metrics-server-values-v${HELM_CHART_VERSION}.yaml”

 

这将在您配置的Kubernetes集群中部署Metrics服务器。

Output

NAME: metrics-server LAST DEPLOYED: Wed May 25 11:54:43 2022 NAMESPACE: metrics-server STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: *********************************************************************** * Metrics Server * *********************************************************************** Chart version: 3.8.2 App version: 0.6.1 Image tag: k8s.gcr.io/metrics-server/metrics-server:v0.6.1 ***********************************************************************

部署完成后,您可以使用helm ls命令来验证metrics-server是否已添加到您的部署中。

  1. helm ls -n metrics-server

 

Output

NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION metrics-server metrics-server 1 2022-02-24 14:58:23.785875 +0200 EET deployed metrics-server-3.8.2 0.6.1

接下来,您可以检查部署到metrics-server命名空间的所有Kubernetes资源的状态。

  1. kubectl get all -n metrics-server

 

根据您所部署的配置,deployment.apps和replicaset.apps的值应该计算出两个可用实例。

Output

NAME READY STATUS RESTARTS AGE pod/metrics-server-694d47d564-9sp5h 1/1 Running 0 8m54s pod/metrics-server-694d47d564-cc4m2 1/1 Running 0 8m54s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/metrics-server ClusterIP 10.245.92.63 <none> 443/TCP 8m54s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/metrics-server 2/2 2 2 8m55s NAME DESIRED CURRENT READY AGE replicaset.apps/metrics-server-694d47d564 2 2 2 8m55s

您现在已将指标服务器部署到您的Kubernetes集群中。下一步,您将查看HorizontalPodAutoscaler自定义资源定义的一些参数。

第二步 – 了解HPAs

到目前为止,您的配置都使用了一个固定值来部署ReplicaSet实例的数量。在这一步中,您将学习如何定义一个HorizontalPodAutoscaler CRD,以便该值可以动态增加或缩小。

一个典型的HorizontalPodAutoscaler CRD的样子如下:

crd.yaml 的含义是什么?
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app-deployment
  minReplicas: 1
  maxReplicas: 3
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

这个配置中使用的参数如下:

  • spec.scaleTargetRef: A named reference to the resource being scaled.
  • spec.minReplicas: The lower limit for the number of replicas to which the autoscaler can scale down.
  • spec.maxReplicas: The upper limit.
  • spec.metrics.type: The metric to use to calculate the desired replica count. This example is using the Resource type, which tells the HPA to scale the deployment based on average CPU (or memory) utilization. averageUtilization is set to a threshold value of 50.

你有两种选择来创建应用部署的高性能架构(HPA):

    1. 使用 kubectl autoscale 命令在现有的部署上进行自动缩放。

 

    创建一个 HPA YAML 清单,然后使用 kubectl 将更改应用到您的集群。

你将首先尝试选项#1,使用Silicon Cloud Kubernetes入门套件中的另一种配置。其中包含一个名为myapp-test.yaml的部署文件,通过创建一些任意的CPU负载来演示HPA的工作情况。

你可以使用nano或你喜欢的文本编辑器来查看那个文件。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/myapp-test.yaml

 

我的应用程序测试文件 myapp-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-test
spec:
  selector:
    matchLabels:
      run: myapp-test
  replicas: 1
  template:
    metadata:
      labels:
        run: myapp-test
    spec:
      containers:
        - name: busybox
          image: busybox
          resources:
            limits:
              cpu: 50m
            requests:
              cpu: 20m
          command: ["sh", "-c"]
          args:
            - while [ 1 ]; do
              echo "Test";
              sleep 0.01;
              done

请注意文件的最后几行。它们包含一些shell语法,可以每秒重复打印“Test”一百次,以模拟负载。完成文件审核后,您可以使用kubectl将其部署到您的集群中。

  1. kubectl apply -f Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/myapp-test.yaml

 

接下来,使用 kubectl autoscale 创建一个针对 myapp-test 部署的 HorizontalPodAutoscaler。

  1. kubectl autoscale deployment myapp-test –cpu-percent=50 –min=1 –max=3

 

请注意传递给此命令的参数 – 这意味着当CPU利用率达到50%时,您的部署将在1到3个副本之间进行扩展。

你可以通过运行 kubectl get hpa 来检查是否已创建 HPA 资源。

  1. kubectl get hpa

 

最终输出的”目标”栏将显示当前使用量占目标使用量的百分比。

Output

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE myapp-test Deployment/myapp-test 240%/50% 1 3 3 52s

Note

注意:目标列的值在一段时间内(大约15秒)将显示为/50%。这是正常的,因为HPA需要逐渐收集平均值,而在第一个15秒间隔之前,它没有足够的数据。默认情况下,HPA每隔15秒检查一次度量。

您还可以通过使用kubectl describe命令观察HPA生成的已记录事件。

  1. kubectl describe hpa myapp-test

 

Output

Name: myapp-test Namespace: default Labels: <none> Annotations: <none> CreationTimestamp: Mon, 28 May 2022 10:10:50 -0800 Reference: Deployment/myapp-test Metrics: ( current / target ) resource cpu on pods (as a percentage of request): 240% (48m) / 50% Min replicas: 1 Max replicas: 3 Deployment pods: 3 current / 3 desired … Events: Type Reason Age From Message —- —— —- —- ——- Normal SuccessfulRescale 17s horizontal-pod-autoscaler New size: 2; reason: cpu resource utilization (percentage of request) above target Normal SuccessfulRescale 37s horizontal-pod-autoscaler New size: 3; reason: cpu resource utilization (percentage of request) above target

这是kubectl自动缩放的方法。在生产环境中,通常应该使用专门的YAML清单来定义每个HPA,而不是使用这种方法。这样,您可以通过将清单提交到Git仓库并根据需要进行修改来跟踪更改。

在本教程的最后一步,您将通过一个示例来走一遍。在继续之前,删除myapp-test的部署和相应的HPA资源。

  1. kubectl delete hpa myapp-test
  2. kubectl delete deployment myapp-test

 

步骤三 – 通过度量服务器自动缩放应用程序

在这最后一步中,您将尝试两种不同的方法通过YAML清单生成服务器负载并进行扩展。

    1. 一个应用部署通过执行一些CPU密集型计算来创建持续负载。

 

    一个Shell脚本通过连续快速发出HTTP调用来模拟外部负载,用于一个Web应用程序。

恒定负载测试

在这种情况下,您将使用Python创建一个示例应用程序,执行一些CPU密集型计算。类似于上一步中的shell脚本,这段Python代码包含在入门套件的示例清单之一中。您可以使用nano或您最喜欢的文本编辑器打开constant-load-deployment-test.yaml文件。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/constant-load-deployment-test.yaml

 

常量负载部署测试.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: python-test-code-configmap
data:
  entrypoint.sh: |-
    #!/usr/bin/env python

    import math

    while True:
      x = 0.0001
      for i in range(1000000):
        x = x + math.sqrt(x)
        print(x)
      print("OK!")

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: constant-load-deployment-test
spec:
  selector:
    matchLabels:
      run: python-constant-load-test
  replicas: 1
  template:
    metadata:
      labels:
        run: python-constant-load-test
    spec:
      containers:
        - name: python-runtime
          image: python:alpine3.15
          resources:
            limits:
              cpu: 50m
            requests:
              cpu: 20m
          command:
            - /bin/entrypoint.sh
          volumeMounts:
            - name: python-test-code-volume
              mountPath: /bin/entrypoint.sh
              readOnly: true
              subPath: entrypoint.sh
      volumes:
        - name: python-test-code-volume
          configMap:
            defaultMode: 0700
            name: python-test-code-configmap

以上突出显示了一个Python代码,它重复生成任意平方根。部署将获取一个托管所需Python运行时的Docker镜像,然后将ConfigMap附加到托管之前显示的示例Python脚本的应用Pod上。

首先,为这个部署创建一个独立的命名空间(以便更好地观察),然后通过kubectl部署它。

  1. kubectl create ns hpa-constant-load
  2. kubectl apply -f Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/constant-load-deployment-test.yaml -n hpa-constant-load

 

Output

configmap/python-test-code-configmap created deployment.apps/constant-load-deployment-test created

Note

注意:示例部署还为示例应用程序的Pod配置了资源请求限制。这一点很重要,因为HPA逻辑依赖于设置Pod的资源请求限制。通常情况下,建议为您所有的应用程序Pod设置资源请求限制,以避免不可预测的瓶颈。

验证部署是否成功创建,并且已经启动运行。

  1. kubectl get deployments -n hpa-constant-load

 

Output

NAME READY UP-TO-DATE AVAILABLE AGE constant-load-deployment-test 1/1 1 1 8s

接下来,您需要在此集群中部署另一个HPA。在constant-load-hpa-test.yaml中有一个匹配此场景的示例,您可以使用Nano或您喜欢的文本编辑器打开它。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/constant-load-hpa-test.yaml -n hpa-constant-load

 

恒定负载 HPA 测试.yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: constant-load-test
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: constant-load-deployment-test
  minReplicas: 1
  maxReplicas: 3
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

通过使用kubectl进行部署

  1. kubectl apply -f Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/constant-load-hpa-test.yaml -n hpa-constant-load

 

这将创建一个针对样本 Python 部署的 HPA 资源。可以通过 kubectl get hpa 命令来检查 constant-load-test HPA 的状态。

  1. kubectl get hpa constant-load-test -n hpa-constant-load

 

请注意参考列针对常量负载部署测试,以及目标列显示当前CPU资源请求与阈值数值的对比,如上一个示例所示。

Output

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE constant-load-test Deployment/constant-load-deployment-test 255%/50% 1 3 3 49s

你可能还会注意到示例应用的部署中,根据HPA CRD规范,REPLICAS列的值从1增加到3。这一变化发生得非常快,因为该示例中使用的应用程序能够迅速生成CPU负载。和之前的示例一样,你也可以使用kubectl describe hpa -n hpa-constant-load命令来查看记录的HPA事件。

外部负载测试

一个更有趣和真实的场景是观察外部负载的产生位置。对于这个最后的示例,您将使用不同的命名空间和清单集来避免重用之前测试中的任何数据。

本例将使用当前样本服务器的引用。每当向该服务器发送HTTP请求时,它将作为响应发送不同的引用。您将通过每1毫秒发送HTTP请求来对集群进行负载测试。此部署已包含在quote_deployment.yaml文件中。请使用nano或您喜欢的文本编辑器查看此文件。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/quote_deployment.yaml

 

“引用部署.yaml”
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: quote
spec:
  replicas: 1
  selector:
    matchLabels:
      app: quote
  template:
    metadata:
      labels:
        app: quote
    spec:
      containers:
        - name: quote
          image: docker.io/datawire/quote:0.4.1
          ports:
            - name: http
              containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 50Mi
            limits:
              cpu: 200m
              memory: 100Mi

---
apiVersion: v1
kind: Service
metadata:
  name: quote
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app: quote

请注意,这次实际的HTTP查询脚本不包含在清单中 – 此清单仅用于配置应用程序以进行查询运行。完成文件审查后,请使用kubectl创建引用命名空间和部署。

  1. kubectl create ns hpa-external-load
  2. kubectl apply -f Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/quote_deployment.yaml -n hpa-external-load

 

确认报价应用程序的部署和服务是否正常运行。

  1. kubectl get all -n hpa-external-load

 

Output

NAME READY STATUS RESTARTS AGE pod/quote-dffd65947-s56c9 1/1 Running 0 3m5s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/quote ClusterIP 10.245.170.194 <none> 80/TCP 3m5s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/quote 1/1 1 1 3m5s NAME DESIRED CURRENT READY AGE replicaset.apps/quote-6c8f564ff 1 1 1 3m5s

接下来,您将为报价部署创建HPA(Horizontal Pod Autoscaler)。这将在quote-deployment-hpa-test.yaml中进行配置。请使用Nano或您喜欢的文本编辑器查看该文件。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/quote-deployment-hpa-test.yaml

 

“请将以下内容用中文进行释义:

引用-deployment-hpa-test.yaml”

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: external-load-test
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: quote
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 60
  minReplicas: 1
  maxReplicas: 3
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 20

请注意,在这种情况下,CPU利用率资源指标的阈值值(20%)设置不同。还有一种不同的缩放行为。此配置改变了scaleDown.stabilizationWindowSeconds的行为,并将其设置为较低的60秒。这并不总是在实践中需要,但在这种情况下,您可能希望加快速度,以便更快地查看自动缩放器执行缩放操作的情况。默认情况下,HorizontalPodAutoscaler具有5分钟的冷却期。在大多数情况下,这已经足够,并且应该避免副本进行缩放时的波动。

当您准备好时,请使用kubectl部署。

  1. kubectl apply -f Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/manifests/hpa/metrics-server/quote-deployment-hpa-test.yaml -n hpa-external-load

 

现在,检查HPA资源是否已经部署并且正常运行。

  1. kubectl get hpa external-load-test -n hpa-external-load

 

Output

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE external-load-test Deployment/quote 1%/20% 1 3 1 108s

最后,您将使用shell脚本quote_service_load_test.sh来运行实际的HTTP查询。之前没有将这个shell脚本嵌入到清单中的原因是为了能够在集群中观察其运行,并直接记录到您的终端中。使用nano或您喜欢的文本编辑器查看该脚本的内容。

  1. nano Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/scripts/quote_service_load_test.sh

 

引用服务负载测试脚本。
#!/usr/bin/env sh

echo
echo "[INFO] Starting load testing in 10s..."
sleep 10
echo "[INFO] Working (press Ctrl+C to stop)..."
kubectl run -i --tty load-generator \
    --rm \
    --image=busybox \
    --restart=Never \
    -n hpa-external-load \
    -- /bin/sh -c "while sleep 0.001; do wget -q -O- http://quote; done" > /dev/null 2>&1
echo "[INFO] Load testing finished."

为了进行这个演示,在两个独立的终端窗口中打开。在第一个终端中运行quote_service_load_test.sh的shell脚本。

  1. Kubernetes-Starter-Kit-Developers/09-scaling-application-workloads/assets/scripts/quote_service_load_test.sh

 

接下来,在第二个窗口中,使用 -w 标志在 HPA 资源上运行一个 kubectl watch 命令。

  1. kubectl get hpa -n hpa-external-load -w

 

你应该看到负载指数逐渐上升,并且自动按比例缩放。

Output

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE external-load-test Deployment/quote 1%/20% 1 3 1 2m49s external-load-test Deployment/quote 29%/20% 1 3 1 3m1s external-load-test Deployment/quote 67%/20% 1 3 2 3m16s

当负载增加时,您可以观察到自动缩放器的启动,它会将报价服务器的部署副本集增加到更高的值。一旦负载生成脚本停止,会有一个冷却期,大约1分钟后,副本集会降低到初始值1。在返回到第一个终端窗口后,您可以按Ctrl+C终止运行的脚本。

结论:

在本教程中,您部署并观察了使用Kubernetes Metrics Server的水平Pod自动扩展(HPA)在几种不同情景下的行为。HPA是Kubernetes的一个重要组件,可以在需要时帮助您的基础架构处理更多的流量。

Metrics Server在于不能提供除了CPU或内存使用之外的任何指标,这是一个重要的限制。您可以进一步阅读Metrics Server的文档,了解如何在其使用情况下进行操作。如果您需要使用其他指标(例如磁盘使用或网络负载)进行扩展,您可以使用一个名为prometheus-adapter的特殊适配器来使用Prometheus。

发表回复 0

Your email address will not be published. Required fields are marked *