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

简介: #### 前言 在上一篇文章中,给大家介绍和剖析了HPA的实现原理以及演进的思路与历程。在本文中,我们会为大家讲解如何使用HPA以及一些需要注意的细节。 #### `autoscaling/v1`实践 v1的模板可能是大家平时见到最多的也是最简单的,v1版本的HPA只支持一种指标 —— CPU。传统意义上,弹性伸缩最少也会支持CPU与Memory两种指标,为什么在Ku

前言

在上一篇文章中,给大家介绍和剖析了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版本的DeploymenttargetCPUUtilizationPercentage表示当整体的资源利用率超过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"
  1. 检查扩容状态
    scale-up.png
  2. 关闭压测应用
    delete-load.png
  3. 检查缩容状态
    scale-down.png

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

autoscaling/v2beta1实践

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

image.png

上面这张图为大家展现了开启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。
image.png
将这两个参数拷贝到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'

接下来我们修改下HeapsterService,将服务的后端从Heapster转移到Metrics Server
image.png
如果此时从控制台的节点页面可以获取到右侧的监控信息的话,说明Metrics Server以及完全兼容Heapster
image.png
此时通过kubectl get apiservice,如果可以看到注册的v1beta1.metrics.k8s.io的api,则说明已经注册成功。
image.png
接下来我们需要在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
image.png
需要将--horizontal-pod-autoscaler-use-rest-clients=true,这里有一个注意点,因为如果使用vim进行编辑,vim会自动生成一个缓存文件影响最终的结果,所以比较建议的方式是将这个配置文件移动到其他的目录下进行修改,然后再移回原来的目录。至此,Metrics Server已经可以为HPA进行服务了,接下来我们来做自定义指标的部分。

  1. 部署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/v1autoscaling/v2beta1的感性的认识和大体的操作方式,对于autoscaling/v1我们不做过多的赘述,对于希望使用支持Custom Metricsautoscaling/v2beta1的开发者也许会认为整体的操作流程过于复杂难以理解,我们会在下一篇文章中为大家详解autoscaling/v2beta1使用Custom Metrics的种种细节,帮助大家跟深入的理解这其中的原理与设计思路。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
9月前
|
数据采集 弹性计算 Kubernetes
单机扛不住,我把爬虫搬上了 Kubernetes:弹性伸缩与成本优化的实战
本文讲述了作者在大规模爬虫项目中遇到的挑战,包括任务堆积、高失败率和成本失控。通过将爬虫项目迁移到Kubernetes并使用HPA自动伸缩、代理池隔离和Redis队列,作者成功解决了这些问题,提高了性能,降低了成本,并实现了系统的弹性伸缩。最终,作者通过这次改造学到了性能、代理隔离和成本控制的重要性。
298 2
单机扛不住,我把爬虫搬上了 Kubernetes:弹性伸缩与成本优化的实战
|
Prometheus Kubernetes 监控
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
|
存储 弹性计算 安全
阿里云服务器ECS通用型规格族解析:实例规格、性能基准与场景化应用指南
作为ECS产品矩阵中的核心序列,通用型规格族以均衡的计算、内存、网络和存储性能著称,覆盖从基础应用到高性能计算的广泛场景。通用型规格族属于独享型云服务器,实例采用固定CPU调度模式,实例的每个CPU绑定到一个物理CPU超线程,实例间无CPU资源争抢,实例计算性能稳定且有严格的SLA保证,在性能上会更加稳定,高负载情况下也不会出现资源争夺现象。本文将深度解析阿里云ECS通用型规格族的技术架构、实例规格特性、最新价格政策及典型应用场景,为云计算选型提供参考。
|
人工智能 自然语言处理 算法
DeepSeek大模型在客服系统中的应用场景解析
在数字化浪潮下,客户服务领域正经历深刻变革,AI技术成为提升服务效能与体验的关键。DeepSeek大模型凭借自然语言处理、语音交互及多模态技术,显著优化客服流程,提升用户满意度。它通过智能问答、多轮对话引导、多模态语音客服和情绪监测等功能,革新服务模式,实现高效应答与精准分析,推动人机协作,为企业和客户创造更大价值。
1070 5
|
存储 人工智能 NoSQL
Tablestore深度解析:面向AI场景的结构化数据存储最佳实践
《Tablestore深度解析:面向AI场景的结构化数据存储最佳实践》由阿里云专家团队分享,涵盖Tablestore十年发展历程、AI时代多模态数据存储需求、VCU模式优化、向量检索发布及客户最佳实践等内容。Tablestore支持大规模在线数据存储,提供高性价比、高性能和高可用性,特别针对AI场景进行优化,满足结构化与非结构化数据的统一存储和高效检索需求。通过多元化索引和Serverless弹性VCU模式,助力企业实现低成本、灵活扩展的数据管理方案。
905 12
|
存储 缓存 人工智能
深度解析CPFS 在 LLM 场景下的高性能存储技术
本文深入探讨了CPFS在大语言模型(LLM)训练中的端到端性能优化策略,涵盖计算端缓存加速、智能网卡加速、数据并行访问及数据流优化等方面。重点分析了大模型对存储系统的挑战,包括计算规模扩大、算力多样性及数据集增长带来的压力。通过分布式P2P读缓存、IO加速、高性能存算通路技术以及智能数据管理等手段,显著提升了存储系统的吞吐量和响应速度,有效提高了GPU利用率,降低了延迟,从而加速了大模型的训练进程。总结了CPFS在AI训练场景中的创新与优化实践,为未来大模型发展提供了有力支持。
|
监控 网络协议 算法
OSPFv2与OSPFv3的区别:全面解析与应用场景
OSPFv2与OSPFv3的区别:全面解析与应用场景
760 0
|
算法 Python
Python 大神修炼手册:图的深度优先&广度优先遍历,深入骨髓的解析
在 Python 编程中,掌握图的深度优先遍历(DFS)和广度优先遍历(BFS)是进阶的关键。这两种算法不仅理论重要,还能解决实际问题。本文介绍了图的基本概念、邻接表表示方法,并给出了 DFS 和 BFS 的 Python 实现代码示例,帮助读者深入理解并应用这些算法。
506 2
|
JavaScript API 开发工具
<大厂实战场景> ~ Flutter&鸿蒙next 解析后端返回的 HTML 数据详解
本文介绍了如何在 Flutter 中解析后端返回的 HTML 数据。首先解释了 HTML 解析的概念,然后详细介绍了使用 `http` 和 `html` 库的步骤,包括添加依赖、获取 HTML 数据、解析 HTML 内容和在 Flutter UI 中显示解析结果。通过具体的代码示例,展示了如何从 URL 获取 HTML 并提取特定信息,如链接列表。希望本文能帮助你在 Flutter 应用中更好地处理 HTML 数据。
572 1

推荐镜像

更多
  • DNS