Akemi

k8s自动扩缩容HPA VPA KPA

2024/06/01

弹性伸缩是根据用户的业务需求和策略,自动“调整”其“弹性资源”的管理服务。通过弹性伸缩功能,用户可设置定时、周期或监控策略,恰到好处地增加或减少“弹性资源”,并完成实例配置,保证业务平稳健康运行

在k8s中扩缩容分为两种:

1、Node层面:
对K8s物理节点扩容和缩容,根据业务规模实现物理节点自动扩缩容

2、Pod层面:
我们一般会使用Deployment中的replicas参数,设置多个副本集来保证服务的高可用,但是这是一个固定的值,比如我们设置10个副本,就会启10个pod 同时running来提供服务。如果这个服务平时流量很少的时候,也是10个pod同时在running,而流量突然暴增时,又可能出现10个pod不够用的情况。针对这种情况怎么办?就需要扩容和缩容

四种扩容方式介绍

HPA

Kubernetes HPA(Horizontal Pod Autoscaling):Pod水平自动伸缩

通过此功能,只需简单的配置,便可以利用监控指标(cpu使用率、磁盘、自定义的等)自动的扩容或缩容服务中Pod数量,当业务需求增加时,系统将无缝地自动增加适量pod容器,提高系统稳定性。

HPAv1版只能根据CPU使用率进行自动扩缩容
HPAv2可以基于内存和自定义的指标做扩容和缩容

但是并非所有的系统都可以仅依靠CPU或者Memory指标来扩容,对于大多数 Web 应用的后端来说,基于每秒的请求数量进行弹性伸缩来处理突发流量会更加的靠谱。对于一个自动扩缩容系统来说,我们不能局限于CPU、Memory基础监控数据,每秒请求数RPS等自定义指标也是十分重要。

如何采集资源指标?
如果我们的系统默认依赖Prometheus,自定义的Metrics指标则可以从各种数据源或者exporter中获取,基于拉模型的Prometheus会定期从数据源中拉取数据。 也可以基于metrics-server自动获取节点和pod的资源指标

如何实现自动扩缩容?
K8s的HPA controller已经实现了一套简单的自动扩缩容逻辑,默认情况下,每30s检测一次指标,只要检测到了配置HPA的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在5min内没有重新扩缩容的情况下,才会触发扩缩容。 HPA本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果正处在5min内的HPA稳定期,这个时候根据HPA的策略,会导致无法扩容。

VPA

VPA(Vertical Pod Autoscaler),垂直 Pod 自动扩缩容,

基于Pod的资源使用情况自动为集群设置资源占用的限制,从而让集群将Pod调度到有足够资源的最佳节点上

它会根据容器资源使用率自动设置pod的CPU和内存的requests,从而允许在节点上进行适当的调度,以便为每个 Pod 提供适当的可用的节点。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源不足的容量。

如果不满足要求,pod就会pending,避免这种情况,VPA就会自动设置requests

KPA

KPA(Knative Pod Autoscaler):基于请求数对Pod自动扩缩容,KPA 的主要限制在于它不支持基于 CPU 的自动扩缩容。

1、根据并发请求数实现自动扩缩容
2、设置扩缩容边界实现自动扩缩容(最大和最小pod数量)

相比HPA,KPA会考虑更多的场景,其中一个比较重要的是流量突发的时候

一般会与HPA混合使用

Cluster-autoscaler(CA)

只能支持云厂商的K8s

Cluster Autoscaler (CA)是一个独立程序,是用来弹性伸缩kubernetes集群的。它可以自动根据部署应用所请求的资源量来动态的伸缩集群。当集群容量不足时,它会自动去 Cloud Provider (支持 GCE、GKE 和 AWS)创建新的 Node,而在 Node 长时间资源利用率很低时自动将其删除以节省开支。

在以下情况下,集群自动扩容或者缩放:

扩容:由于资源不足,某些Pod无法在任何当前节点上进行调度
缩容: Node节点资源利用率较低时,且此node节点上存在的pod都能被重新调度到其他node节点上运行

