HPA
HPA介绍
HPA:全称Horizontal Pod Autoscaler ,对应中文叫Pod的自动水平伸缩;
- Pod的水平伸缩是水平方向增加/减少Pod的数量;
- Pod的垂直伸缩则是垂直方向上控制Pod的硬件,比如增加/缩减CPU、内存等资源;
- Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。
- Pod 水平自动扩缩特性由 Kubernetes API 资源和控制器实现。资源决定了控制器的行为。
- 控制器会周期性的调整副本控制器或 Deployment 中的副本数量,以使得 Pod 的平均 CPU 利用率与用户所设定的目标值匹配
k8s的HPA一般会根据一个具体的指标来做,比如常见CPU、内存的负载;也可以根据web服务的吞吐量、单位时间内的传输字节数等;另外还可以根据自定义的指标,比如RabbitMQ的队列数量、Webhook等。
HPA原理
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.io、custom.metrics.k8s.io 和 external.metrics.k8s.io)中获取度量值。 metrics.k8s.io API 通常由 Metrics 服务器(需要额外启动)提供。
安装metrics-server
官方代码仓库地址:https://github.com/kubernetes-sigs/metrics-server
下载yaml
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml
修改arg:
添加- --kubelet-insecure-tls
kubelet 的10250端口使用的是https协议,连接需要验证tls证书,--kubelet-insecure-tls不验证客户端证书。
修改镜像地址:
registry.k8s.io/metrics-server/metrics-server:v0.6.3
修改为
docker.io/dyrnq/metrics-server:v0.6.3
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls
image: docker.io/dyrnq/metrics-server:v0.6.3
imagePullPolicy: IfNotPresent
安装
[root@master hpa]# kubectl apply -f components.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
[root@master hpa]# kubectl get pods -n kube-system |grep metrics-server
metrics-server-7b8f8cb648-pkbpt 1/1 Running 0 2m8s
[root@master hpa]# kubectl top nodes
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 94m 4% 849Mi 45%
node1 45m 2% 398Mi 21%
node2 39m 1% 398Mi 21%
HPA API对象
[root@master hpa]# kubectl api-versions | grep autoscal
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
API名称 | 描述 |
---|---|
autoscaling/v1 | 只支持基于CPU指标的缩放 |
autoscaling/v2beta1 | 支持Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)的缩放 |
autoscaling/v2beta2 | 支持Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)和ExternalMetrics(额外指标)的缩放 |
HPA 案例演示
基于cpu测试
https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
创建测试镜像
[root@master hpa-example]# cat index.php
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
$x += sqrt($x);
}
echo "OK!";
?>
[root@master hpa-example]# cat Dockerfile
FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php
[root@master hpa-example]# docker build -f Dockerfile -t 10.0.0.80:5000/hpa-example:v1 .
[root@master hpa-example]# docker push 10.0.0.80:5000/hpa-example:v1
部署deployment
[root@master1 ~]# vim php-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
app: php-apache
replicas: 1
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: php-apache
image: 10.0.0.80:5000/hpa-example:v1
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
[root@master hpa-example]# kubectl create -f php-apache.yaml
deployment.apps/php-apache created
[root@master hpa-example]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 1/1 1 1 47s
[root@master hpa-example]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
php-apache-fc47b9cd7-khgvt 1/1 Running 0 22m 10.244.1.33 node1 <none> <none>
创建HPA
方式一:文件创建
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 3
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 50
maxReplicas:pod的最大个数
minReplicas:pod的最少个数
scaleTargetRef:目标作用对象,可以是Deployment、ReplicationController或ReplicaSet。
targetCPUUtilizationPercentage:表示所有Pod的平均CPU使用率维持在50%,超过就要扩容
方式二:命令行创建
[root@master hpa-example]# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=3
[root@master hpa-example]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 3 1 39s
压测
对pod发起请求
while true; do wget -q -O- http://10.244.1.33; done
查看hpa和deploy
[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 250%/50% 1 3 3 7m31s
[root@master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 3/3 3 3 24m
停止压测后,等几分钟后查看hpa和deploy
[root@master hpa]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 3 1 19m
[root@master hpa]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 1/1 1 1 36m
基于内存测试
部署deployment
[root@master hpa]# vim nginx-hpa.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hpa
spec:
selector:
matchLabels:
app: nginx-hpa
replicas: 1
template:
metadata:
labels:
app: nginx-hpa
spec:
containers:
- name: nginx
image: nginx:1.15-alpine
ports:
- containerPort: 80
name: http
protocol: TCP
resources:
requests:
cpu: 0.01
memory: 25Mi
limits:
cpu: 0.05
memory: 60Mi
[root@master hpa]# kubectl create -f nginx-hpa.yaml
deployment.apps/nginx-hpa created
[root@master hpa]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-hpa 1/1 1 1 37s
php-apache 1/1 1 1 33m
[root@master hpa]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-hpa-b9fb96f5c-qw8sb 1/1 Running 0 63s 10.244.1.36 node1 <none> <none>
php-apache-fc47b9cd7-khgvt 1/1 Running 0 33m 10.244.1.33 node1 <none> <none>
创建HPA
[root@master hpa]# vim hpa-mem.yaml
apiVersion: autoscaling/v2beta1 # v2beta1版本
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
maxReplicas: 3
minReplicas: 1 # 1-3个pod范围内扩容与裁剪
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-hpa
metrics:
- type: Resource
resource:
name: memory
targetAverageUtilization: 50 # 50%内存利用
[root@master hpa]# kubectl create -f hpa-mem.yaml
horizontalpodautoscaler.autoscaling/nginx-hpa created
[root@master hpa]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 12%/50% 1 3 1 95s
php-apache Deployment/php-apache 0%/50% 1 3 1 19m
压测
进入pod使用dd命令测试
[root@master hpa]# kubectl exec -it nginx-hpa-b9fb96f5c-qw8sb /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # dd if=/dev/zero of=/tmp/file1
查看hpa和deploy
[root@master hpa-example]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 63%/50% 1 3 3 12m
php-apache Deployment/php-apache 0%/50% 1 3 1 30m
[root@master hpa-example]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-hpa 3/3 3 3 14m
php-apache 1/1 1 1 46m
停止压测后,等几分钟后查看hpa和deploy
[root@master hpa-example]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-hpa 1/1 1 1 16m
php-apache 1/1 1 1 48m
[root@master hpa-example]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 12%/50% 1 3 1 14m
php-apache Deployment/php-apache 0%/50% 1 3 1 32m