HPA - k8s自动伸缩机制

一、HPA是什么

自动缩容扩容

举例:淘宝双11并发量大导致服务挂了,加3台之后恢复运行。双11过后这3台机器就浪费了。

可以在11:50创建一个job一次性计划任务,瞬间创建百台机器,但有延时。

二、部署 HPA

HPA(Horizontal Pod Autoscaling)Pod 水平自动伸缩,Kubernetes 有一个 HPA 的资源,HPA 可以根据 CPU 利用率自动伸缩一个 Replication Controller、Deployment 或者Replica Set 中的 Pod 数量。

metrics-server:收集node、pod资源使用情况的信息

超过阈值,扩容;低于阈值自动缩容

(1)HPA 基于 Master 上的 kube-controller-manager 服务启动参数 horizontal-pod-autoscaler-sync-period 定义的时长(默认为30秒),周期性的检测 Pod 的 CPU 使用率。

(2)HPA 与之前的 RC、Deployment 一样,也属于一种 Kubernetes 资源对象。通过追踪分析 RC 控制的所有目标 Pod 的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理。

(3)metrics-server 也需要部署到集群中, 它可以通过 resource metrics API 对外提供度量数据。

部署 metrics-server

●metrics-server:是kubernetes集群资源使用情况的聚合器,收集数据给kubernetes集群内使用,如kubectl、hpa、scheduler等。

//在所有 Node 节点上传 metrics-server.tar 镜像包到 /opt 目录

cd /opt/

docker load -i metrics-server.tar

//使用 helm install 安装 metrics-server

mkdir /opt/metrics

cd /opt/metrics

helm repo remove stable

helm repo add stable https://charts.helm.sh/stable

helm repo add stable http://mirror.azure.cn/kubernetes/charts

helm repo update

helm pull stable/metrics-server

vim metrics-server.yaml

args:

  • --logtostderr

  • --kubelet-insecure-tls #tls证书

  • --kubelet-preferred-address-types=InternalIP

image:

repository: k8s.gcr.io/metrics-server-amd64

tag: v0.3.2

//使用 helm install 安装 metrics-server

helm install metrics-server stable/metrics-server -n kube-system -f metrics-server.yaml

kubectl get pods -n kube-system | grep metrics-server

#需要多等一会儿

kubectl top node #cup和内存资源

kubectl top pods --all-namespaces #命名空间下pod使用的cpu、内存资源

部署 HPA

//在所有节点上传 hpa-example.tar 镜像文件到 /opt 目录

hpa-example.tar 是谷歌基于 PHP 语言开发的用于测试 HPA 的镜像,其中包含了一些可以运行 CPU 密集计算任务的代码。

cd /opt

docker load -i hpa-example.tar

docker images | grep hpa-example

gcr.io/google_containers/hpa-example latest 4ca4c13a6d7c 5 years ago 481MB

//创建用于测试的 Pod 资源,并设置请求资源为 cpu=200m(豪核)

vim hpa-pod.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

labels:

run: php-apache

name: php-apache

spec:

replicas: 1

selector:

matchLabels:

run: php-apache

template:

metadata:

labels:

run: php-apache

spec:

containers:

name: php-apache

imagePullPolicy: IfNotPresent

ports:

  • containerPort: 80

resources:

requests:

cpu: 200m


apiVersion: v1

kind: Service

metadata:

name: php-apache

spec:

ports:

  • port: 80

protocol: TCP

targetPort: 80

selector:

run: php-apache

kubectl apply -f hpa-pod.yaml

kubectl get pods

NAME READY STATUS RESTARTS AGE

php-apache-799f99c985-5j5b4 1/1 Running 0 26s

//使用 kubectl autoscale 命令创建 HPA 控制器,设置 cpu 负载阈值为请求资源的 50%,指定最少负载节点数量为 1 个,最大负载节点数量为 10 个(超过50%变成10个)

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

//需要等一会儿,才能获取到指标信息 TARGETS(metrics-server收集数据需要时间)

kubectl get hpa

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE

php-apache Deployment/php-apache 0%/50% 1 10 1 8m27s

kubectl top pods

NAME CPU(cores) MEMORY(bytes)

php-apache-799f99c985-5j5b4 0m 11Mi

//创建一个测试客户端容器

kubectl run -it load-generator --image=busybox /bin/sh

//增加负载

while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

//打开一个新的窗口,查看负载节点数目

kubectl get hpa -w

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE

php-apache Deployment/php-apache 39%/50% 1 10 1 13m

php-apache Deployment/php-apache 54%/50% 1 10 1 13m

php-apache Deployment/php-apache 342%/50% 1 10 1 14m

php-apache Deployment/php-apache 315%/50% 1 10 4 14m

php-apache Deployment/php-apache 315%/50% 1 10 7 14m

php-apache Deployment/php-apache 315%/50% 1 10 7 14m

php-apache Deployment/php-apache 68%/50% 1 10 7 15m

php-apache Deployment/php-apache 62%/50% 1 10 7 15m

php-apache Deployment/php-apache 67%/50% 1 10 7 15m

php-apache Deployment/php-apache 67%/50% 1 10 10 15m

php-apache Deployment/php-apache 56%/50% 1 10 10 16m

php-apache Deployment/php-apache 52%/50% 1 10 10 16m

php-apache Deployment/php-apache 45%/50% 1 10 10 16m

php-apache Deployment/php-apache 34%/50% 1 10 10 16m

