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等一系列知识点的讲解,并且最后总