弹性伸缩是一个比较吸引人的话题,类似与云计算中所提倡的按需付费,合理使用可以减少所需计算资源,降低相关的服务器成本。对于k8s来说目前一共有两种弹性伸缩:
- Cluster 即自动增加删除节点
- Pod 分为水平和垂直两种,水平伸缩在k8s里已经支持,垂直伸缩需要安装
相关repo https://github.com/kubernetes/autoscaler ,下面分别介绍下相关信息。
Node
Cluster-autoscaler
ClusterScaler安装相对来说比较简单,和其他插件类似,定义好ServiceAccount,Deployment以及伸缩组等即可,但是比较强依靠公有云。目前支持的AliCloud,Azure,AWS,BaiduCloud等,注意需要配置Access Key以及根证书(访问API时需要)等信息。关键配置如下:
- ./cluster-autoscaler
- --v=4
- --stderrthreshold=info
- --cloud-provider=aws
- --skip-nodes-with-local-storage=false
- --scale-down-delay-after-add=3m
- --nodes=1:5:nodes.demo.k8s.local
按照正常步骤,向集群添加节点一共需要三步:
- 新开一台机器,
- 配置bootstap token等信息,
- 最后加入集群。
ClusterScaler相当于替我们做了这些工作,仔细阅读相关文档,可以看到阿里云依赖的是ESS,而kops下的aws依赖的是ASG(auto scaling group),通过自动伸缩组可以几乎无干预的完成扩容。
这里穿插一个小知识,对于大多数公有云来说,都支持一个叫做cloud-init的东西,也叫做user data,也就是在机器初始化的时候执行的一段shell脚本,这也就是上面的第二步。
那么它是如何判断集群需要扩容、缩容呢?我们先启动一个request为4C8G的nginx做测试,或者是5个1C2G的nginx,目的就是超过现有集群剩余的计算资源,正常情况下一定会有pod处于pending状态,这时候通过观察日志可以发现,ClusterScaler就会触发扩容节点。
I0408 04:46:52.022024 1 scale_up.go:249] Pod default/demo-589b486fbb-r5fn4 is unschedulable
I0408 04:46:52.022039 1 scale_up.go:249] Pod default/demo-589b486fbb-rzlpn is unschedulable
Pod
HPA 水平伸缩
现在官方支持的就是HorizontalPodAutoscaler,可以根据CPU和memory使用情况来判断伸缩,需要注意的是,伸缩的条件是CPU利用率超过多少就触发扩容,所以至少需要两个参数,pod现在的CPU,以及它request的CPU, 所以我们首先需要部署metric-server,用来获取pod的实时CPU使用情况。 https://github.com/kubernetes-incubator/metrics-server
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/aggregated-metrics-reader.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/auth-delegator.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/auth-reader.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/metrics-apiservice.yaml
# 可以修改下镜像
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/metrics-server-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/metrics-server-service.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-incubator/metrics-server/master/deploy/1.8%2B/resource-reader.yaml
报错一
> unable to fully collect metrics: unable to fully scrape metrics from source kubelet_summary:east1-monitor1: unable to fetch metrics from Kubelet xxx: Get https://xxx1:10250/stats/summary/: dial tcp: lookup xxx on 10.96.0.10:53: no such host
修改Deployment,加上
- args:
- --kubelet-preferred-address-types=InternalIP
- --kubelet-insecure-tls
完成之后执行 kubectl top po
或者kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
命令应该会返回一串json,那就是安装完成了。接下来我们就试着用hpa来实现Pod水平扩容。
首先运行一个nginx的pod
kubectl run nginx --image=nginx:alpine --port=80 --requests='cpu=20m,memory=20m'
接着规定CPU超过80%就扩容,最多为3个
# kubectl autoscale deployment nginx --max=3 --cpu-percent=20
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
creationTimestamp: "2019-05-26T11:09:52Z"
name: nginx
spec:
maxReplicas: 3
minReplicas: 1
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: nginx
targetCPUUtilizationPercentage: 80
status:
currentReplicas: 0
desiredReplicas: 0
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: podinfo
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: podinfo
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 80
- type: Resource
resource:
name: memory
targetAverageValue: 200Mi
然后我们使用工具去压测一下Nginx,这里用的是vegeta
echo "GET http://10.244.0.16" | vegeta attack -rate=1000 -duration=50s | tee results.bin | vegeta report`
# 查看hpa情况。已经严重超过目标值了
kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx Deployment/nginx 1075%/20% 1 3 3 4m52s
# 已经扩容了
kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-584fd85d4-bdvbj 1/1 Running 0 22s
nginx-584fd85d4-hg6hl 1/1 Running 0 22m
nginx-584fd85d4-sntkc 1/1 Running 0 22s
VPA 垂直扩容
TODO
###Custom Metrics自定义指标
metrics在微服务的监控体系运用的可谓是相当广泛,仅依靠Pod的CPU就做扩容可能有些不是很完善,更符合的是依靠服务质量来扩容,比如90%的请求都是5s才返回,于是custom metrics就诞生了,它扩展了新的API Server Groupcustom.metrics.k8s.io
,相关repo: https://github.com/stefanprodan/k8s-prom-hpa,需要注意的是生成证书的环节。
├── cm-adapter-serving-certs.yaml
├── custom-metrics-apiserver-auth-delegator-cluster-role-binding.yaml
├── custom-metrics-apiserver-auth-reader-role-binding.yaml
├── custom-metrics-apiserver-deployment.yaml
├── custom-metrics-apiserver-resource-reader-cluster-role-binding.yaml
├── custom-metrics-apiserver-service-account.yaml
├── custom-metrics-apiserver-service.yaml
├── custom-metrics-apiservice.yaml
├── custom-metrics-cluster-role.yaml
├── custom-metrics-config-map.yaml
├── custom-metrics-resource-reader-cluster-role.yaml
└── hpa-custom-metrics-cluster-role-binding.yaml
如下是一个http_requests 超过10 就扩容的scaler定义,可以使用上面的命令再次压测一下。
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: podinfo
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: podinfo
minReplicas: 2
maxReplicas: 10
metrics:
- type: Pods
pods:
metricName: http_requests
targetAverageValue: 10