一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
一、前言
在实际的生产环境中,当服务的请求数量急剧增加的时候,我们需要对某个服务进行扩容,当资源紧张或服务的工作负载降低时,我们可以对某个服务进行缩容。
通过
Deployment/ReplicationController/ReplicaSet
的Scale
机制可以完成Pod
扩缩容。
Pod
扩缩容分为两种模式,手动扩缩容和自动扩缩容:
- 手动扩缩容:通过执行命令
kubectl scale
或通过RESTful API
对Deployment/rc/rs
进行Pod
副本数量设置来一键完成扩缩容。 - 自动扩缩容:指定某个性能指标或自定义业务指标的范围,以及指定
Pod
副本数量的范围,kubernetes
系统会自动在副本数量的范围内根据性能指标的变化进行调整。
二、手动扩缩容
通过命令 kubectl scale
可以进行手动扩缩容,使用参数 --replicas
指定需要增加或是减少 Pod
的数量到某个指定的数字。
- 创建
nginx-deployment.yaml
文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
- 执行创建
$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
- 查看
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-5754944d6c-hkz57 1/1 Running 0 55s
nginx-deployment-5754944d6c-jvhwq 1/1 Running 0 55s
nginx-deployment-5754944d6c-z7ccp 1/1 Running 0 55s
- 扩容(将
nginx-deployment Pod
副本数量从 3 个扩容到 5 个)
# 执行扩容
$ kubectl scale deployment nginx-deployment --replicas 5
deployment.extensions/nginx-deployment scaled
- 查看
# 可以看到有两个新创建的 Pod
$ kubectl get pods
- 缩容(将
nginx-deployment Pod
副本数量从 5 个缩容到 1 个)
# 执行缩容
$ kubectl scale deployment nginx-deployment --replicas 1
deployment.extensions/nginx-deployment scaled
- 查看
# 从结果中可以看出,系统 kill 掉了一些运行中的 Pod,只保留了一个 Pod 来实现缩容
$ kubectl get pods
三、 自动扩缩容
从 Kubernetes v1.1
版本开始,添加了名为 Horizontal Pod Autoscaler
(HPA) 的控制器,用于实现 Pod
自动扩缩容的功能。HPA
控制器基于 Master
的 kube-controller-manager
服务启动参数 --horizontal-pod-autoscaler-sync-period
定义的检测周期(默认值为 15s),周期性检测目标 Pod
的资源性能指标,并与 HPA
资源对象中的扩缩容条件进行对比,当满足条件时对 Pod
副本数量进行调整。
扩缩容会根据内存、CPU 资源使用率、或是自定义的业务监控指标作为资源性能指标。
kubernetes
系统的资源采集,由这两种 API
实现:
Resource Metrics API
(通过metrics-server
实现):负责采集Node
、Pod
的核心资源数据Custom Metrics API
(通常使用Prometheus
实现):负责自定义的指标数据采集,比如:网卡流量、磁盘IOPS
、HTTP
请求数、数据库连接数等
四、 扩缩容算法
Autoscaler
控制器从聚合 API
获取到 Pod
性能指标数据之后,通过下面的算法计算目标 Pod
副本数量:
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
目标副本数量 = 当前副本数 * (当前指标值/期望指标值)
举个栗子
以 CPU
请求数量为例,假设当前系统运行了一个 Pod
副本,用户设置的期望值为 100m:
- 如果当前实际使用的指标值为 200m,则:目标副本数量 = 1 * (200/100) = 2,也就是期望 Pod 副本数量为 2,这个时候就会进行
Pod
扩容 - 如果当前实际使用的指标值为 50m,则:目标副本数量 = 1 * (50/100) = 0.5,将计算结果向上取整为 1,也就是期望 Pod 副本数量为 1,这个时候就不会改变
Pod
的数量
当计算结果与 1 非常接近时,可以设置一个容忍度使系统不做扩缩容处理,通过 kube-controller-manager
服务的启动参数 --horizontal-pod-autoscaler-tolerance
进行设置,该参数的默认值为 0.1(10%),所以上述算法计算结果在正负 10% 的区间中都不会执行扩缩容操作。
期望指标值(desiredMetricValue)也可以是指标的平均值,比如:targetAverageValue,这时当前指标值(currentMetricValue)的算法为:
当前指标值 = 所有 Pod 副本当前指标值总和 / Pod 副本数量