在之前的文章 Depolyment中提到的伸缩 ,是通过 Deployment 管理的 ReplicaSet 来手动控制 pod 的伸缩,而在刚接触 Kubernetes 时,就一直听到或者看到各种视频文章教程,都说K8S可以通过对资源利用率的判断,进行 pod 的自动伸缩。本文中,它来了。
HPA,全称是 Horizontal Pod Autoscaling
,简称HPA自动水平伸缩,它可以根据 cpu/qps/vpa 等指标进行伸缩。
应用场景:如业务的流量高峰和低峰,不管是物理服务器还是 pod,都不能为了高峰一直保持着资源的高利用,着实有点浪费资源
以常用的 cpu 为伸缩指标,HPA 依赖 metrics-server
服务 pod 用来资源指标收集。另外 kubectl top
命令也依赖于 metrics-server
,仅支持查看 node 和 pod 的资源利用率
Metrics Server 是一个集群范围的资源使用情况的数据聚合器。作为一个应用部署在集群中。Metrics Server 从每个节点的 kubelet API 收集指标,通过 Kubernetes 聚合器注册在 Master API Server 中。
部署metrics-server
修改apiserver配置参数
$ vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
spec:
containers:
- command:
...
- --enable-aggregator-routing=true
下载 metrics-server
的yaml文件并部署
$ wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.4/components.yaml
# 需要修改该文件的两个值,找到Deployment部分的yaml配置
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
# 如果旧版中以下三行都没有,手动添加1/3即可,
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname # 这里改为InternalIP,使用节点ip访问kubelet
# 默认使用的Hostname,没有解析则访问不到,也不会部署成功
- --kubelet-use-node-status-port
- --kubelet-insecure-tls # 添加该行,跳过tls的验证
# 国内用户修改镜像为以下
image: bitnami/metrics-server:0.4.4
$ kubectl apply -f components.yaml
此时可以根据以下确认 metrics-server
部署成功
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
...
kube-system metrics-server-6fb5c69669-t6p2f 1/1 Running 0 8m10s
$ kubectl get apiservices
NAME SERVICE AVAILABLE AGE
...
v1beta1.metrics.k8s.io kube-system/metrics-server True 7m47s
...
查看资源
查看节点资源利用率
$ kubectl top nodes
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
feiyi 640m 0% 6147Mi 2%
查看pod资源利用率
$ kubectl top pods -A
NAMESPACE NAME CPU(cores) MEMORY(bytes)
calico-system calico-kube-controllers-867fdc777c-rvkfx 3m 36Mi
calico-system calico-node-kqs8s 106m 177Mi
calico-system calico-typha-79fbf7798f-flqm6 3m 46Mi
kube-system coredns-558bd4d5db-pxlh9 5m 27Mi
kube-system coredns-558bd4d5db-qlsnw 6m 29Mi
kube-system etcd-feiyi 34m 318Mi
kube-system kube-apiserver-feiyi 97m 445Mi
kube-system kube-controller-manager-feiyi 27m 73Mi
kube-system kube-proxy-z5qns 18m 33Mi
kube-system kube-scheduler-feiyi 6m 29Mi
kube-system metrics-server-6fb5c69669-t6p2f 5m 28Mi
自动伸缩
正如文章开头所说,自动伸缩需要有事件去触发伸缩。这里的事件也是上面提到的 cpu/qps/vpa 等指标,当这些指标到达一定的峰值,触发自动伸缩,这里以 cpu 为例
先来创建一个 nginx 的 deployment
# 这是我自己练习时写的一个yaml,里面包含了namespace/configmap/deployment/service
# service使用nodeport,端口号为30000,如果冲突,自行修改
wget https://www.feiyiblog.com/files/practise/nginx.yaml
kubectl apply -f nginx.yaml
查看部署好的资源
$ kubectl get pods -n nginx
NAME READY STATUS RESTARTS AGE
nginx-deployment-54b69b44b5-r7vsw 1/1 Running 0 7s
nginx-deployment-54b69b44b5-x9chf 1/1 Running 0 7s
[root@feiyi nginx]# kubectl get all -n nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-54b69b44b5-r7vsw 1/1 Running 0 44s
pod/nginx-deployment-54b69b44b5-x9chf 1/1 Running 0 44s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-svc NodePort 10.103.255.125 <none> 8080:30000/TCP 44s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 44s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-54b69b44b5 2 2 2 44s
访问 nodeip:nodeport
页面如下
对刚才创建的nginx进行自动伸缩的设置
kubectl autoscale deployment -n nginx nginx-deployment --min=2 --max=10 --cpu-percent=10
# --max: 当达到扩展规则,需要进行扩展时,按照该参数给出的值进行伸展pod
# --min: 当低于扩展规则,则会自动进行缩小pod,直到缩小到该参数的值为止
# --cpu-percent: 改参数的值默认为百分比,当pod cpu的使用率达到该值,则进行扩展,生产一半为60-80,这里就以10%为例测试
查看创建好的 hpa
$ kubectl get hpa -n nginx
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-deployment Deployment/nginx-deployment <unknown>/10% 2 10 0 7s
可以看到 TARGETS
的值中有 <unknown>
,这是因为在创建的 nginx pod 中没有添加资源限制的参数,这是必须的,否则默认 pod 使用宿主机的 cpu 配置,那将是很大的
# 修改nginx.yaml中deployment的containers部分,添加资源限制
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: "0.5"
重新加载配置
kubectl apply -f nginx.yaml
再次查看hpa:这里需要等个一两分钟来获取指标
$ kubectl get hpa -n nginx
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-deployment Deployment/nginx-deployment 0%/10% 2 10 2 2m54s
接下来人为手动的给该pod增加cpu使用压力
# 安装压测工具abyum -y install httpd-tools
使用ab工具对svc暴露的 nodeip:nodeport
或者 clusterip:port
端口压测
ab -n 100000 -c 10000 http://172.16.182.193:30000/index.html
# -n: 请求数
# -c: 并发量
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 172.16.182.193 (be patient)
socket: Too many open files (24)
这里报错了 socket: Too many open files (24)
,这是因为有文件打开数的限制,默认是1024,使用命令 ulimit -n
查看,将限制提高到最大65536
# 临时
ulimit -SHn 65536
# 永久,需重启
echo "* soft nofile 65536" >>/etc/security/limits.conf
echo "* hard nofile 65536" >>/etc/security/limits.conf
重新压测
# 1-2分钟内可以看到 hpa 中 replicas 的值伸展到了8
$ kubectl get hpa -n nginx
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-deployment Deployment/nginx-deployment 40%/10% 2 10 8 9m48s
# pod数量也增长到了8
$ kubectl get pods -n nginx
NAME READY STATUS RESTARTS AGE
nginx-deployment-75cb949d68-4gh46 1/1 Running 0 9m10s
nginx-deployment-75cb949d68-8442x 1/1 Running 0 24s
nginx-deployment-75cb949d68-qdh75 1/1 Running 0 24s
nginx-deployment-75cb949d68-qks2d 1/1 Running 0 24s
nginx-deployment-75cb949d68-qvd65 1/1 Running 0 39s
nginx-deployment-75cb949d68-rfnnl 1/1 Running 0 9m12s
nginx-deployment-75cb949d68-vd79j 1/1 Running 0 39s
nginx-deployment-75cb949d68-xcsch 1/1 Running 0 24s
压测结束过一段时间cpu压力减小后,会自动缩容,这个时间有点慢,实验环境用了5-10分钟
$ kubectl get hpa -n nginx
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-deployment Deployment/nginx-deployment 0%/10% 2 10 2 15m