什么时候集群节点不会被 CA 删除
1)节点上有pod被 PodDisruptionBudget 控制器限制。
2)节点上有命名空间是 kube-system 的pods。
3)节点上的pod不是被控制器创建,例如不是被deployment, replica set, job, stateful set创建。
4)节点上有pod使用了本地存储
5)节点上pod驱逐后无处可去,即没有其他node能调度这个pod
6)节点有注解:”cluster-autoscaler.kubernetes.io/scale-down-disabled“: “true”(在CA 1.0.3或更高版本中受支持)

部署HPA

HPA可以基于CPU利用率与自定义指标,对deployment中的pod数量进行自动扩缩容(不适用于daemonset)

HPA由Kubernetes API资源和控制器实现。控制器会周期性的获取平均CPU利用率,并与目标值相比较后调整deployment中的副本数量。

1
2
3
4
5
6
7
8
9
10
kubectl api-versions | grep auto
autoscaling/v1
autoscaling/v2

kubectl top pods -n kube-system --sort-by=cpu -A
NAMESPACE NAME CPU(cores) MEMORY(bytes)
kube-system kube-apiserver-ws-k8s-master1 62m 368Mi
kube-system etcd-ws-k8s-master1 51m 149Mi
kube-system kube-apiserver-ws-k8s-master3 47m 314Mi

K8S从1.8版本开始,CPU、内存等资源的metrics信息可以通过 Metrics API来获取,用户可以直接获取这些metrics信息(例如通过执行kubect top命令),HPA使用这些metics信息来实现动态伸缩。

Metrics server:
1、Metrics server是K8S集群资源使用情况的聚合器
2、从1.8版本开始,Metrics server可以通过yaml文件的方式进行部署
3、Metrics server收集所有node节点的metrics信息

HPA原理

HPA的实现是一个控制循环,由controller manager的–horizontal-pod-autoscaler-sync-period参数指定周期(默认值为15秒)。每个周期内,controller manager根据每个HorizontalPodAutoscaler定义中指定的指标查询资源利用率。controller manager可以从resource metrics API(pod 资源指标)和custom metrics API(自定义指标)获取指标。

通过现有pods的CPU使用率的平均值,除以设定的每个Pod的CPU使用率限额)跟目标使用率进行比较

读取平均值=⇒>比较

使用流程

1、创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数
2、收集一组中(PodSelector)每个Pod最近一分钟内的CPU使用率,并计算平均值
3、读取HPA中设定的CPU使用限额
4、计算:平均值之和/限额,求出目标调整的实例个数
5、回到第2步,不断循环

注:目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数

基于CPU进行自动扩缩容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
1.安装metrics-server
这个组件Prometheus也会用,我之前安装的是0.5.1,干脆换一个最新版的0.7.1试试

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.7.1

apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- /metrics-server
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP
- --kubelet-use-node-status-port
- --metric-resolution=15s
image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 10Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100

2.创建一个服务供测试
php文件
cat index.php
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000;$i++) {
$x += sqrt($x);
}
echo "OK!";
?>

dockerfile文件
cat dockerfile
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

构建镜像,并上传至harbor
docker build -t 192.168.10.130/wangsheng/hpa-example:v1 .
docker push 192.168.10.130/wangsheng/hpa-example:v1

3.部署服务的yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: 192.168.10.130/wangsheng/hpa-example:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache

kubectl apply -f php-dp.yaml
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# php-apache-bc79b594f-sbs98 1/1 Running 0 13s

3.自定义一个hpa规则
使用kubectl autoscale创建自动缩放器,实现对php-dp的pod自动扩缩容
#kubectl autoscale deployment --help
#kubectl autoscale deployment [DEPLOYMENT_NAME] --min=MIN_PODS --max=MAX_PODS --cpu-percent=CPU_PERCENT_THRESHOLD
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
CPU占用率高于50时,最大数量10,最小数量1

4.测试
创建一个pod,针对php-apache的CPU进行压测
kubectl run v1 -it --image=busybox --image-pull-policy=IfNotPresent /bin/sh
kubectl get svc
#NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
#kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 81d
#php-apache ClusterIP 10.101.138.183 <none> 80/TCP 14m
while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

