Kubernetes 弹性伸缩全场景解析(三) - HPA 实践手册

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: 在上一篇文章中,给大家介绍和剖析了 HPA 的实现原理以及演进的思路与历程。本文我们将会为大家讲解如何使用 HPA 以及一些需要注意的细节。  实践 v1 的模板可能是大家平时见到最多的也是最简单的,v1 版本的 HPA 只支持一种指标 ——  CPU。

在上一篇文章中,给大家介绍和剖析了 HPA 的实现原理以及演进的思路与历程。本文我们将会为大家讲解如何使用 HPA 以及一些需要注意的细节。

 autoscaling/v1 实践

v1 的模板可能是大家平时见到最多的也是最简单的,v1 版本的 HPA 只支持一种指标 ——  CPU。传统意义上,弹性伸缩最少也会支持 CPU 与 Memory 两种指标,为什么在 Kubernetes 中只放开了 CPU 呢?其实最早的 HPA 是计划同时支持这两种指标的,但是实际的开发测试中发现:内存不是一个非常好的弹性伸缩判断条件。因为和 CPU不 同,很多内存型的应用,并不会因为 HPA 弹出新的容器而带来内存的快速回收,很多应用的内存都要交给语言层面的 VM 进行管理,也就是说,内存的回收是由 VM 的 GC 来决定的。这就有可能因为 GC 时间的差异导致 HPA 在不恰当的时间点震荡,因此在 v1 的版本中,HPA 就只支持了 CPU 这一种指标。

一个标准的 v1 模板大致如下:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50

其中 scaleTargetRef 表示当前要操作的伸缩对象是谁。在本例中,伸缩的对象是一个 apps/v1 版本的 Deployment。 targetCPUUtilizationPercentage 表示:当整体的资源利用率超过 50% 的时候,会进行扩容。接下来我们做一个简单的 Demo 来实践下。

  1. 登录容器服务控制台,首先创建一个应用部署,选择使用模板创建,模板内容如下:
apiVersion: apps/v1beta1
  kind: Deployment
  metadata:
name: php-apache
labels:
 app: php-apache
  spec:
replicas: 1
selector:
 matchLabels:
   app: php-apache
template:
 metadata:
   labels:
     app: php-apache
 spec:
   containers:
   - name: php-apache
     image: registry.cn-hangzhou.aliyuncs.com/ringtail/hpa-example:v1.0
     ports:
     - containerPort: 80
     resources:
       requests:
         memory: "300Mi"
         cpu: "250m"
  --- 
  apiVersion: v1
  kind: Service
  metadata:
name: php-apache
labels:
 app: php-apache
  spec:
selector:
 app: php-apache
ports:
- protocol: TCP
 name: http
 port: 80 
 targetPort: 80
type: ClusterIP

2.部署压测模组 HPA 模板

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
  apiVersion: apps/v1beta1
  kind: Deployment
  name: php-apache
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50

3.开启压力测试

apiVersion: apps/v1beta1
   kind: Deployment
   metadata:
     name: load-generator 
     labels:
       app: load-generator
   spec:
     replicas: 1
     selector:
       matchLabels:
         app: load-generator
     template:
       metadata:
         labels:
           app: load-generator
       spec:
         containers:
         - name: load-generator
           image: busybox 
           command:
             - "sh"
             - "-c"
             - "while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done"

4.检查扩容状态 

a1

5.关闭压测应用

a2

6.检查缩容状态 

a3

这样一个使用 autoscaling/v1 的 HPA 就完成了。相对而言,这个版本的 HPA 目前是最简单的,无论是否升级 Metrics-Server 都可以实现。

autoscaling/v2beta1 实践

在前面的内容中为大家讲解了 HPA 还有 autoscaling/v2beta1 和 autoscaling/v2beta2 两个版本。这两个版本的区别是 autoscaling/v1beta1 支持了 Resource Metrics 和 Custom Metrics。而在 autoscaling/v2beta2 的版本中额外增加了 External Metrics 的支持。对于 External Metrics 在本文中就不进行过多赘述,因为 External Metrics 目前在社区里面没有太多成熟的实现,比较成熟的实现是 Prometheus Custom Metrics

a4