#以上可以看到经过压测,负载节点数量最大上升到 10 个,并且 cpu 负载也随之下降。

//如果 cpu 性能较好导致负载节点上升不到 10 个,可再创建一个测试客户端同时测试:

kubectl run -i --tty load-generator1 --image=busybox /bin/sh

while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

//查看 Pod 状态,也发现已经创建了 10 个 Pod 资源

kubectl get pods

NAME READY STATUS RESTARTS AGE

load-generator-7d549cd44-xq5rv 1/1 Running 0 6m34s

php-apache-799f99c985-5j5b4 1/1 Running 0 20m

php-apache-799f99c985-6zn9n 1/1 Running 0 3m12s

php-apache-799f99c985-8rnqz 1/1 Running 0 101s

php-apache-799f99c985-lgth4 1/1 Running 0 2m57s

php-apache-799f99c985-nhtzv 1/1 Running 0 101s

php-apache-799f99c985-nssrp 1/1 Running 0 2m57s

php-apache-799f99c985-nx4hn 1/1 Running 0 3m12s

php-apache-799f99c985-p7h4w 1/1 Running 0 2m57s

php-apache-799f99c985-rmb9t 1/1 Running 0 3m12s

php-apache-799f99c985-xwj5p 1/1 Running 0 101s

STATUS 出现 Pending 可能是1、资源不足(内存、cpu);2、node节点问题

#HPA 扩容的时候,负载节点数量上升速度会比较快;但回收的时候,负载节点数量下降速度会比较慢。(类似四次挥手,防止负载点上还有业务正在进行)

原因是防止在业务高峰期时因为网络波动等原因的场景下,如果回收策略比较积极的话,K8S集群可能会认为访问流量变小而快速收缩负载节点数量,而仅剩的负载节点又承受不了高负载的压力导致崩溃,从而影响业务。

三、资源限制 - Pod(cgroup)

Kubernetes对资源的限制实际上是通过cgroup来控制的,cgroup是容器的一组用来控制内核如何运行进程的相关属性集合。针对内存、CPU 和各种设备都有对应的 cgroup。

默认情况下,Pod 运行没有 CPU 和内存的限额。这意味着系统中的任何 Pod 将能够像执行该 Pod 所在的节点一样, 消耗足够多的 CPU 和内存。一般会针对某些应用的 pod 资源进行资源限制,这个资源限制是通过 resources 的 requests 和 limits 来实现。requests 为创建 Pod 时初始要分配的资源,limits 为 Pod 最高请求的资源值。

示例:

spec:

containers:

  • image: xxxx

imagePullPolicy: IfNotPresent

name: auth

ports:

  • containerPort: 8080

protocol: TCP

resources:

limits:

cpu: "2"

memory: 1Gi

requests:

cpu: 250m

memory: 250Mi

//资源限制 - 命名空间

1.计算资源配额

apiVersion: v1

kind: ResourceQuota #使用 ResourceQuota 资源类型

metadata:

name: compute-resources

namespace: spark-cluster #指定命令空间

spec:

hard:

pods: "20" #设置 Pod 数量最大值

requests.cpu: "2"

requests.memory: 1Gi

limits.cpu: "4"

limits.memory: 2Gi

2.配置对象数量配额限制

apiVersion: v1

kind: ResourceQuota

metadata:

name: object-counts

namespace: spark-cluster

spec:

hard:

configmaps: "10"

persistentvolumeclaims: "4" #设置 pvc 数量最大值

replicationcontrollers: "20" #设置 rc 数量最大值

secrets: "10"

services: "10"

services.loadbalancers: "2"

#如果Pod没有设置requests和limits,则会使用当前命名空间的最大资源;如果命名空间也没设置,则会使用集群的最大资源。

K8S 会根据 limits 限制 Pod 使用资源,当内存超过 limits 时 cgruops 会触发 OOM。

这里就需要创建 LimitRange 资源来设置 Pod 或其中的 Container 能够使用资源的最大默认值

apiVersion: v1

kind: LimitRange #使用 LimitRange 资源类型

metadata:

name: mem-limit-range

namespace: test #可以给指定的 namespace 增加一个资源限制

spec:

limits:

  • default: #default 即 limit 的值

memory: 512Mi

cpu: 500m

defaultRequest: #defaultRequest 即 request 的值

memory: 256Mi

cpu: 100m

type: Container #类型支持 Container、Pod、PVC

相关推荐
开挖掘机上班28 分钟前
基于Alpine构建MySQL镜像
mysql·docker·容器
todoitbo1 小时前
docker搭建freeswitch实现点对点视频,多人视频
docker·容器·音视频·freeswitch·视频聊天
William一直在路上2 小时前
回顾一下Docker的基本操作
docker·容器·eureka
阿里云云原生3 小时前
Nacos 开源 MCP Router,加速 MCP 私有化部署
云原生
赵成ccc3 小时前
如何进行 Docker 数据目录迁移
docker·容器·eureka
康闯4 小时前
Docker 部署emberstack/sftp 镜像
java·docker·容器
William一直在路上5 小时前
kube-proxy 中 IPVS 与 iptables
云原生
陈小唬7 小时前
Docker 拉取镜像并离线迁移至云桌面指南(以Redis为例)
redis·docker·容器
探索云原生7 小时前
K8s 自定义调度器 Part1:通过 Scheduler Extender 实现自定义调度逻辑
docker·云原生·容器·kubernetes·go