k8s中实现pod自动扩缩容「建议收藏」

k8s中实现pod自动扩缩容「建议收藏」如何在k8s中实现基于cpu、内存的pod自动扩缩容来应对非线性资源使用情况,以满足业务需求、节约资源。

大家好,又见面了,我是你们的朋友全栈君。

k8s应用自动扩缩容概述

为什么要自动扩缩容

在实际的业务场景中,我们经常会遇到某个服务需要扩容的场景(例如:测试对服务压测、电商平台秒杀、大促活动、或由于资源紧张、工作负载降低等都需要对服务实例数进行扩缩容操作)。

扩缩容分类

按对象层面

  • node扩缩容
    在使用 kubernetes 集群经常问到的一个问题是,我应该保持多大的节点规模来满足应用需求呢?cluster-autoscaler 的出现解决了这个问题, 可以通过 cluster-autoscaler 实现节点级别的动态添加与删除,动态调整容器资源池,应对峰值流量。

  • pod层面
    我们一般会使用 Deployment 中的 replicas 参数,设置多个副本集来保证服务的高可用,但是这是一个固定的值,比如我们设置 10 个副本,就会启 10 个 pod 同时 running 来提供服务。
    如果这个服务平时流量很少的时候,也是 10 个 pod 同时在 running,而流量突然暴增时,又可能出现 10 个 pod 不够用的情况。针对这种情况怎么办?就需要自动扩缩容。

按方式分类

  • 手动模式::通过 kubectl scale 命令,这样需要每次去手工操作一次,而且不确定什么时候业务请求量就很大了,所以如果不能做到自动化的去扩缩容的话,这也是一个很麻烦的事情。

  • 自动模式
    1、kubernetes HPA(Horizontal Pod Autoscaling):根据监控指标(cpu 使用率、磁盘、自定义的等)自动扩容或缩容服务中的pod数量,当业务需求增加时,系统将无缝地自动增加适量 pod 容器,提高系统稳定性。

    2、kubernetes KPA(Knative Pod Autoscaler):基于请求数对 Pod 自动扩缩容,KPA 的主要限制在于它不支持基于 CPU 的自动扩缩容。

    3、kubernetes VPA(Vertical Pod Autoscaler):基于 Pod 的资源使用情况自动设置 pod 的 CPU 和内存的 requests,从而让集群将 Pod 调度到有足够资源的最佳节点上。

如何实现自动扩缩容

HPA运作方式

  • 整体逻辑:K8s 的 HPA controller 已经实现了一套简单的自动扩缩容逻辑,默认情况下,每 15s 检测一次指标,只要检测到了配置 HPA 的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在 5min 内没有重新扩缩容的情况下,才会触发扩缩容。
  • 缺陷:HPA 本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果正处在 5min 内的 HPA 稳定期,这个时候根据 HPA 的策略,会导致无法扩容。
  • pod数量计算方式:通过现有 pods 的 CPU 使用率的平均值(计算方式是最近的 pod 使用量(最近一分钟的平均值,从 metrics-server 中获得)除以设定的每个 Pod 的 CPU 使用率限额)跟目标使用率进行比较,并且在扩容时,还要遵循预先设定的副本数限制:MinReplicas <= Replicas <= MaxReplicas。
    计算扩容后 Pod 的个数:sum(最近一分钟内某个 Pod 的 CPU 使用率的平均值)/CPU 使用上限的整数+1

指标信息来源

K8S 从 1.8 版本开始,各节点CPU、内存等资源的 metrics 信息可以通过 Metrics API 来获取,用户可以直接获取这些 metrics 信息(例如通过执行 kubect top 命令),HPA 使用这些 metics 信息来实现动态伸缩。

部署HPA实现pod自动扩缩容

基于1.23.1版kubernetes
HPA官网:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/

数据采集组件metrics-server

概述

metrics-server 是一个集群范围内的资源数据集和工具,同样的,metrics-server 也只是显示数据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、请求延时等指标,metric-server 收集数据给 k8s 集群内使用,如 kubectl,hpa,scheduler 等。

github地址:https://github.com/kubernetes-sigs/metrics-server/
不同k8s版本根据官网安装对应版本的metrics-server
在这里插入图片描述

部署

1、镜像下载

所用镜像可提前自行下载:registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.1

2、导入镜像

docker load -i metrics-server-0.6.1.tar.gz

3、修改apiserver配置

注意:会中断业务,生产环境谨慎操作!
这个是 k8s 在 1.17 的新特性,如果是 1.16 版本的可以不用添加,1.17 以后要添加。这个参数的作用是 Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API。

vim /etc/kubernetes/manifests/kube-apiserver.yaml

增加如下内容:

- --enable-aggregator-routing=true

添加后的效果如下图所示:
在这里插入图片描述
修改完成后重启kubelet

systemctl restart kubelet

4、部署metrics-server 服务

kubectl apply -f components.yaml

用到的yaml文件到github下载,地址:https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.1/components.yaml

5、验证metrics-server是否部署成功

kubectl get pods -n kube-system | grep metrics

