18. Pod 自动管理——HPA 自动扩缩容机制

本章讲解知识点

  • 前言
  • HPA 自动扩缩容机制

<br>

1. 前言

前面我们学习了 Deployment、 StatefulSet、DeamonSet、Job,明白了 Kubernetes 为了帮助我们更好的管理 Pod,提供了一系列好用的工具。但是还远远不止于此,以上工具还需要我们手动设置 replicas 副本数量。

我们来想象一种场景,我们服务已经正常上线了,运行良好。但是节假日流量突升,我们不得不扩容副本以应对流量;然后节假日一过,我们又得手动缩容。听起来好像有点麻烦,有没有更方便的方法,让系统自动感知流量突升并自动增加副本数量?

当然有,就是我们接下来要讲的 HPA 自动扩缩容机制。

<br>

2. HPA 自动扩缩容机制

2.1. 工作原理

HPA(Horizontal Pod Autoscaler)是 Kubernetes 中一种自动扩缩容机制,它可以根据预定义的指标来自动调整 Pod 的数量,以达到更好的负载均衡和性能。

HPA 根据监控指标来决定是否需要自动扩缩容,监控指标通常包括 CPU 使用率、内存使用率、网络流量等。当监控指标超过了预设的阈值时,HPA 将自动创建或销毁 Pod,以增加或减少集群中的计算资源。

HPA 的工作原理如下:

  • HPA 获取 Pod 相关的监控指标。
  • 根据指标值,计算出需要的 Pod 数量。
  • 通过 API Server 更新 Deployment、ReplicaSet、StatefulSet 等对象的 Replicas 字段,发起 scale 操作,来实现自动扩缩容。

在 HPA 中,可以设置最小副本数和最大副本数,来限制 Pod 数量的变化范围。同时,也可以设置扩缩容的速率、触发阈值等参数,以更好地控制 HPA 的行为。

使用 HPA 可以避免手动调整 Pod 数量的繁琐工作,提高集群的自动化程度和可维护性。

2.2. 指标的类型

  • Pod 的资源使用率,例如 CPU 使用率
  • Pod 自定义指标,例如接收的请求数量
  • Object 自定义指标或外部定义指标,需要容器应用以某种方式提供,例如通过 HTTP URL“/metrics” 提供, 或者使用外部服务提供的指标采集 URL

Kubernetes从1.11 版本开始,全面转向基于Metrics Server完成数据采集。 Metrics Server 将采集到的 Pod 性能指标数据通过聚合API(Aggregated API) 如 metrics.k8s.io、 custom.metrics.k8s.io 和 external.metrics.k8s.io 提供给 HPA 控制器进行查询。

2.3. 扩容算法详解

Autoscaler 控制器从聚合 API 获取到 Pod 性能指标数据之后,基于下面的算法计算出目标 Pod 副本数量,与当前运行的 Pod 的数量进行对比,觉定是否需要进行扩缩容操作:

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

即当前副本数 x ( 当前指标值 / 期望的指标值 ),将结果向上取整。

以 CPU 请求数量为例,如果用户设置的期望指标值为 100m,当前实际使用的指标值为 200m,则计算的得到期望的 Pod 副本数量应为两个(200/100=2)。如果当前实际使用的指标值为 500m,假设计算结果为 0.5,则向上取整,值为 1,得到目标 Pod 副本数量应为 1 个。

当计算结果与 1 非常接近时,可以设置一个容忍度让系统不做扩缩容操作。容忍度通过 kube-controller-manager 服务的启动参数 --horizontal-pod-autoscaler-tolerance 进行设置,默认值为 0.1(即10%),表示基于上述算法得到的结果在 [-10%, +10%] 区间内,即 [0.9, 1.1] 区间,控制器都不会进行扩缩容操作。

也可以将期望指标值(desiredMetricValue)设置为指标的平均值类型,例如 targetAverageValue 或 targetAverageUtilization,此时当前指标值(currentMetricValue)的算法为所有 Pod 副本当前指标值的总和除以 Pod 副本数量得到的平均值。

此外,存在几种 Pod 异常的情况,如下所述:

  • Pod 正在被删除(设置了删除时间戳):将不会计入目标 Pod 副本数量。
  • Pod 的当前指标值无法获得:本次探测不会将这个 Pod 纳入目标 Pod 副本数量,后续的探测会被重新纳入计算范围。
  • 如果指标类型是 CPU 使用率,则对于正在启动但是还未到达 Ready 状态的 Pod,也暂时不会纳入目标副本数量范围。可以通过 kube-controller-manager 服务的启动参数 --horizontal-pod-autoscaler-initial-readiness-delay 设置首次探测 Pod 是否 ready 的延时时间,默认值为 30s。另一个启动参数 --horizontal-pod-autoscaler-cpu-initialization-period 设置首次采集 Pod 的 CPU 使用率的延时时间。

在计算当前指标值 / 期望的指标值时将不会包括上述这些异常的 Pod。

当存在缺失指标的 Pod 时,系统将更保守地重新计算平均值。系统会假设这些 Pod 在需要缩容时消耗了期望指标值的 100%,在需要扩容时消耗了期望指标值的 0%,这样可以抑制潜在的扩缩容操作。

