zoukankan      html  css  js  c++  java
  • 十三、Kubernetes之HPA

    1、Pod 水平自动扩缩

    Pod 水平自动扩缩(Horizontal Pod Autoscaler) 可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。 除了 CPU 利用率,也可以基于其他应程序提供的 自定义度量指标 来执行自动扩缩。 Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。

    Pod 水平自动扩缩特性由 Kubernetes API 资源和控制器实现。资源决定了控制器的行为。 控制器会周期性地调整副本控制器或 Deployment 中的副本数量,以使得类似 Pod 平均 CPU 利用率、平均内存利用率这类观测到的度量值与用户所设定的目标值匹配。

    2、Horizontal Pod Autoscaler 如何工作

     

    Pod 水平自动扩缩器的实现是一个控制回路,由控制器管理器的 --horizontal-pod-autoscaler-sync-period 参数指定周期(默认值为 15 秒)。

    每个周期内,控制器管理器根据每个 HorizontalPodAutoscaler 定义中指定的指标查询资源利用率。 控制器管理器可以从资源度量指标 API(按 Pod 统计的资源用量)和自定义度量指标 API(其他指标)获取度量值。

    • 对于按 Pod 统计的资源指标(如 CPU),控制器从资源指标 API 中获取每一个 HorizontalPodAutoscaler 指定的 Pod 的度量值,如果设置了目标使用率, 控制器获取每个 Pod 中的容器资源使用情况,并计算资源使用率。 如果设置了 target 值,将直接使用原始数据(不再计算百分比)。 接下来,控制器根据平均的资源使用率或原始值计算出扩缩的比例,进而计算出目标副本数。

      需要注意的是,如果 Pod 某些容器不支持资源采集,那么控制器将不会使用该 Pod 的 CPU 使用率。

    • 如果 Pod 使用自定义指示,控制器机制与资源指标类似,区别在于自定义指标只使用 原始值,而不是使用率。

    • 如果 Pod 使用对象指标和外部指标(每个指标描述一个对象信息)。 这个指标将直接根据目标设定值相比较,并生成一个上面提到的扩缩比例。 在 autoscaling/v2beta2 版本 API 中,这个指标也可以根据 Pod 数量平分后再计算。

    通常情况下,控制器将从一系列的聚合 API(metrics.k8s.iocustom.metrics.k8s.ioexternal.metrics.k8s.io)中获取度量值。 metrics.k8s.io API 通常由 Metrics 服务器(需要额外启动)提供。 可以从 metrics-server 获取更多信息。 另外,控制器也可以直接从 Heapster 获取指标。

    说明:
    FEATURE STATE: Kubernetes 1.11 [deprecated]
    自 Kubernetes 1.11 起,从 Heapster 获取指标特性已废弃。

    自动扩缩控制器使用 scale 子资源访问相应可支持扩缩的控制器(如副本控制器、 Deployment 和 ReplicaSet)。 scale 是一个可以动态设定副本数量和检查当前状态的接口。

    3、HPA的基本算法

    pod 水平自动扩缩控制器根据当前指标和期望指标来计算扩缩比例。

    期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]

    例如,当前度量值为 200m,目标设定值为 100m,那么由于 200.0/100.0 == 2.0, 副本数量将会翻倍。 如果当前指标为 50m,副本数量将会减半,因为50.0/100.0 == 0.5。 如果计算出的扩缩比例接近 1.0 (根据--horizontal-pod-autoscaler-tolerance 参数全局配置的容忍值,默认为 0.1), 将会放弃本次扩缩。

    如果 HorizontalPodAutoscaler 指定的是 targetAverageValuetargetAverageUtilization, 那么将会把指定 Pod 度量值的平均值做为 currentMetricValue。 然而,在检查容忍度和决定最终扩缩值前,我们仍然会把那些无法获取指标的 Pod 统计进去。

    所有被标记了删除时间戳(Pod 正在关闭过程中)的 Pod 和失败的 Pod 都会被忽略。

    如果某个 Pod 缺失度量值,它将会被搁置,只在最终确定扩缩数量时再考虑。

    当使用 CPU 指标来扩缩时,任何还未就绪(例如还在初始化)状态的 Pod 最近的指标 度量值采集于就绪状态前的 Pod,该 Pod 也会被搁置。

    由于受技术限制,Pod 水平扩缩控制器无法准确的知道 Pod 什么时候就绪, 也就无法决定是否暂时搁置该 Pod。 --horizontal-pod-autoscaler-initial-readiness-delay 参数(默认为 30s)用于设置 Pod 准备时间, 在此时间内的 Pod 统统被认为未就绪。 --horizontal-pod-autoscaler-cpu-initialization-period 参数(默认为5分钟) 用于设置 Pod 的初始化时间, 在此时间内的 Pod,CPU 资源度量值将不会被采纳。

    在排除掉被搁置的 Pod 后,扩缩比例就会根据 currentMetricValue/desiredMetricValue 计算出来。

    如果缺失任何的度量值,我们会更保守地重新计算平均值, 在需要缩小时假设这些 Pod 消耗了目标值的 100%, 在需要放大时假设这些 Pod 消耗了 0% 目标值。 这可以在一定程度上抑制扩缩的幅度。

    此外,如果存在任何尚未就绪的 Pod,我们可以在不考虑遗漏指标或尚未就绪的 Pod 的情况下进行扩缩, 我们保守地假设尚未就绪的 Pod 消耗了期望指标的 0%,从而进一步降低了扩缩的幅度。

    在扩缩方向(缩小或放大)确定后,我们会把未就绪的 Pod 和缺少指标的 Pod 考虑进来再次计算使用率。 如果新的比率与扩缩方向相反,或者在容忍范围内,则跳过扩缩。 否则,我们使用新的扩缩比例。

    注意,平均利用率的原始值会通过 HorizontalPodAutoscaler 的状态体现( 即使使用了新的使用率,也不考虑未就绪 Pod 和 缺少指标的 Pod)。

    如果创建 HorizontalPodAutoscaler 时指定了多个指标, 那么会按照每个指标分别计算扩缩副本数,取最大值进行扩缩。 如果任何一个指标无法顺利地计算出扩缩副本数(比如,通过 API 获取指标时出错), 并且可获取的指标建议缩容,那么本次扩缩会被跳过。 这表示,如果一个或多个指标给出的 desiredReplicas 值大于当前值,HPA 仍然能实现扩容。

    最后,在 HPA 控制器执行扩缩操作之前,会记录扩缩建议信息。 控制器会在操作时间窗口中考虑所有的建议信息,并从中选择得分最高的建议。 这个值可通过 kube-controller-manager 服务的启动参数 --horizontal-pod-autoscaler-downscale-stabilization 进行配置, 默认值为 5 分钟。 这个配置可以让系统更为平滑地进行缩容操作,从而消除短时间内指标值快速波动产生的影响。

    4、API 对象

    HorizontalPodAutoscaler 是 Kubernetes autoscaling API 组的资源。 在当前稳定版本(autoscaling/v1)中只支持基于 CPU 指标的扩缩。

    API 的 beta 版本(autoscaling/v2beta2)引入了基于内存和自定义指标的扩缩。 在 autoscaling/v2beta2 版本中新引入的字段在 autoscaling/v1 版本中以注解 的形式得以保留。

    5、HPA的部署测试

    5.1部署metrics-server

    官方代码仓库地址:https://github.com/kubernetes-sigs/metrics-server

     

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

    metrics-server.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
      selector:
        k8s-app: metrics-server
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        k8s-app: metrics-server
      name: metrics-server
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          k8s-app: metrics-server
      strategy:
        rollingUpdate:
          maxUnavailable: 0
      template:
        metadata:
          labels:
            k8s-app: metrics-server
        spec:
          containers:
          - args:
            - --cert-dir=/tmp
            - --secure-port=4443
            - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
            - --kubelet-use-node-status-port
            #image: k8s.gcr.io/metrics-server/metrics-server:v0.4.4
            image: harbor.ywx.net/k8s-baseimages/metrics-server:v0.4.4 
            imagePullPolicy: IfNotPresent
            livenessProbe:
              failureThreshold: 3
              httpGet:
                path: /livez
                port: https
                scheme: HTTPS
              periodSeconds: 10
            name: metrics-server
            ports:
            - containerPort: 4443
              name: https
              protocol: TCP
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /readyz
                port: https
                scheme: HTTPS
              periodSeconds: 10
            securityContext:
              readOnlyRootFilesystem: true
              runAsNonRoot: true
              runAsUser: 1000
            volumeMounts:
            - mountPath: /tmp
              name: tmp-dir
          nodeSelector:
            kubernetes.io/os: linux
          priorityClassName: system-cluster-critical
          serviceAccountName: metrics-server
          volumes:
          - emptyDir: {}
            name: tmp-dir
    ---
    apiVersion: apiregistration.k8s.io/v1
    kind: APIService
    metadata:
      labels:
        k8s-app: metrics-server
      name: v1beta1.metrics.k8s.io
    spec:
      group: metrics.k8s.io
      groupPriorityMinimum: 100
      insecureSkipTLSVerify: true
      service:
        name: metrics-server
        namespace: kube-system
      version: v1beta1
      versionPriority: 100

    运行metrics-server.yaml清单

    #运行metrics-server前
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl top nodes
    W1028 22:12:32.344418  107255 top_node.go:119] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
    error: Metrics API not available
    
    
    #运行metrics-server后
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl apply -f metrics-server.yaml 
    serviceaccount/metrics-server created
    clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
    clusterrole.rbac.authorization.k8s.io/system:metrics-server created
    rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
    clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
    clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
    service/metrics-server created
    deployment.apps/metrics-server created
    apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
    
    #使用kubectl top nodes命令可以显示所有节点的CPU和MEM使用状态
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl top nodes
    W1028 22:12:55.126877  107834 top_node.go:119] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
    NAME             CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
    172.168.33.207   310m         31%    1047Mi          81%       
    172.168.33.208   92m          9%     994Mi           77%       
    172.168.33.209   97m          9%     944Mi           73%       
    172.168.33.210   121m         3%     684Mi           21%       
    172.168.33.211   341m         8%     730Mi           22%       
    172.168.33.212   135m         3%     692Mi           21%  

    5.2部署hpa

    注意:Deployment对象必须配置requests的参数,不然无法获取监控数据,也无法通过HPA进行动态伸缩

    nginx-deploy.yaml

    apiVersion: apps/v1
    kind: Deployment #类型为deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 1  #副本数
      selector:    #匹配标签,必须与template中定义的标签一样
        matchLabels:
          app: nginx
      template:    #定义pod模板
        metadata:
          labels:
            app: nginx  #pod的标签与deployment选择的标签一致
        spec: #定义容器
          containers:
          - name: nginx
            image: nginx:1.16.0
            imagePullPolicy: IfNotPresent
            ports:
            - name: http
              containerPort: 80
            #不配置资源限制requests,deployment无法获取监控数据,也无法通过HPA进行动态伸缩
            resources:
                limits:
                  cpu: 1
                  memory: "512Mi"
                requests:
                  cpu: 500m
                  memory: "512Mi"

    运行清单

    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl apply -f nginx-deploy.yaml 
    deployment.apps/nginx-deployment created
    
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl get pods
    NAME                                READY   STATUS        RESTARTS   AGE
    nginx-deployment-777d596565-nnbtb   1/1     Running       0          3s
    
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl get deployments.apps 
    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   1/1     1            1           78s

    5.2.1手动命令部署

    #nginx-deployment副本数,在cpu使用率超过10%时,最多扩大到4个;在cpu使用率不超过10%时,最少保障2个
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl autoscale deployment nginx-deployment --cpu-percent=10 --min=2 --max=4 -n default
    horizontalpodautoscaler.autoscaling/nginx-deployment autoscaled
    
    #部署的期望副本为2个,原deployment为1个,不满足期望副本,会自动增加1个来满足期望值。
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl get pod
    NAME                                READY   STATUS    RESTARTS   AGE
    nginx-deployment-777d596565-j72n9   1/1     Running   0          4s
    nginx-deployment-777d596565-nnbtb   1/1     Running   0          4m55s
    
    #查看deployment的hpa值
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl get hpa nginx-deployment 
    NAME               REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    nginx-deployment   Deployment/nginx-deployment   0%/10%    2         4         2          7m31s
    
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl describe hpa nginx-deployment
    Name:                                                  nginx-deployment
    Namespace:                                             default
    Labels:                                                <none>
    Annotations:                                           <none>
    CreationTimestamp:                                     Thu, 28 Oct 2021 22:38:22 +0800
    Reference:                                             Deployment/nginx-deployment
    Metrics:                                               ( current / target )
      resource cpu on pods  (as a percentage of request):  0% (0) / 10%         
    Min replicas:                                          2
    Max replicas:                                          4
    Deployment pods:                                       2 current / 2 desired
    Conditions:
      Type            Status  Reason               Message
      ----            ------  ------               -------
      AbleToScale     True    ScaleDownStabilized  recent recommendations were higher than current one, applying the highest recent recommendation
      ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
      ScalingLimited  False   DesiredWithinRange   the desired count is within the acceptable range
    Events:           <none>
    
    #current:为当前值
    #target:为配置的目标值

    5.2.2 yaml清单部署

    #apiVersion: autoscaling/v2beta1
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      namespace: default
      name: pha-nginx-deployment
      labels:
        app: hpa-nginx-deployment
        version: v2beta1
    spec:
      #定义deployment/nginx-deployment中部署hpa
      scaleTargetRef:
        apiVersion: apps/v1
        #apiVersion: extensions/v1beta1 
        kind: Deployment
        name: nginx-deployment
      minReplicas: 2  #最少2个副本
      maxReplicas: 20 #最大20个副本
      targetCPUUtilizationPercentage: 60
      #metrics:
      #- type: Resource
      #  resource:
      #    name: cpu
      #    targetAverageUtilization: 60
      #- type: Resource
      #  resource:
      #    name: memory

    运行清单并测试

    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl apply -f hpa-nginx-deployment.yaml 
    horizontalpodautoscaler.autoscaling/pha-nginx-deployment created
    
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl get hpa pha-nginx-deployment 
    NAME                   REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    pha-nginx-deployment   Deployment/nginx-deployment   0%/60%    2         20        2          34s
    
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl get hpa pha-nginx-deployment 
    NAME                   REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    pha-nginx-deployment   Deployment/nginx-deployment   0%/60%    2         20        2          34s
    root@k8s-master01:/apps/k8s-yaml/hpa# kubectl describe hpa pha-nginx-deployment 
    Name:                                                  pha-nginx-deployment
    Namespace:                                             default
    Labels:                                                app=hpa-nginx-deployment
                                                           version=v2beta1
    Annotations:                                           <none>
    CreationTimestamp:                                     Thu, 28 Oct 2021 22:44:27 +0800
    Reference:                                             Deployment/nginx-deployment
    Metrics:                                               ( current / target )
      resource cpu on pods  (as a percentage of request):  0% (0) / 60%
    Min replicas:                                          2
    Max replicas:                                          20
    Deployment pods:                                       2 current / 2 desired
    Conditions:
      Type            Status  Reason               Message
      ----            ------  ------               -------
      AbleToScale     True    ScaleDownStabilized  recent recommendations were higher than current one, applying the highest recent recommendation
      ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
      ScalingLimited  False   DesiredWithinRange   the desired count is within the acceptable range
    Events:           <none>
    I have a dream so I study hard!!!
  • 相关阅读:
    白话机器学习的数学笔记系列1算法回归_一元回归+多项式回归
    使用verdaccio搭建npm私有库 pm2守护进程 nrm管理npm源
    Nginx笔记
    FileSystemResource 和 ClassPathResource 以及 ServletContextResource 获取资源用法
    ClickHouse 使用
    springboot整合nacos项目配置文件
    SpringBoot基础篇Bean之条件注入@ConditionalOnExpression
    java web项目服务端返回json结果时过滤字段为null的属性
    Navicat导出Excel格式表结构
    sql积累
  • 原文地址:https://www.cnblogs.com/yaokaka/p/15478122.html
Copyright © 2011-2022 走看看