Pod的扩缩容
Kubernetes对Pod的扩缩容操作提供了手动和自动两种模式,手动模式通过执行kubectl scale命令或通过RESTful API对一个Deployment/RC进行Pod副本数量的设置,即可一键完成。自动模式则需要用户根据某个性能指标或者自定义业务指标,并指定Pod副本数量的范围,系统将自动在这个范围内根据性能指标的变化进行调整。
一、手动扩缩容:
首先查看命名空间update下的deploy控制器nginx-app下的pod副本数量为2,如图:

扩容:通过kubectl scale命令可以将Pod副本数量从初始的2个更新为3个,如图:

缩容:通过 kubectl scale命令可以将Pod副本数量从初始的3个缩减为1个,如图:

再次查看已经缩容成功:

二、自动扩缩容(Horizontal Pod Autoscaler):
Horizontal Pod Autoscaler 可以根据 CPU 利用率自动扩缩 ReplicationController、 Deployment、ReplicaSet 或 StatefulSet 中的 Pod 数量 ( 除了 CPU 利用率,也可以基于其他应程序提供的 自定义度量指标 来执行自动扩) Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet
原理:Kubernetes中的某个Metrics Server持续采集所有Pod副本的指标数据。HPA控制器通过Metrics Server的API获取这些数据,基于用户定义
的扩缩容规则进行计算,得到目标Pod的副本数量。当目标Pod副本数量 与 当 前 副 本 数 量 不 同 时 , HPA 控 制 器 就 向 Pod 的 副 本 控 制 器
(Deployment、RC或ReplicaSet)发起scale操作,调整Pod的副本数量,完成扩缩容操作。

HPA扩缩容算法:Autoscaler控制器从聚合API获取到Pod性能指标数据之后,基于下面的算法计算出目标Pod副本数量,与当前运行的Pod副本数量进行对比,决定是否需要进行扩缩容操作:
期望副本数 = ceil[当前副本数 * ( 当前指标 / 期望指标 )]
例子:以CPU请求数量为例,如果用户设置的期望指标值为100m,当前实际使用的指标值为200m,则计算得到期望的Pod副本数量应为两个
(200/100=2)。如果当前实际使用的指标值为50m,计算结果为0.5,则向上取整,值为1,得到目标Pod副本数量应为1个。
当计算结果与1非常接近时,可以设置一个容忍度让系统不做扩缩容 操 作 。 容 忍 度 通 过 kube-controller-manager 服 务 的 启 动 参 数 —
horizontal-pod-autoscaler-tolerance进行设置,默认值为0.1(即10%),表示基于上述算法得到的结果在[-10%,+10%]区间内,即[0.9,1.1]区
间,控制器都不会进行扩缩容操作。
存在几种Pod异常的情况,如下所述:
- Pod正在被删除(设置了删除时间戳):将不会计入目标Pod副本数量。
- Pod的当前指标值无法获得:本次探测不会将这个Pod纳入目标Pod副本数量,后续的探测会被重新纳入计算范围
- 如果指标类型是CPU使用率,则对于正在启动但是还未达到Ready状态的Pod,也暂时不会纳入目标副本数量范围。可以通过kubecontroller-manager 服 务 的 启 动 参 数 –horizontal-pod-autoscaler-initialreadiness-delay设置首次探测Pod是否Ready的延时时间,默认值为30s。另一个启动参数–horizontal-pod-autoscaler-cpu-initialization-period设置首次采集Pod的CPU使用率的延时时间,默认5分钟
为了演示 Horizontal Pod Autoscaler,我们将使用一个基于 php-apache 镜像的 定制 Docker 镜像。Dockerfile 内容如下:
FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php
该文件定义了一个 index.php 页面来执行一些 CPU 密集型计算:
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
$x += sqrt($x);
}
echo "OK!";
?>
1、首先,使用下面的配置启动一个 Deployment 来运行这个镜像并暴露一个服务,文件名为php-apache.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: hpa-example
imagePullPolicy: Never #使用本地镜像
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
memory: 50Mi
requests:
cpu: 200m #pod的请求cpu为200毫核
memory: 25Mi
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
执行命令创建deployment,kubectl create -f php-apache.yaml,如图:

2、创建 Horizontal Pod Autoscaler(根据cpu来实现自动扩缩容):
php-apache 服务器已经运行,接下来创建 Horizontal Pod Autoscaler。 以下两种方式将创建一个 Horizontal Pod Autoscaler 用于控制我们上一步骤中创建的 Deployment,根据cpu的使用率来控制 Pod 的副本数量维持在 1 到 5之间。 大致来说,HPA 通过 Deployment 增加或者减少 Pod 副本的数量以保持所有 Pod 的平均 CPU 利用率在 10% 左右(例如每个 Pod 请求 200 毫核的 CPU,如果扩容为2个pod这意味着平均 每个pod的CPU 用量为 100 毫核)
第一种方式:直接使用kubectl autoscale来创建hpa,执行命令如下:
kubectl autoscale deployment php-apache --cpu-percent=10 --min=1 --max=5
查询创建后的hpa,如图:

请注意当前的 CPU 利用率是 0%,这是由于我们尚未发送任何请求到服务器
第二种方式:通过yaml文件形式,如图:

注意看文件开头的api版本为autoscaling/v2beta2,此版本可以基于多项度量指标和自定义度量指标自动扩缩
3、测试HPA, 启动一个容器,并通过一个循环向 php-apache 服务器发送无限的查询请求 ,命令如下:
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
一分钟时间左右之后,通过以下命令,我们可以看到 CPU 负载升高了,cpu利用率升高的比例超过了预设的10%,会触发自动扩容,如图:

此时查看副本数已实现自动扩容,如图:

扩容为2个副本后,此时查看pod的平均使用率为,如图:

可以看到当前的Pod平均cpu使用率为6%,也就是请求的cpu的6%,上图中设置的请求cpu为200m,那么200的6%左右即为如下图所示的用量,如图:

当请求停止后,观察kubectl get hpa中的cpu使用率已经下降,并且pod副本已自动降低为1个,如图:

3、 创建 Horizontal Pod Autoscaler(根据内存来实现自动扩缩容):
编辑hpa-php.yaml文件,添加内存指标,如图:

执行命令kubectl apply -f hpa-php.yaml创建资源并查看,如图:

从上图中可以看出,内存使用率已经达到了79%,超过了设定的值,此时会触发扩容,查看pod数量,发现已经扩容到了上限5个,如图:

查看Pod的内存资源利用率可以发现,平均内存利用率还是超过50%(请求资源为25Mi,上面的资源定义文件中有配置),如图:

由于hpa-php.yaml中设定的Pod最大副本数量为5,因此导致无法基础扩容,此时可以修改最大数量为10 ,然后观察副本变化,发现又继续扩容,如图:

除了HPA外,还有VPA(Vertical Pod Autoscaler),即垂直Pod自动扩缩容,它根据容器资源使用率自动推测并设置Pod合理的CPU和内存的需求指标,从而更加精确地调度Pod,实现整体上节省集群资源的目标,因为无须人为操作,因此也进一步提升了运维自动化的水平。
注:如果开启了自动扩缩容,那么在创建pod的时候,就不需要设置replicas参数了,此时默认的pod数量为1