上面这张图为大家展现了开启 Metrics Server 后, HPA 如何使用不同类型的Metrics,如果需要使用 Custom Metrics ,则需要配置安装相应的 Custom Metrics Adapter。在下文中,主要为大家介绍一个基于 QPS 来进行弹性伸缩的例子。

  1. 安装 Metrics Server 并在 kube-controller-manager 中进行开启

目前默认的阿里云容器服务 Kubernetes 集群使用还是 Heapster,容器服务计划在 1.12 中更新 Metrics Server,这个地方需要特别说明下,社区虽然已经逐渐开始废弃 Heapster,但是社区中还有大量的组件是在强依赖 Heapster 的 API,因此阿里云基于 Metrics Server 进行了 Heapster 完整的兼容,既可以让开发者使用 Metrics Server 的新功能,又可以无需担心其他组件的宕机。

在部署新的 Metrics Server 之前,我们首先要备份一下 Heapster 中的一些启动参数,因为这些参数稍后会直接用在 Metrics Server 的模板中。其中重点关心的是两个 Sink,如果需要使用 Influxdb 的开发者,可以保留第一个 Sink;如果需要保留云监控集成能力的开发者,则保留第二个 Sink。 

a5

将这两个参数拷贝到 Metrics Server 的启动模板中,在本例中是两个都兼容,并下发部署。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    kubernetes.io/name: "Metrics-server"
spec:
  selector:
    k8s-app: metrics-server
  ports:
  - port: 443
    protocol: TCP
    targetPort: 443
---
apiVersion: apiregistration.k8s.io/v1beta1
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
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: admin
      containers:
      - name: metrics-server
        image: registry.cn-hangzhou.aliyuncs.com/ringtail/metrics-server:1.1
        imagePullPolicy: Always
        command:
        - /metrics-server
        - '--source=kubernetes:https://kubernetes.default'
        - '--sink=influxdb:http://monitoring-influxdb:8086'
        - '--sink=socket:tcp://monitor.csk.[region_id].aliyuncs.com:8093?clusterId=[cluster_id]&public=true'

接下来我们修改下 Heapster 的 Service,将服务的后端从 Heapster 转移到 Metrics Server。 

a6

如果此时从控制台的节点页面可以获取到右侧的监控信息的话,说明 Metrics Server 已经完全兼容 Heapster

a7

此时通过 kubectl get apiservice,如果可以看到注册的 v1beta1.metrics.k8s.io 的 api,则说明已经注册成功。

a8

接下来我们需要在 kube-controller-manager 上切换 Metrics 的数据来源。kube-controller-manger 部署在每个 master 上,是通过 Static Pod 的托管给 kubelet 的。因此只需要修改 kube-controller-manager 的配置文件,kubelet 就会自动进行更新。kube-controller-manager 在主机上的路径是 /etc/kubernetes/manifests/kube-controller-manager.yaml

a9

需要将 --horizontal-pod-autoscaler-use-rest-clients=true,这里有一个注意点,因为如果使用 vim 进行编辑,vim 会自动生成一个缓存文件影响最终的结果,所以比较建议的方式是将这个配置文件移动到其他的目录下进行修改,然后再移回原来的目录。至此,Metrics Server 已经可以为 HPA 进行服务了,接下来我们来做自定义指标的部分。

2.部署 Custom Metrics Adapter

如集群中未部署 Prometheus,可以参考《阿里云容器Kubernetes监控(七) - Prometheus监控方案部署》先部署 Prometheus。接下来我们部署 Custom Metrics Adapter

kind: Namespace
apiVersion: v1
metadata:
  name: custom-metrics
---
kind: ServiceAccount
apiVersion: v1
metadata:
  name: custom-metrics-apiserver
  namespace: custom-metrics
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: custom-metrics:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: custom-metrics-apiserver
  namespace: custom-metrics
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: custom-metrics-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: custom-metrics-apiserver
  namespace: custom-metrics
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-metrics-resource-reader
rules:
- apiGroups:
  - ""
  resources:
  - namespaces
  - pods
  - services
  verbs:
  - get
  - list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: custom-metrics-apiserver-resource-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: custom-metrics-resource-reader