可以看到已经自动扩容了
kubectl get hpa
#NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
#php-apache Deployment/php-apache 90%/50% 1 10 9 2m29s
#php-apache Deployment/php-apache 48%/50% 1 10 9 2m56s
停止压测,自动缩容
kubectl get hpa -w
#NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
#php-apache Deployment/php-apache 0%/50% 1 10 1 9m3s

基于内存进行自动扩缩容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
1.创建一个基础服务
docker pull nginx
docker tag nginx:latest 192.168.10.130/wangsheng/nginx:latest
docker push 192.168.10.130/wangsheng/nginx:latest

vim nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hpa
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: 192.168.10.130/wangsheng/nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
protocol: TCP
resources:
requests:
cpu: 0.01
memory: 25Mi
limits:
cpu: 0.05
memory: 60Mi
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
type: NodePort
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
kubectl apply -f nginx.yaml

2.创建hpa
vim hpa-v1.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
maxReplicas: 10 # 最多10个
minReplicas: 1 # 最少1个
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-hpa
metrics: # 采集指标
- type: Resource
# 可选"External" 外部指标
# "Object" 自定义资源
# "Pods" Pod 的自定义指标
# "Resource"容器资源的使用情况
resource:
name: memory
target:
averageUtilization: 60 # 比例大于60
type: Utilization
# 可选Utilization 百分比的使用率
# Value 一个具体的值
# AverageValue 平均值

kubectl apply -f hpa-v1.yaml
kubectl get hpa
#NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
#nginx-hpa Deployment/nginx-hpa 24%/60% 1 10 1 4m51s

3.压测nginx
# 进入pod
kubectl exec -it nginx-hpa-dc6bdf6-nt2z4 -- /bin/sh
dd if=/dev/zero of=/tmp/a

kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 131%/60% 1 10 3 6m53s
nginx-hpa Deployment/nginx-hpa 62%/60% 1 10 3 7m1s
nginx-hpa Deployment/nginx-hpa 62%/60% 1 10 3 7m15s

# 结束压测
rm -rf /tmp/a
在第20分钟的时候完成缩容
kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx-hpa 25%/60% 1 10 3 15m
php-apache Deployment/php-apache 0%/50% 1 10 1 72m
nginx-hpa Deployment/nginx-hpa 26%/60% 1 10 2 15m
nginx-hpa Deployment/nginx-hpa 26%/60% 1 10 2 20m
nginx-hpa Deployment/nginx-hpa 23%/60% 1 10 1 20m

部署VPA

Vertical Pod Autoscaler(VPA):垂直Pod自动扩缩容,用户无需为其pods中的容器设置最新的资源request。配置后,它将根据使用情况自动设置request,从而允许在节点上进行适当的调度,以便为每个pod提供适当的资源量。

随着服务的负载的变化,VPA的推荐值也会不断变化。当目前运行的pod的资源达不到VPA的推荐值,就会执行pod驱逐,重新部署新的足够资源的服务。

VPA使用限制:
不能与HPA(Horizontal Pod Autoscaler )一起使用
Pod比如使用副本控制器,例如属于Deployment或者StatefulSet

VPA有啥好处:
Pod 资源用其所需,所以集群节点使用效率高。
Pod 会被安排到具有适当可用资源的节点上。
不必运行基准测试任务来确定 CPU 和内存请求的合适值。
VPA 可以随时调整 CPU 和内存请求,无需人为操作,因此可以减少维护时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
1.准备工作
准备镜像,直接扔到harbor里
git clone -b vpa-release-0.14 https://github.com/kubernetes/autoscaler.git
进入deploy,修改部署vpa的yaml文件
cd /root/VPA/autoscaler/vertical-pod-autoscaler/deploy

sed -i 's/Always/IfNotPresent/g' recommender-deployment.yaml
sed -i 's/Always/IfNotPresent/g' admission-controller-deployment.yaml
sed -i 's/Always/IfNotPresent/g' updater-deployment.yaml

修改这三个文件的所用镜像分别为下面这三个push的镜像

