在生产环境中总会遇到高并发的场景,故在kubernetes中有一种Pod 水平自动扩缩策略,故整理相关文件汇总此博文!
Horizontal Pod Autoscaler(HPA,Pod水平自动伸缩)是根据资源利用率或者自定义指标自动调整replication controller, Deployment 或 ReplicaSet,实现部署的水平自动扩缩容,让部署的规模接近于实际服务的负载。如果是DaemonSet这种无法缩放的对象,他是不支持的。
官网地址
流程图地址
K8s中的MetricsServer会持续采集Pod的指标数据,HPA 控制器通过 Metrics Server 的 API(Heapster 的 API 或聚合 API)获取这些数据,基于用户定义的扩缩容规则进行计算,得到目标 Pod 副本数量。当目标 Pod 副本数量与当前副本数量不同时,HPA 控制器就向 Pod 的副本控制器(Deployment、RC 或 ReplicaSet)发起 scale 操作,然后副本控制器会调整 Pod 的副本数量,完成扩缩容操作。
kubernetes 弹性伸缩布局在 Kubernetes 的生态中,在多个维度、多个层次提供了不同的组件来满足不同的伸缩场景
1 有三种弹性伸缩:
(1) CA(Cluster Autoscaler): Node级别自动扩/缩容cluster-autoscaler组件。
(2) HPA(Horizontal Pod Autoscaler): Pod个数自动扩/缩容。
(3) VPA(Vertical Pod Autoscaler): Pod配置自动扩/缩容,主要是CPU、内存。addon-resizer组件
如果在云上建议 HPA 结合 cluster-autoscaler 的方式进行集群的弹性伸缩管理。
2 在Kubernetes平台中,资源分为两个维度
(1) Node级别:K8s将多台服务器抽象一个集群资源池,每个Node提供这些资源
(2) Pod级别: Pod是K8s最小部署单元,运行实际的应用程序,使用request和limit为Pod配额
因此,K8s实现弹性伸缩也是这两个级别,当Node资源充裕情况下,Pod可任意弹性,当不足情况下需要弹性增加节点来扩容资源池。
(3) 针对Pod负载: 当Pod资源不足时,使用HPA(Horizontal Pod Autoscaler)自动增加Pod副本数量
(4) 针对Node负载:当集群资源池不足时,使用CA(Cluster Autoscaler)自动增加Node
3 Node弹性伸缩有两种方案
(1) Cluster Autoscaler:是一个自动调整Kubernetes集群大小的组件,需要与公有云一起使用,例如AWS、Azure、Aliyun
项目地址:https://github.com/kubernetes/autoscaler
(2) 自研发:根据Node监控指标或者Pod调度状态判断是否增加Node,需要一定开发成本
在弹性伸缩中,冷却周期是不能逃避的一个话题, 由于评估的度量标准是动态特性,副本的数量可能会不断波动。有时被称为颠簸, 所以在每次做出扩容缩容后,冷却时间是多少。在 HPA 中,默认的扩容冷却周期是 3 分钟,缩容冷却周期是 5 分钟。
可以通过调整 kube-controller-manager 组件启动参数设置冷却时间。
--horizontal-pod-autoscaler-downscale-delay // 扩容冷却 --horizontal-pod-autoscaler-upscale-delay // 缩容冷却算法细节
从最基本的角度来看,Pod 水平自动扩缩控制器根据当前指标和期望指标来计算扩缩比例。
期望副本数 = ceil [当前副本数 * (当前指标 / 期望指标)]
例如,如果当前指标值为 200m,而期望值为 100m,则副本数将加倍, 因为 200.0 / 100.0 == 2.0 如果当前值为 50m,则副本数将减半, 因为 50.0 / 100.0 == 0.5。如果比率足够接近 1.0(在全局可配置的容差范围内,默认为 0.1), 则控制平面会跳过扩缩操作。
如果 HorizontalPodAutoscaler 指定的是 targetAverageValue 或 targetAverageUtilization, 那么将会把指定 Pod 度量值的平均值做为 currentMetricValue。更多内容请参考https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/官网链接!
Metrics Server 核心监视数据的聚合器(从kubelet收集到目标资源的指标,并通过Metrics API在kube API Server当中提供资源)
API 通过API Server对外暴露Pod的资源使用情况
Server 如何读取资源数据,存储在etcd当中(临时性)
功能:基于kubelet集群的CPU、内存的水平自动伸缩,可以支持多达5000个节点运算。Metrics Server在每个资源节点上占用0.5的cpu和4M的内存
maxReplicas: 是autoscaler可以扩展到的副本数的上限。
minReplicas: 是自动缩放程序将复制到的副本数的下限,默认是1
scaleTargetRef: 需要动态伸缩的scale所在的K8S资源。
metrics: 指动态伸缩的控制指标
有以下几种类型
★resource:指的是当前伸缩对象下的pod的指标。target.type只支持Utilization和AverageValue类型的阈值
★containerResource:指的是当前伸缩对象下的container的cpu和memory指标,只支持Utilization和AverageValue类型的阈值
★pods: 指的是伸缩对象Pods的指标,数据需要第三方的adapter提供,只允许AverageValue类型的阈值
★external:指的是k8s外部的指标,数据同样需要第三方的adapter提供。只支持Value和AverageValue类型的阈值
★object: 指的是指定k8s内部对象的指标,数据需要第三方adapter提供,例如Ingress。只支持Value和AverageValue类型的阈值
metrics的目标值有以下几类
★averageUtilization: 当整体的资源利用率超过这个百分比的时候,会进行扩容
★averageValue: 当指标的平均值或资源的平均利用率超过这个的时候,会进行扩容
★Value: 当指标的值超过这个的时候,会进行扩容
pods、external、object支持使用筛选器进行筛选,允许进行条件选择。
★behavior 用来精确控制HPA的扩容和缩容的速度
behavior中包括:scaleDown:(缩容速度策略)和scaleUp(扩容速度策略)
[root@server1 ~]# kubectl top node W1112 16:17:15.201270 83935 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部署HPA 1.三台安装Metrics Server
[root@server1 ~]# wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.4/components.yaml [root@server1 ~]# vim components.yaml //查看下载的镜像(因为默认下载Google镜像下载不下来,所以需要换镜像) 136 image: k8s.gcr.io/metrics-server/metrics-server:v0.4.4 137 imagePullPolicy: IfNotPresent [root@server1 ~]# docker search metrics-server NAME DESCRIPTION STARS willdockerhub/metrics-server sync from k8s.gcr.io/metrics-server/metrics-… 0 [root@server1 ~]# docker pull willdockerhub/metrics-server:v0.4.4 [root@server1 ~]# docker tag willdockerhub/metrics-server:v0.4.4 k8s.gcr.io/metrics-server/metrics-server:v0.4.4 [root@server1 ~]# docker rmi willdockerhub/metrics-server:v0.4.4
Server2+Server3
docker pull willdockerhub/metrics-server:v0.4.4 docker tag willdockerhub/metrics-server:v0.4.4 k8s.gcr.io/metrics-server/metrics-server:v0.4.4 docker rmi willdockerhub/metrics-server:v0.4.4
不要进行加密操作,密码验证
[root@server1 ~]# vim components.yaml 135 - --kubelet-use-node-status-port 136 - --kubelet-insecure-tls #不使用加密的方式去登录 [root@server1 ~]# kubectl apply -f components.yaml [root@server1 ~]# kubectl top node W1115 11:14:21.667735 25180 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% server1 159m 7% 1232Mi 33% server2 35m 1% 619Mi 36% server3 49m 2% 590Mi 34% [root@server1 ~]# kubectl get pod --all-namespaces [root@server1 ~]# kubectl get apiservices | grep metrics-server v1beta1.metrics.k8s.io kube-system/metrics-server True 2m2s [root@server1 ~]# kubectl top 显示资源(CPU/内存)使用情况 top命令允许您查看节点或pods的资源消耗情况 . This command requires Metrics Server to be correctly configured and working on the server. Available Commands: node 显示 nodes 的 Resource (CPU/Memory) 使用 pod 显示 pods 的 Resource (CPU/Memory) 使用 [root@server1 ~]# kubectl -n kube-system top pod //可以查看到资源使用情况2.构建镜像并制作访问页面
[root@server1 ~]# vim index.php
$x += sqrt($x); #自增
}
echo "ok!" #每次自增输出一句话(不换行)
?>
[root@server1 ~]# vim Dockerfile
FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php #让他拥有执行权限
[root@server1 ~]# docker build -t hpa-test .
[root@server1 ~]# docker save -o hpa.tar hpa-test:latest
[root@server1 ~]# scp hpa.tar server2:/root
[root@server1 ~]# scp hpa.tar server3:/root
[root@server2 ~]# docker load -i hpa.tar
[root@server3 ~]# docker load -i hpa.tar
3.部署deployment服务并把它暴露出一个端口
[root@server1 ~]# vim test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1 #最好在使用HPA时不要设置副本(默认为1)
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: hpa-test:latest
imagePullPolicy: IfNotPresent #使用刚才构建的本地镜像
ports:
- containerPort: 80
resources: #请求的资源
limits: #硬限制
cpu: 500m #限制CPU最大使用CPU的50%
memory: 20Mi#1Mi = 1024*1024*1000m=1048576000m
requests: #软限制
cpu: 200m #最少使用CPU的20%才能部署数据
#向客户端申请的时候,客户端的cpu一定要大于500
#请求上限为50%,下限为20%
#在客户端请求的时候,客户端的电脑有20%cpu剩余,才可以申请成功
#{如果一个容器只指明limit而未设定request,则request的值等于limit值。requests申请范围是0到node节点的最大配置,而limits申请范围是requests到无限,即0 <= requests <= Node Allocatable, requests <= limits <= Infinity。CPU超过limits时,pod不会被kill,只会被限制。但是内存超过时,就会被kernel视为内存溢出(OOM)kill掉}
---
#暴露
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
[root@server1 ~]# kubectl apply -f test.yml
[root@server1 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
php-apache-57fbcf8788-zdrk8 1/1 Running 0 22s 10.244.1.2 server3
[root@server1 ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 6d16h
php-apache ClusterIP 10.108.99.242 80/TCP 57s
[root@server1 ~]# curl 10.108.99.242
ok!
4.自动伸缩
与每个 API 资源一样,HorizontalPodAutoscaler 都被 kubectl 以标准方式支持。 你可以使用 kubectl create 命令创建一个新的自动扩缩器。 你可以通过 kubectl get hpa 列出自动扩缩器或通过 kubectl describe hpa 获取详细描述。 最后你可以使用 kubectl delete hpa 删除自动扩缩器。
此外,还有一个特殊的 kubectl autoscale 命令用于创建 HorizontalPodAutoscaler 对象。 例如,执行 kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80 将为 ReplicaSet foo 创建一个自动扩缩器,目标 CPU 利用率设置为 80%,副本数在 2 到 5 之间。
[root@server1 ~]# kubectl autoscale deployment php-apache --max=10 --min=1 --cpu-percent=50 --max:最大10个容器 --min:最小1个容器 --cpu-percent:HPA的Cpu百分比50%没有人去访问就是0%
[root@server1 ~]# kubectl get hpa NAME REFERENCE 目标 MINPODS MAXPODS REPLICAS(副本) AGE php-apache Deployment/php-apache 0%/50% 1 10 1 73s [root@server1 ~]# kubectl describe hpa php-apache Name: php-apache Namespace: default Reference: Deployment/php-apache Metrics: ( current / target ) resource cpu on pods (as a percentage of request): 0% (1m) / 50% Min replicas: 1 Max replicas: 10 Deployment pods: 1 current / 1 desired(预期的) Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ScaleDownStabilized 最近的推荐值高于当前的推荐值,采用的是最近最高的推荐值 ScalingActive True ValidMetricFound HPA能够从cpu资源利用率成功计算副本计数(请求的比例) ScalingLimited False DesiredWithinRange 所需计数在可接受范围内发起访问,访问的是service的域名
[root@server1 ~]# kubectl run -i -t load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done" 当cpu上去的时候,就会增加容器 [root@server1 ~]# kubectl get pod -o wide -w //最多十个容器(需要另开终端) [root@server1 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE load-generator 1/1 Running 0 81s 10.244.1.4 server3 php-apache-57fbcf8788-jt6jt 1/1 Running 0 25s 10.244.2.3 server2 php-apache-57fbcf8788-mwkxt 1/1 Running 0 25s 10.244.1.5 server3 php-apache-57fbcf8788-qpwhp 1/1 Running 0 25s 10.244.2.4 server2 php-apache-57fbcf8788-zdrk8 1/1 Running 0 17m 10.244.1.2 server3 [root@server1 ~]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 188%/50% 1 10 4 10m打断的时候就会自动减少回原来的
[root@server1 ~]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 0%/50% 1 10 1 17m [root@server1 ~]# kubectl get pod -o wide //需要等待好长时间 [root@server1 ~]# kubectl describe hpa php-apache NAME READY STATUS RESTARTS AGE IP NODE php-apache-57fbcf8788-jt6jt 1/1 Running 0 8m11s 10.244.2.3 server2 Type Reason Age From Message Normal SuccessfulRescale 10m horizontal-pod-autoscaler 新的大小: 4; 原因: CPU资源利用率(请求百分比)高于目标 Normal SuccessfulRescale 4m50s horizontal-pod-autoscaler New size: 3; reason: 所有指标低于目标 Normal SuccessfulRescale 3m50s horizontal-pod-autoscaler New size: 1; reason: All metrics below target工作流程图 伸缩原理 Node 自动扩容/缩容
扩容:Cluster AutoScaler 定期检测是否有充足的资源来调度新创建的 Pod,当资源不足时会调用 Cloud Provider 创建新的 Node。
缩容:Cluster AutoScaler 也会定期监测 Node 的资源使用情况,当一个 Node 长时间资源利用率都很低时(低于 50%)自动将其所在虚拟机从云服务商中删除。此时,原来的 Pod 会自动调度到其他 Node 上面。
(1) 资源指标工作流程: hpa -> apiserver -> kube aggregation -> metrics-server -> kubelet(cadvisor)
(2) 自定义资源指标工作流程: hpa -> apiserver -> kube aggregation -> prometheus-adapter -> prometheus -> pods