subjects:
- kind: ServiceAccount
  name: custom-metrics-apiserver
  namespace: custom-metrics
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-metrics-getter
rules:
- apiGroups:
  - custom.metrics.k8s.io
  resources:
  - "*"
  verbs:
  - "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: hpa-custom-metrics-getter
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: custom-metrics-getter
subjects:
- kind: ServiceAccount
  name: horizontal-pod-autoscaler
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: custom-metrics-apiserver
  namespace: custom-metrics
  labels:
    app: custom-metrics-apiserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: custom-metrics-apiserver
  template:
    metadata:
      labels:
        app: custom-metrics-apiserver
    spec:
      tolerations:
      - key: beta.kubernetes.io/arch
        value: arm
        effect: NoSchedule
      - key: beta.kubernetes.io/arch
        value: arm64
        effect: NoSchedule
      serviceAccountName: custom-metrics-apiserver
      containers:
      - name: custom-metrics-server
        image: luxas/k8s-prometheus-adapter:v0.2.0-beta.0
        args:
        - --prometheus-url=http://prometheus-k8s.monitoring.svc:9090
        - --metrics-relist-interval=30s
        - --rate-interval=60s
        - --v=10
        - --logtostderr=true
        ports:
        - containerPort: 443
        securityContext:
          runAsUser: 0
---
apiVersion: v1
kind: Service
metadata:
  name: api
  namespace: custom-metrics
spec:
  ports:
  - port: 443
    targetPort: 443
  selector:
    app: custom-metrics-apiserver
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: v1beta1.custom.metrics.k8s.io
spec:
  insecureSkipTLSVerify: true
  group: custom.metrics.k8s.io
  groupPriorityMinimum: 1000
  versionPriority: 5
  service:
    name: api
    namespace: custom-metrics
  version: v1beta1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-metrics-server-resources
rules:
- apiGroups:
  - custom-metrics.metrics.k8s.io
  resources: ["*"]
  verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: hpa-controller-custom-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: custom-metrics-server-resources
subjects:
- kind: ServiceAccount
  name: horizontal-pod-autoscaler
  namespace: kube-system

3.部署手压测应用与 HPA 模板

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: sample-metrics-app
  name: sample-metrics-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-metrics-app
  template:
    metadata:
      labels:
        app: sample-metrics-app
    spec:
      tolerations:
      - key: beta.kubernetes.io/arch
        value: arm
        effect: NoSchedule
      - key: beta.kubernetes.io/arch
        value: arm64
        effect: NoSchedule
      - key: node.alpha.kubernetes.io/unreachable
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 0
      - key: node.alpha.kubernetes.io/notReady
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 0
      containers:
      - image: luxas/autoscale-demo:v0.1.2
        name: sample-metrics-app
        ports:
        - name: web
          containerPort: 8080
        readinessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: sample-metrics-app
  labels:
    app: sample-metrics-app
spec:
  ports:
  - name: web
    port: 80
    targetPort: 8080
  selector:
    app: sample-metrics-app
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: sample-metrics-app
  labels:
    service-monitor: sample-metrics-app
spec:
  selector:
    matchLabels:
      app: sample-metrics-app
  endpoints:
  - port: web
---
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: sample-metrics-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sample-metrics-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Object
    object:
      target:
        kind: Service
        name: sample-metrics-app
      metricName: http_requests
      targetValue: 100
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: sample-metrics-app
  namespace: default
  annotations:
    traefik.frontend.rule.type: PathPrefixStrip
spec:
  rules:
  - http:
      paths:
      - path: /sample-app
        backend:
          serviceName: sample-metrics-app
          servicePort: 80

这个压测的应用暴露了一个 Prometheus 的接口。接口中的数据如下,其中 http_requests_total 这个指标就是我们接下来伸缩使用的自定义指标。

[root@iZwz99zrzfnfq8wllk0dvcZ manifests]# curl 172.16.1.160:8080/metrics
# HELP http_requests_total The amount of requests served by the server in total
# TYPE http_requests_total counter
http_requests_total 3955684

4.部署压测应用

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: load-generator 
  labels:
    app: load-generator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: load-generator
  template:
    metadata:
      labels:
        app: load-generator
    spec:
      containers:
      - name: load-generator
        image: busybox 
        command:
          - "sh"
          - "-c"
          - "while true; do wget -q -O- http://sample-metrics-app.default.svc.cluster.local; done"