docker pull giantswarm/vpa-admission-controller:0.14.0
docker pull giantswarm/vpa-recommender:0.14.0
docker pull giantswarm/vpa-updater:0.14.0
docker tag giantswarm/vpa-admission-controller:0.14.0 192.168.10.130/wangsheng/vpa-admission-controller:0.14.0
docker tag giantswarm/vpa-recommender:0.14.0 192.168.10.130/wangsheng/vpa-recommender:0.14.0
docker tag giantswarm/vpa-updater:0.14.0 192.168.10.130/wangsheng/vpa-updater:0.14.0
docker push 192.168.10.130/wangsheng/vpa-admission-controller:0.14.0
docker push 192.168.10.130/wangsheng/vpa-recommender:0.14.0
docker push 192.168.10.130/wangsheng/vpa-updater:0.14.0

准备源码包安装openssl
yum -y install gcc gcc-c++
wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz --no-check-certificate && tar zxf openssl-1.1.1k.tar.gz && cd openssl-1.1.1k
./config
make && make install
mv /usr/local/bin/openssl /usr/local/bin/openssl.bak # 备份openssl
mv apps/openssl /usr/local/bin # 替换掉

做软连接
rm -rf /usr/lib64/libssl.so.1.1
rm -rf /usr/lib64/libcrypto.so.1.1
ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1

2.安装
git clone
tar xf autoscaler.tar.gz
/root/VPA/autoscaler-master/vertical-pod-autoscaler/hack
./vpa-up.sh # 执行安装脚本

kubectl get deployments.apps -n kube-system | grep vpa
vpa-admission-controller 1/1 1 1 13m
vpa-recommender 1/1 1 1 13m
vpa-updater 1/1 1 1 12s

3.创建测试deployment
kubectl create ns vpa

vim vpa-1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: vpa
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: 192.168.10.130/wangsheng/nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
requests:
cpu: 100m
memory: 50Mi
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: vpa
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: nginx

kubectl apply -f vpa-1.yaml
kubectl get pods -n vpa
NAME READY STATUS RESTARTS AGE
nginx-6f68695ff5-b2lpp 1/1 Running 0 18s
nginx-6f68695ff5-wckhv 1/1 Running 0 18s

curl -I 192.168.10.131:30093 | grep HTTP
HTTP/1.1 200 OK

4.创建vpa规则
(1)Off模式
vim vpa-rule-1.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: nginx-vpa-1
namespace: vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: nginx
updatePolicy:
updateMode: "Off" # 默认为Auto
resourcePolicy: # 资源策略
containerPolicies:
- containerName: "nginx" # 绑定的容器名称
minAllowed: # 最小允许设置的参数
cpu: "500m"
memory: "100Mi"
maxAllowed: # 最大允许设置的参数
cpu: "2000m"
memory: "2600Mi"
kubectl apply -f vpa-rule-1.yaml

压测
yum -y install httpd-tools
ab -c 100 -n 10000000 http://10.107.198.208:80/

前后对比图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Auto模式:
vim vpa-rule-2.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: nginx-vpa-2
namespace: vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: nginx
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "nginx"
minAllowed:
cpu: "500m"
memory: "100Mi"
maxAllowed:
cpu: "2000m"
memory: "2600Mi"
kubectl apply -f vpa-rule-2.yaml

压测:
ab -c 100 -n 10000000 http://10.107.198.208:80/

查看kubectl get events -n vpa
可以发现有pod已经被kill,并且基于推荐值重新创建pod

部署KPA(未完成)

基于并发请求数进行自动扩缩容与最大最小副本数的控制

参考官网文档:
Install Serving with YAML - Knative

技术干货:解密最受欢迎的开源 Serverless 框架弹性技术实现 (baidu.com)

官方建议环境:
单节点部署——6C6G 30Gdisk
多节点部署——2C4G 20Gdisk
k8s版本1.28以上
能联网(需要拉取镜像,也可以使用私仓)

Knative-Serving安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
1.安装Knative Serving组件
本地服务组件:
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.14.1/serving-crds.yaml
核心组件——依赖于本地服务组件:
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.14.1/serving-core.yaml