此外,如果存在未达到 Ready 状态的 Pod,并且系统原本会在不考虑缺失指标或 NotReady 的 Pod 情况下进行扩展,则系统任然会保守地假设这些 Pod 消耗期望指标值的 0%,从而进一步抑制扩容操作。

如果在 HorizontalPodAutoscaler 中设置了多少个指标,系统就会对每个指标都执行上面的算法,在全部结果中以期望副本数量的最大值为最终结果。如果这些指标中的任意一个都无法被转换为期望的副本数量,系统就会跳过扩缩容操作。

使用 HPA 特性时,可能因为指标动态的变化造成 Pod 副本数量频繁变动,这也被称为“抖动”。抖动会影响到业务的稳定性。Kubernetes 1.12 版本增加了全新的参数 Horizontal-pod-autoscaler-downscale-stabilization(kube-controller-manager 服务的参数)来解决这个问题。它表示 HPA 扩缩容过程中的冷却时间,即从上次扩缩容执行结束后,需要经过最少多长时间才可以再次执行扩缩容操作。当前的默认时间时 5min,此配置可以让系统更为平滑地进行扩缩容操作,从而消除短时间内指标值快速波动产生的影响。对该值的设定以实际生产环境为准,时间设置过短,系统抖动,设置时间过长,导致 HPA 失效。

2.4. 实验

接下来我们就开始实验,创建我们的第一个 HorizontalPodAutoscaler 定义文件,命名为 my-first-hpa.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-first-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-first-deploy
  template:
    metadata:
      labels:
        app: my-first-deploy
    spec:
      containers:
      - name: my-first-container
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: "2"
          requests:
            cpu: "200m"

---
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-first-deploy
  minReplicas: 1
  maxReplicas: 3
  targetCPUUtilizationPercentage: 50

上面的 YAML 文件定义了一个名为 my-first-deploy 的 Deployment 和一个名为 myapp-hpa 的 HPA 对象。Deployment 启动了一个名为 my-first-container 的容器,使用最多 2 个 CPU 核心并请求至少 200m 的 CPU 资源。HPA 对象定义了一个名为 cpu 的指标,并将目标 CPU 利用率设置为 50%。这意味着如果平均 CPU 利用率超过 50%,则 HPA 会尝试增加副本数量以满足所需的容量,如果平均 CPU 利用率低于 50%,则 HPA 会尝试减少副本数量。

主要参数如下:

  • scaleTargetRef 是指标对象的引用,用于告诉 HPA 从哪个对象中获取指标数据。如Deployment、StatefulSet
  • minReplicas 参数用于指定该 Deployment/ReplicaSet/StatefulSet 的最小 Pod 副本数,HPA 在运行过程中不会将 Pod 的数量减少到该值以下。
  • metrics 参数用于定义度量指标的类型和配置

可以将metrics 中的type(指标类型)设置为以下四种:

  • Pods:这是默认值。使用此类型时,HPA 将监视 pods。HPA 将使用 pod 中的资源使用情况指标来确定需要增加或减少多少个 pods。
  • Object:使用此类型时,HPA 将监视对象的指标。使用此类型时,必须指定一个具有可读度量标准端点的 API 对象。例如,Deployment、ReplicaSet、StatefulSet 等。HPA 将使用这些对象的度量标准来确定需要增加或减少多少个副本。
  • Resource:使用此类型时,HPA 将监视 Pod 中的资源使用情况指标,例如 CPU 和内存。HPA 将使用 pod 中的资源使用情况指标来确定需要增加或减少多少个 pods。
  • External:使用此类型时,HPA 将监视来自外部 API 的度量标准。必须指定度量标准的 endpoint。例如 Prometheus、Heapster 等。

我们创建应用:

[root@master mtuser]# kubectl create -f my-first-hpa.yaml
deployment.apps/my-first-deploy created
horizontalpodautoscaler.autoscaling/myapp-hpa created
[root@master mtuser]#
[root@master mtuser]# kubectl get hpa
NAME        REFERENCE                    TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
myapp-hpa   Deployment/my-first-deploy   <unknown>/50%   1         3         0          10s
[root@master mtuser]#
[root@master mtuser]# kubectl get deploy
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
my-first-deploy   1/1     1            1           25s
[root@master mtuser]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
my-first-deploy-7c69657-w7qfk   1/1     Running   0          28s

我们发现此时 HPA 在监控 Pod CPU 占用率时显示 unknown,这时因为需要依赖 metrics server 服务才能采集 Pod CPU 占有率信息,因此我们需要安装 metrics server,下载定义文件 components.yaml:

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

components.yaml 定义文件如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"
  name: system:aggregated-metrics-reader
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  - configmaps
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selec

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

云计算面试题全解析 文章被收录于专栏

本专刊适合于立志转行云计算的小白,有一定的编程、操作系统、计算机网络、数据结构、算法基础。 本专刊同时也适合于面向云计算(Docker + Kubernetes)求职的从业者。 本专刊囊括了云计算、VMWare、Docker、Kubernetes、Containerd等一系列知识点的讲解,并且最后总

全部评论

相关推荐

牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务