可以看到pod处于Running状态:
在这里插入图片描述

kubectl top nodes                                               # 查看各节点资源使用情况

在这里插入图片描述

kubectl top pods -n kube-system                                 # 查看kube-system名称空间下pod资源使用情况

在这里插入图片描述

测试环境准备

创建php-apache服务

1、镜像准备

使用 dockerfile 构建一个新的镜像,在 k8s 的 xuegod63 节点构建

mkdir php
cd php
vim dockerfile

dockerfile内容如下:

FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

创建index.php文件,内容如下:

<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000;$i++) { 
   
 $x += sqrt($x);
 }
 echo "OK!";
?>
docker build -t k8s.gcr.io/hpa-example:v1 .                     # 构建镜像
docker save -o hpa-example.tar.gz k8s.gcr.io/hpa-example:v1     # 打包镜像
scp hpa-example.tar.gz xuegod64:/root/                          # 将镜像传到工作节点

在工作节点导入镜像:

docker load -i hpa-example.tar.gz

2、通过 deployment 部署一个 php-apache 服务

cat php-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
    name: php-apache
    labels:
      run: php-apache
spec:
  ports:
  - port: 80
  selector:
   run: php-apache
kubectl apply -f php-apache.yaml                               # 更新资源清单文件
kubectl get pods                                               # 验证 php 是否部署成功

在这里插入图片描述

创建nginx服务

1、通过deployment部署一个nginx服务

cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hpa
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        resources:
          requests:
            cpu: 0.01
            memory: 25Mi
          limits:
            cpu: 0.05
            memory: 60Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080

注意:nginx 的 pod 里需要有如下字段,否则 hpa 会采集不到内存指标

resources:
  requests:
    cpu: 0.01
    memory: 25Mi
  limits:
    cpu: 0.05
    memory: 60Mi

创建资源并查看:

kubectl apply -f nginx.yaml                                    # 更新资源清单
kubectl get pods                                               # 查看pod
kubectl get svc                                                # 查看service

在这里插入图片描述

HPA基于cpu自动扩缩容

php-apache 服务正在运行,使用 kubectl autoscale 创建自动缩放器,实现对 php-apache 这个deployment 创建的 pod 自动扩缩容,下面的命令将会创建一个 HPA,HPA 将会根据 CPU资源指标增加或减少副本数,创建一个可以实现如下目的的 hpa:
(1)让副本数维持在 1-10 个之间(这里副本数指的是通过 deployment 部署的 pod 的副本数)
(2)将所有 Pod 的平均 CPU 使用率维持在 50%(通过 kubectl run 运行的每个 pod 如果是 200毫核,这意味着平均 CPU 利用率为 100 毫核)

创建HPA基于cpu自动扩缩容

创建:

kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10 

查看:

kubectl get hpa

在这里插入图片描述
可以看到cpu目标及当前状态,最大、最小、当前副本数。

压测php-apache服务,看扩容

重新打开一个master节点的终端,进行如下操作:

kubectl run v1 -it --image=busybox --image-pull-policy=IfNotPresent /bin/sh
while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

在原master终端查看hpa情况:

kubectl get hpa
kubectl get pods

在这里插入图片描述
在这里插入图片描述

可以看到平均cpu使用率达到了98%,副本数已经变为5个。
注意:可能需要几分钟来稳定副本数。由于不以任何方式控制负载量,因此最终副本数可能会与此示例不同。

停止对 php-apache 服务压测,看缩容

停止向 php-apache 这个服务发送查询请求,在 busybox 镜像创建容器的终端中,通过 Ctrl+ C 把刚才 while 请求停止,然后,我们将验证结果状态(大约一分钟后):

kubectl get hpa

在这里插入图片描述
可以看到平均cpu使用率降为0%,副本数降为1。

HPA基于内存自动扩缩容

nginx 服务正在运行,使用 kubectl autoscale 创建自动缩放器,实现对 nginx 这个deployment 创建的 pod 自动扩缩容,下面的命令将会创建一个 HPA,HPA 将会根据内存资源指标增加或减少副本数,创建一个可以实现如下目的的 hpa:
(1)让副本数维持在 1-10 个之间(这里副本数指的是通过 deployment 部署的 pod 的副本数)
(2)将所有 Pod 的平均内存使用率维持在 60%

创建HPA基于内存自动扩缩容

hpa-v1.yaml 内容如下:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
    maxReplicas: 10
    minReplicas: 1
    scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: nginx-hpa
    metrics:
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 60
kubectl apply -f hpa-v1.yaml                                  # 更新资源清单
kubectl get hpa nginx-hpa                                     # 查看创建的hpa

在这里插入图片描述
可以看到当前内存使用率、目标内存使用率,最大、最小、当前副本数。

压测nginx服务,看扩容

使用master节点的终端2登录到上面通过 pod 创建的 nginx,并生成一个文件,增加内存

kubectl exec -it nginx-hpa-7f5d6fbfd9-4d95f -- /bin/bash
dd if=/dev/zero of=/tmp/a