2.安装kourier网络组件
提供kourier、Istio、contour三种方式,官方推荐kourier
安装控制器:
kubectl apply -f https://github.com/knative/net-kourier/releases/download/knative-v1.14.0/kourier.yaml
在核心组件中添加网络组件配置-具体而言是写入了一个ingress-class
kubectl patch configmap/config-network \
--namespace knative-serving \
--type merge \
--patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}'

查看外部地址或CNAME
kubectl --namespace kourier-system get service kourier
#NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
#kourier LoadBalancer 10.101.131.83 <pending> 80:30296/TCP,443:30857/TCP 4m24s

3.重新准备镜像
kubectl get pods -n knative-serving
NAME READY STATUS RESTARTS AGE
activator-5d7f9fc58d-rg7bq 0/1 ImagePullBackOff 0 5m48s
autoscaler-d57d974cb-pts52 0/1 ImagePullBackOff 0 5m48s
controller-b8b47f9b9-dhllq 0/1 ImagePullBackOff 0 5m48s
net-kourier-controller-68d89f78d5-8clfx 0/1 ImagePullBackOff 0 5m33s
webhook-5676f857c4-tc9fq 0/1 ImagePullBackOff 0 5m48s
通过describe查看pod,列出了需要的镜像
gcr.io/knative-releases/knative.dev/serving/cmd/activator
gcr.io/knative-releases/knative.dev/serving/cmd/autoscaler
gcr.io/knative-releases/knative.dev/serving/cmd/controller
gcr.io/knative-releases/knative.dev/net-kourier/cmd/kourier
gcr.io/knative-releases/knative.dev/serving/cmd/webhook

(1)第一种方法:(不推荐)
重新用docker拉取,tag并且push到私仓,再修改deployment中的image来源
docker pull gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/activator:v1.14.1
docker pull gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/autoscaler:v1.14.1
docker pull gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/controller:v1.14.1
docker pull gcr.dockerproxy.com/knative-releases/knative.dev/net-kourier/cmd/kourier
docker pull gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/webhook

docker tag gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/activator:v1.14.1
docker tag gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/autoscaler:v1.14.1
docker tag gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/controller:v1.14.1
docker tag gcr.dockerproxy.com//knative-releases/knative.dev/net-kourier/cmd/kourier:latest
docker tag gcr.dockerproxy.com/knative-releases/knative.dev/serving/cmd/webhook:latest

(2)第二种方法(推荐)
直接edit deployment,将gcr.io修改为gcr.dockerproxy.com

kubectl get pods -n knative-serving
NAME READY STATUS RESTARTS AGE
activator-f66494978-v9btl 1/1 Running 0 5m46s
autoscaler-5f55df446-2q4x6 1/1 Running 0 4m19s
controller-f47dcfc5d-mk7lp 1/1 Running 0 3m58s
net-kourier-controller-5c65d5f9b-qfgmp 1/1 Running 0 2m55s
webhook-7cfc867c9c-49slw 1/1 Running 0 2m23s

4.配置dns
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.14.1/serving-default-domain.yaml

5.安装HPA插件
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.14.1/serving-hpa.yaml
并edit修改镜像源

kubectl get pods -n knative-serving
NAME READY STATUS RESTARTS AGE
activator-7b5b999c5-whn5w 1/1 Running 0 7m23s
autoscaler-f7785c775-ghcg4 1/1 Running 0 6m36s
autoscaler-hpa-88c48f8bc-s7fzh 1/1 Running 0 3m8s
controller-6878f5f766-bnrtp 1/1 Running 0 7m6s
default-domain-h5mk6 1/1 Running 0 5m
net-kourier-controller-5c65d5f9b-qfgmp 1/1 Running 0 19m
webhook-7cfc867c9c-49slw 1/1 Running 0 18m
CATALOG
  1. 1. 四种扩容方式介绍
    1. 1.1. HPA
    2. 1.2. VPA
    3. 1.3. KPA
    4. 1.4. Cluster-autoscaler(CA)
  2. 2. 部署HPA
    1. 2.1. HPA原理
    2. 2.2. 使用流程
    3. 2.3. 基于CPU进行自动扩缩容
    4. 2.4. 基于内存进行自动扩缩容
  3. 3. 部署VPA
  4. 4. 部署KPA(未完成)
    1. 4.1. Knative-Serving安装