hpa
云计算具有水平弹性的特性,这个是云计算区别于传统IT技术架构的主要特性。对于Kubernetes中的POD集群来说,HPA就是实现这种水平伸缩的控制器, 它能在当POD中业务负载上升的时候,创建新的POD来保证业务系统稳定运行,当POD中业务负载下降的时候,可以销毁POD来提高资源利用率。
HPA介绍
Horizontal Pod Autoscaling,简称HPA,是Kubernetes中实现POD水平自动伸缩的功能。为什么要水平而不叫垂直, 那是因为自动扩展主要分为两种:
- 水平扩展(scale out),针对于实例数目的增减
- 垂直扩展(scal up),即单个实例可以使用的资源的增减, 比如增加cpu和增大内存
而HPA属于前者。它可以根据CPU使用率或应用自定义
metrics
自动扩展Pod数量(支持 replication controller、deployment 和 replica set)
架构介绍
获取metrics的两种方式:
- Heapster: heapster提供metrics服务, 但是在v1(autoscaling/v1)版本中仅支持以CPU作为扩展度量指标, 而其他比如:内存, 网络流量, qps等目前处于beta阶段(autoscaling/v2beta1)
- Cousom: 同样处于beta阶段(autoscaling/v2beta1), 但是涉及到自定义的REST API的开发, 复杂度会大一些, 并且当需要从自定义的监控中获取数据时,只能设置绝对值,无法设置使用率
工作流程:
- 1.创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数, 一定要设置Pod的资源限制参数: request, 负责HPA不会工作。
- 2.控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询
metrics
的资源使用情况 - 3.然后与创建时设定的值和指标做对比(平均值之和/限额),求出目标调整的实例个数
- 4.目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数
- 重复2-4步
自动伸缩算法:
HPA Controller会通过调整副本数量使得CPU使用率尽量向期望值靠近,而且不是完全相等.另外,官方考虑到自动扩展的决策可能需要一段时间才会生效:例如当pod所需要的CPU负荷过大,从而在创建一个新pod的过程中,系统的CPU使用量可能会同样在有一个攀升的过程。所以,在每一次作出决策后的一段时间内,将不再进行扩展决策。对于扩容而言,这个时间段为3分钟,缩容为5分钟(可以通过--horizontal-pod-autoscaler-downscale-delay
, --horizontal-pod-autoscaler-upscale-delay
进行调整)。
- HPA Controller中有一个tolerance(容忍力)的概念,它允许一定范围内的使用量的不稳定,现在默认为0.1,这也是出于维护系统稳定性的考虑。例如,设定HPA调度策略为cpu使用率高于50%触发扩容,那么只有当使用率大于55%或者小于45%才会触发伸缩活动,HPA会尽力把Pod的使用率控制在这个范围之间。
- 具体的每次扩容或者缩容的多少Pod的算法为: Ceil(前采集到的使用率 / 用户自定义的使用率) * Pod数量)
- 每次最大扩容pod数量不会超过当前副本数量的2倍
依赖部署
这是kuberntes整个系列的第四篇, 该篇依赖Heapster服务成功安装, 如果未安装请参考:
- 企业级Docker镜像仓库harbor的部署和使用
- kubernetes 1.8.7 离线部署手册(一)
- kubernetes 1.8.7 离线部署手册(二)
因为基于HeapsterHPA仅支持CPU为维度的自动伸缩, 因此写了个计算100位π的HTTP服务, 该程序已打包放于百度网盘下, 下载hpa-test-app.tar 导入然后推到自己私有仓库, 等待后续测试(放心该镜像仅有5M多点)
源代码如下:
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"strings"
)
func main() {
http.HandleFunc("/", compPiHandler)
log.Println("Server work at :8080 ...")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func compPiHandler(w http.ResponseWriter, r *http.Request) {
var (
lenI int
err error
)
lenS := r.URL.Query().Get("length")
if lenS != "" {
lenI, err = strconv.Atoi(lenS)
if err != nil {
lenI = 100
}
} else {
lenI = 100
}
fmt.Fprintf(w, compPi(lenI))
}
func compPi(L int) string {
var Pi []string
N := (L)/4 + 1
s := make([]int, N+3)
w := make([]int, N+3)
v := make([]int, N+3)
q := make([]int, N+3)
n := (int)(float32(L)/1.39793 + 1)
w[0] = 16 * 5
v[0] = 4 * 239
for k := 1; k <= n; k++ {
p(w, 25, w, N)
p(v, 57121, v, N)
sub(w, v, q, N)
p(q, 2*k-1, q, N)
if k%2 != 0 {
add(s, q, s, N)
} else {
sub(s, q, s, N)
}
}
Pi = append(Pi, fmt.Sprintf("%d.", s[0]))
for k := 1; k < N; k++ {
Pi = append(Pi, fmt.Sprintf("%04d", s[k]))
}
return strings.Join(Pi, "")
}
func add(a []int, b []int, c []int, N int) {
i, carry := 0, 0
for i = N + 1; i >= 0; i-- {
c[i] = a[i] + b[i] + carry
if c[i] < 10000 {
carry = 0
} else {
c[i] = c[i] - 10000
carry = 1
}
}
}
func sub(a []int, b []int, c []int, N int) {
i, borrow := 0, 0
for i = N + 1; i >= 0; i-- {
c[i] = a[i] - b[i] - borrow
if c[i] >= 0 {
borrow = 0
} else {
c[i] = c[i] + 10000
borrow = 1
}
}
}
func p(a []int, b int, c []int, N int) {
i, tmp, remain := 0, 0, 0
for i = 0; i <= N+1; i++ {
tmp = a[i] + remain
c[i] = tmp / b
remain = (tmp % b) * 10000
}
}
服务测试
基于上面提供的hpa-test-app镜像, 我们创建一个hpa-test-app service, 然后为该service添加HPA机制。
注意事项:
- 当Pod没有设置request时,HPA不会工作。
创建Deployment
注意根据需要修改自己的镜像地址
cat << EOF > hpa-test-app-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hpa-test-app-deploy
labels:
app: hpa
version: v0.0.1
spec:
replicas: 1
selector:
matchLabels:
name: hpa-test-app-deploy
app: hpa
version: v0.0.1
template:
metadata:
labels:
name: hpa-test-app-deploy
app: hpa
version: v0.0.1
spec:
containers:
- name: hpa-test-app-deploy
image: 192.168.204.15/kubernetes/hpa-test-app:v0.0.1
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
requests:
cpu: 0.006
memory: 32Mi
limits:
cpu: 0.06
memory: 128Mi
EOF
kubectl create -f hpa-test-app-deploy.yaml
创建service
cat << EOF > hpa-test-app-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: hpa-test-app-svc
labels:
app: hpa
version: v0.0.1
spec:
selector:
name: hpa-test-app-deploy
app: hpa
version: v0.0.1
ports:
- name: http
port: 8080
protocol: TCP
EOF
kubectl create -f hpa-test-app-svc.yaml
创建HPA
cat << EOF > hpa-test-app-hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: hpa-test-app-hpa
labels:
app: hpa
version: v0.0.1
spec:
scaleTargetRef:
apiVersion: v1
kind: Deployment
name: hpa-test-app-deploy
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 70
EOF
kubectl create -f hpa-test-app-hpa.yaml
检查服务
[root@k8s-apiserver01 hpa-test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hpa-test-app-deploy-69dbc4cf84-5jvb6 1/1 Running 0 23s
[root@k8s-apiserver01 hpa-test]# kubectl logs hpa-test-app-deploy-69dbc4cf84-5jvb6
2018/02/05 05:13:14 Server work at :8080 ...
[root@k8s-apiserver01 hpa-test]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa-test-app-hpa Deployment/hpa-test-app-deploy 0% / 70% 1 10 1 38s
增压和减压测试
首先我们启动一个busybox的pod, 用来对hap-test-app服务进行压力测试
cat << EOF > pod-busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
EOF
kubectl create -f pod-busybox.yaml
然后我们找到hpa-test-app服务的clusterIP:
[root@k8s-apiserver01 apps]# kubectl get svc hpa-test-app-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hpa-test-app-svc ClusterIP 10.254.155.132 <none> 8080/TCP 1m
应用扩张
进入容器, 持续访问hpa-test-app的API(默认计算100位的π, 如果想加大计算可以通过query string: ?length=1000来增大单个请求对cpu的压力),
kubectl exec -it busybox /bin/sh
/ # while true; do wget -q -O- 10.254.155.132:8080; done
然后我们持续关系HPA的扩张
[root@k8s-apiserver01 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa-test-app-hpa Deployment/hpa-test-app-deploy 345% / 70% 1 10 4 52m
[root@k8s-apiserver01 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa-test-app-hpa Deployment/hpa-test-app-deploy 287% / 70% 1 10 8 56m
[root@k8s-apiserver01 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa-test-app-hpa Deployment/hpa-test-app-deploy 0% / 70% 1 10 10 1h
pod数量的变化情况 1–>2–>4–>8–>10, 最终达到最大的扩展上线而停止.
应用收缩
中断对app的访问, 会发现容器又收缩为原来的1个:
[root@k8s-apiserver01 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa-test-app-hpa Deployment/hpa-test-app-deploy 0% / 70% 1 10 1 1h
[root@k8s-apiserver01 ~]# kubectl describe hpa hpa-test-app-hpa
Name: hpa-test-app-hpa
Namespace: default
Labels: app=hpa
version=v0.0.1
Annotations: <none>
CreationTimestamp: Mon, 05 Feb 2018 00:47:31 -0500
Reference: Deployment/hpa-test-app-deploy
Metrics: ( current / target )
resource cpu on pods (as a percentage of request): 0% (0) / 70%
Min replicas: 1
Max replicas: 10
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True ReadyForNewScale the last scale time was sufficiently old as to warrant a new scale
ScalingActive True ValidMetricFound the HPA was able to succesfully calculate a replica count from cpu resource utilization (percentage of request)
ScalingLimited True TooFewReplicas the desired replica count was less than the minimum replica count
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedGetResourceMetric 46m (x57 over 1h) horizontal-pod-autoscaler missing request for cpu on container hpa-test-app-deploy in pod default/hpa-test-app-deploy-75b4fd6cf6-sf78p
Normal SuccessfulRescale 41m (x2 over 1h) horizontal-pod-autoscaler New size: 4; reason: cpu resource utilization (percentage of request) above target
Normal SuccessfulRescale 33m horizontal-pod-autoscaler New size: 10; reason: cpu resource utilization (percentage of request) above target
Normal SuccessfulRescale 28m horizontal-pod-autoscaler New size: 1; reason: All metrics below target
总结
本文主要介绍了HPA的相关原理和使用方法,此功能可以能对服务的容器数量做自动伸缩,对于服务的稳定性是一个很好的提升。但是当前稳定版本中只有cpu使用率这一个指标,是一个很大的弊端。但是kubernetes中关于HPA的架子已经成熟, 期待v2进入stable, 到时候HPA才能爆发它正在的魅力。
参考
- Kubernetes Horizontal Pod Autoscaler
- Kubernetes 中Pod弹性伸缩详解与使用
相关阅读
既然你搜索到了这篇文章,那么平衡二叉树的作用想必心中已经清楚了,我们接下来就直接来谈谈代码... 目录 知识准备 进阶讲解
基于空间金字塔池化的卷积神经网络物体检测原文地址:http://blog.csdn.net/hjimce/article/details/50187655作者:hjimce一、相关理
jeesite应用实战(数据增删改查),认真读完后10分钟就能开
原文地址: https://blog.csdn.net/qing_gee/article/details/76223064jeesite配置指南(官方文档有坑,我把坑填了!)这篇文章里,我主要
来谈一谈有关touchpad的问题吧~这断时间触摸板总是无法用热键启用和关闭,之前一直忙别的事情(其实就是懒。。。)放着没管,但是触版启