使用终端1查看hpa情况:

kubectl get hpa nginx-hpa

在这里插入图片描述
可以看到平均内存使用率达到了238%,,副本数达到了4个。

取消压测,看缩容

到终端2使用 Ctrl + C 中断dd进程,删除/tmp/a这个文件

rm -rf /tmp/a

在终端1查看hpa的情况:

kubectl get hpa nginx-hpa

在这里插入图片描述
可以看到平均内存使用率已经降到5%,副本数也降为1。(需要等几分钟才能看到)

kubernetes cluster-autoscaler概述

什么是 cluster-autoscaler呢?

Cluster Autoscaler (CA)是一个独立程序,是用来弹性伸缩 kubernetes 集群的。它可以自动根据部署应用所请求的资源量来动态的伸缩集群。当集群容量不足时,它会自动去 Cloud Provider (支持GCE、GKE 和 AWS)创建新的 Node,而在 Node 长时间资源利用率很低时自动将其删除以节省开支。

项目地址:https://github.com/kubernetes/autoscaler

Cluster Autoscaler 什么时候伸缩集群?

在以下情况下,集群自动扩容或者缩放:

  • 扩容:由于资源不足,某些 Pod 无法在任何当前节点上进行调度。
  • 缩容: Node 节点资源利用率较低时,且此 node 节点上存在的 pod 都能被重新调度到其他 node节点上运行。

什么时候集群节点不会被 CA 删除?

  • 1、节点上有 pod 被 PodDisruptionBudget 控制器限制。
  • 2、节点上有命名空间是 kube-system 的 pods。
  • 3、节点上的 pod 不是被控制器创建,例如不是被 deployment, replica set, job, stateful set 创建。
  • 4、节点上有 pod 使用了本地存储。
  • 5、节点上 pod 驱逐后无处可去,即没有其他 node 能调度这个 pod。
  • 6、节点有注解:“cluster-autoscaler.kubernetes.io/scale-down-disabled”: “true”(在 CA 1.0.3 或更高版本中受支持)。
 kubectl annotate node <nodename> cluster-autoscaler.kubernetes.io/scale-down-disabled=true

HPA 如何与 Cluster Autoscaler 一起使用?

Horizontal Pod Autoscaler 会根据当前 CPU 负载更改部署或副本集的副本数。如果负载增加,则 HPA 将创建新的副本,集群中可能有足够的空间,也可能没有足够的空间。如果没有足够的资源,CA将尝试启动一些节点,以便 HPA 创建的 Pod 可以运行。如果负载减少,则 HPA 将停止某些副本。结果,某些节点可能变得利用率过低或完全为空,然后 CA 将终止这些不需要的节点。

Cluster Autoscaler 支持那些云厂商?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/160853.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月17日 上午8:46
下一篇 2022年7月17日 上午9:00


相关推荐

  • java 判断一个对象是否为空对象

    java 判断一个对象是否为空对象最近项目中遇到一个问题,在用户没填数据的时候,我们需要接收从前端传过来的对象为null,但是前端说他们一个一个判断特别麻烦,只能传个空对象过来,我第一个想法就是可以通过反射来判断对象是否为空。第一版:User.javapublicclassUser{privateStringusername;privateBooleanactive;priva…

    2022年6月5日
    40
  • Dash + PhpStorm使用教程

    Dash + PhpStorm使用教程nbsp nbsp nbsp Dashformac 是使用与 MacOS 平台的软件编程文档管理工具 可以浏览 API 文档 以及管理代码片段工具 Dash 自带了丰富的 API 文档 涉及各种主流的编程语言和框架 nbsp nbsp nbsp nbsp nbsp Dash 提供的文档查看和代码管理工具 能极大提高程序员开发效率 nbsp nbsp nbsp nbsp nbsp Dash 官网 https kapeli com dash nbsp nbsp nbsp nbsp nbsp Idea 系列的 PhpStorm amp amp am

    2026年3月17日
    1
  • QUIC简单介绍

    QUIC简单介绍

    2021年12月16日
    51
  • 智能算法学习总结

    智能算法学习总结本科的时候学习了智能信息处理这门课程,所使用的教材是《计算智能》张军,詹志辉.计算智能[M].清华大学出版社,2009.11之前回忆了一下一些还有点记忆的算法,写了一点博客如下:1、神经网络的基础知识与简单分类编程https://blog.csdn.net/SweeNeil/article/details/865313842、模糊逻辑基本原理与编程https://…

    2022年6月22日
    24
  • 全国产算力,科大讯飞发布星火X2大模型

    全国产算力,科大讯飞发布星火X2大模型

    2026年3月14日
    3
  • 并发加锁是怎么实现的_JAVA并发编程

    并发加锁是怎么实现的_JAVA并发编程业务锁在处理并发问题时,很多情况下需要用到业务锁来达到按照某个维度同步执行业务块。例子:@Override@Transactional(rollbackFor=Exception.class,noRollbackFor=TerminateException.class)publicApplyDOsubmitApply(ApplyDOapplyDO){…

    2026年2月8日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号