5.查看 HPA 的状态与伸缩,稍等几分钟,Pod 已经伸缩成功了。

workspace kubectl get hpa
NAME                     REFERENCE                       TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
php-apache               Deployment/php-apache           0%/50%        1         10        1          21d
sample-metrics-app-hpa   Deployment/sample-metrics-app   538133m/100   2         10        10         15h

最后

这篇文章主要是给大家带来一个对于 autoscaling/v1 和 autoscaling/v2beta1 的感性认知和大体的操作方式,对于 autoscaling/v1 我们不做过多的赘述,对于希望使用支持 Custom Metrics 的 autoscaling/v2beta1 的开发者而言,也许会认为整体的操作流程过于复杂难以理解,我们会在下一篇文章中为大家详解 autoscaling/v2beta1 使用 Custom Metrics 的种种细节,帮助大家更深入地理解其中的原理与设计思路。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
存储 人工智能 NoSQL
Tablestore深度解析:面向AI场景的结构化数据存储最佳实践
《Tablestore深度解析:面向AI场景的结构化数据存储最佳实践》由阿里云专家团队分享,涵盖Tablestore十年发展历程、AI时代多模态数据存储需求、VCU模式优化、向量检索发布及客户最佳实践等内容。Tablestore支持大规模在线数据存储,提供高性价比、高性能和高可用性,特别针对AI场景进行优化,满足结构化与非结构化数据的统一存储和高效检索需求。通过多元化索引和Serverless弹性VCU模式,助力企业实现低成本、灵活扩展的数据管理方案。
68 12
|
1月前
|
存储 缓存 人工智能
深度解析CPFS 在 LLM 场景下的高性能存储技术
本文深入探讨了CPFS在大语言模型(LLM)训练中的端到端性能优化策略,涵盖计算端缓存加速、智能网卡加速、数据并行访问及数据流优化等方面。重点分析了大模型对存储系统的挑战,包括计算规模扩大、算力多样性及数据集增长带来的压力。通过分布式P2P读缓存、IO加速、高性能存算通路技术以及智能数据管理等手段,显著提升了存储系统的吞吐量和响应速度,有效提高了GPU利用率,降低了延迟,从而加速了大模型的训练进程。总结了CPFS在AI训练场景中的创新与优化实践,为未来大模型发展提供了有力支持。
|
3月前
|
Prometheus Kubernetes 监控
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
|
3月前
|
监控 网络协议 算法
OSPFv2与OSPFv3的区别:全面解析与应用场景
OSPFv2与OSPFv3的区别:全面解析与应用场景
96 0
|
3月前
|
弹性计算 监控 大数据
云计算中的弹性伸缩:原理与实践
云计算中的弹性伸缩:原理与实践
|
3月前
|
算法 Python
Python 大神修炼手册:图的深度优先&广度优先遍历,深入骨髓的解析
在 Python 编程中,掌握图的深度优先遍历(DFS)和广度优先遍历(BFS)是进阶的关键。这两种算法不仅理论重要,还能解决实际问题。本文介绍了图的基本概念、邻接表表示方法,并给出了 DFS 和 BFS 的 Python 实现代码示例,帮助读者深入理解并应用这些算法。
64 2
|
3月前
|
JavaScript API 开发工具
<大厂实战场景> ~ Flutter&鸿蒙next 解析后端返回的 HTML 数据详解
本文介绍了如何在 Flutter 中解析后端返回的 HTML 数据。首先解释了 HTML 解析的概念,然后详细介绍了使用 `http` 和 `html` 库的步骤,包括添加依赖、获取 HTML 数据、解析 HTML 内容和在 Flutter UI 中显示解析结果。通过具体的代码示例,展示了如何从 URL 获取 HTML 并提取特定信息,如链接列表。希望本文能帮助你在 Flutter 应用中更好地处理 HTML 数据。
157 1
|
4月前
|
Prometheus Kubernetes 监控
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
181 1
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
|
3月前
|
负载均衡 网络协议 算法
OSPF与其他IGP协议的比较:全面解析与应用场景
OSPF与其他IGP协议的比较:全面解析与应用场景
95 0
|
4月前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
86 5

相关产品

  • 容器服务Kubernetes版
  • 推荐镜像

    更多