Prog77X
- 关注

1. 基本概念
Horizontal Pod Autoscaler(HPA,Pod水平自动伸缩),根据平均 CPU 利用率、平均内存利用率或你指定的任何其他自定义指标自动调整 Deployment 、ReplicaSet 或 StatefulSet 或其他类似资源,实现部署的自动扩展和缩减,让部署的规模接近于实际服务的负载。HPA不适用于无法缩放的对象,例如DaemonSet。
实际生产中,一般使用这四类指标:
- Resource metrics——CPU核 和 内存利用率指标。
- Pod metrics——例如网络利用率和流量。
- Object metrics——特定对象的指标,比如Ingress, 可以按每秒使用请求数来扩展容器。
- Custom metrics——自定义监控,比如通过定义服务响应时间,当响应时间达到一定指标时自动扩容。
2. 安装 metrics-server
2.1 HAP 前提条件
默认情况下,Horizontal Pod Autoscaler 控制器会从一系列的 API 中检索度量值。 集群管理员需要确保下述条件,以保证 HPA 控制器能够访问这些 API:
- 对于资源指标,将使用 metrics.k8s.ioAPI,一般由 metrics-server 提供。 它可以作为集群插件启动。
- 对于自定义指标,将使用 custom.metrics.k8s.ioAPI。 它由其他度量指标方案厂商的“适配器(Adapter)” API 服务器提供。 检查你的指标管道以查看是否有可用的 Kubernetes 指标适配器。
- 对于外部指标,将使用 external.metrics.k8s.ioAPI。可能由上面的自定义指标适配器提供。
- 自动检测周期由 kube-controller-manager 的 --horizontal-pod-autoscaler-sync-period 参数设置(默认间隔为 15 秒)。
- metrics-server 提供 metrics.k8s.ioAPI 为pod资源的使用提供支持。
- 15s/周期 -> 查询metrics.k8s.ioAPI -> 算法计算 -> 调用scale 调度 -> 特定的扩缩容策略执行。
Kubernetes Metrics Server:
- Kubernetes Metrics Server 是 Cluster 的核心监控数据的聚合器,kubeadm 默认是不部署的。
- Metrics Server 供 Dashboard 等其他组件使用,是一个扩展的 APIServer,依赖于 API Aggregator。所以,在安装 Metrics Server 之前需要先在 kube-apiserver 中开启 API Aggregator。
- Metrics API 只可以查询当前的度量数据,并不保存历史数据。
- Metrics API URI 为 /apis/metrics.k8s.io/,在k8s.io/metrics下维护。
- 必须部署 metrics-server 才能使用该 API,metrics-server 通过调用 kubelet Summary API 获取数据。
2.2 开启 API Aggregator
修改每个 API Server 的 kube-apiserver.yaml 配置开启 Aggregator Routing
vim /etc/kubernetes/manifests/kube-apiserver.yaml # 添加这行 # --enable-aggregator-routing=true |
修改 manifests 配置后 API Server 会自动重启生效。
使用 kubectl describe 命令来查看 kube-apiserver 的 Pod 描述,确认是否包含了相应的配置。
kubectl describe pod kube-apiserver-k8s-master -n kube-system |
2.3 下载 components.yaml
GitHub地址:https://github.com/kubernetes-sigs/metrics-server/releases
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/metrics-server-helm-chart-3.8.2/components.yaml |
下载后修改如下部分
... template: metadata: labels: k8s-app: metrics-server spec: containers: - args: - --cert-dir=/tmp - --secure-port=4443 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --kubelet-insecure-tls # 加上该启动参数,不加可能会报错 image: registry.aliyuncs.com/google_containers/metrics-server:v0.6.1 # 镜像地址根据情况修改 imagePullPolicy: IfNotPresent ... |
metrics-server pod 若无法启动,出现日志 unable to fully collect metrics
解决方法:在metrics-server中添加--kubelet-insecure-tls参数跳过证书校验
2.4 开始安装
kubectl apply -f components.yaml # 查看 kubectl get pod -n kube-system | grep metrics-server |
2.5 查看node和pod资源使用情况
# 查看node和pod资源使用情况 kubectl top nodes kubectl top pods -n kube-system |
3. Horizontal Pod Autoscaler 工作原理
3.1 原理架构图
- 自动检测周期由 kube-controller-manager 的 --horizontal-pod-autoscaler-sync-period 参数设置(默认间隔为 15 秒)。
- metrics-server 提供 metrics.k8s.ioAPI 为pod资源的使用提供支持。
- 15s/周期 -> 查询metrics.k8s.ioAPI -> 算法计算 -> 调用scale 调度 -> 特定的扩缩容策略执行。
3.2 HPA扩缩容算法
从最基本的角度来看,Pod 水平自动扩缩控制器根据当前指标和期望指标来计算扩缩比例。
期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]
1、扩容
如果计算出的扩缩比例接近 1.0, 将会放弃本次扩缩, 度量指标 / 期望指标接近1.0。
2、缩容
冷却/延迟: 如果延迟(冷却)时间设置的太短,那么副本数量有可能跟以前一样出现抖动。
默认值是 5 分钟:–horizontal-pod-autoscaler-downscale-stabilization
3、特殊处理
- 丢失度量值:缩小时假设这些 Pod 消耗了目标值的 100%, 在需要放大时假设这些 Pod 消耗了 0% 目标值。 这可以在一定程度上抑制扩缩的幅度。
- 存在未就绪的pod的时候:我们保守地假设尚未就绪的 Pod 消耗了期望指标的 0%,从而进一步降低了扩缩的幅度。
- 未就绪的 Pod 和缺少指标的 Pod 考虑进来再次计算使用率。 如果新的比率与扩缩方向相反,或者在容忍范围内,则跳过扩缩。 否则,我们使用新的扩缩比例。
- 指定了多个指标, 那么会按照每个指标分别计算扩缩副本数,取最大值进行扩缩。
3.3 HPA 对象定义
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: nginx spec: behavior: scaleDown: policies: - type: Pods value: 4 periodSeconds: 60 - type: Percent value: 10 periodSeconds: 60 stabilizationWindowSeconds: 300 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 |
主要部分解释:
apiVersion:
autoscaling/v2beta2
- 表示 HPA 使用的 API 版本。
kind:
HorizontalPodAutoscaler
- 资源类型是 HPA。
metadata:
name
:nginx
- HPA 对象的名称。
spec:
behavior: 定义 HPA 的缩放行为。
- scaleDown: 定义缩减副本时的行为策略。
- policies:
type: Pods
- 每次缩减固定数量的 Pod。value: 4
- 每次缩减 4 个 Pod。periodSeconds: 60
- 每 60 秒执行一次该策略。
type: Percent
- 每次缩减副本的百分比。value: 10
- 每次缩减 10% 的 Pod。periodSeconds: 60
- 每 60 秒执行一次该策略。
- stabilizationWindowSeconds:
300
- 缩减副本时的稳定窗口期,为 300 秒。
- policies:
- scaleDown: 定义缩减副本时的行为策略。
scaleTargetRef: 指定 HPA 关联的目标对象。
apiVersion: apps/v1
kind: Deployment
name: nginx
- 目标 Deployment 的名称。
minReplicas:
1
- 最小副本数量。maxReplicas:
10
- 最大副本数量。metrics: 定义缩放的指标。
type: Resource
resource
:name: cpu
- 基于 CPU 资源的利用率。target
:type: Utilization
averageUtilization: 50
- 目标 CPU 利用率为 50%。
HPA对象默认行为:
behavior: scaleDown: stabilizationWindowSeconds: 300 policies: - type: Percent value: 100 periodSeconds: 15 scaleUp: stabilizationWindowSeconds: 0 policies: - type: Percent value: 100 periodSeconds: 15 - type: Pods value: 4 periodSeconds: 15 selectPolicy: Max |
默认行为解释:
- behavior:
scaleDown: 默认缩减副本的行为。
- stabilizationWindowSeconds:
300
- 缩减副本时的稳定窗口期,为 300 秒。 - policies:
type: Percent
- 每次缩减副本的百分比。value: 100
- 每次可以缩减 100% 的 Pod,即全部缩减。periodSeconds: 15
- 每 15 秒执行一次该策略。
- stabilizationWindowSeconds:
scaleUp: 默认增加副本的行为。
- stabilizationWindowSeconds:
0
- 增加副本时没有稳定窗口期。 - policies:
type: Percent
- 每次增加副本的百分比。value: 100
- 每次可以增加 100% 的 Pod。periodSeconds: 15
- 每 15 秒执行一次该策略。
type: Pods
- 每次增加固定数量的 Pod。value: 4
- 每次增加 4 个 Pod。periodSeconds: 15
- 每 15 秒执行一次该策略。
- selectPolicy:
Max
- 当多个策略同时生效时,选择能产生最大效果的策略。
- stabilizationWindowSeconds:
4. 安装镜像
实验以通过 Docker 命令手动拉取nginx:latest镜像为例
docker pull nginx:latest # 输出类似如下(表示拉取成功): Using default tag: latest latest: Pulling from library/nginx aed007321795: Pull complete 3ab6bcb2dcd4: Pull complete 81d0c4dffcf1: Pull complete Digest: sha256:cd842bc5ad3b26cc950a139bd8e55f28e06edda963d0a162f9a96e41f110d920 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest |
确认镜像已下载,可以通过以下命令查看本地镜像:
docker images |
输出类似如下(表示 nginx 镜像已存在):
执行
5. 编排yaml
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: hap-nginx spec: maxReplicas: 10 minReplicas: 1 metrics: - resource: name: cpu target: averageUtilization: 40 type: Utilization type: Resource scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: hap-nginx --- apiVersion: v1 kind: Service metadata: name: hap-nginx spec: type: NodePort ports: - name: "http" port: 80 targetPort: 80 nodePort: 30080 selector: service: hap-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: hap-nginx spec: replicas: 1 selector: matchLabels: service: hap-nginx template: metadata: labels: service: hap-nginx spec: containers: - name: hap-nginx image: nginx:latest resources: requests: cpu: 100m memory: 100Mi limits: cpu: 200m memory: 200Mi |
对于 yaml 详细说明一下:
Horizontal Pod Autoscaler(HPA),我们命名成 hap-nginx,具体来说:
- maxReplicas 和 minReplicas 分别指定了允许的最大和最小 Pod 副本数。
- metrics 定义了用于调整副本数的指标。在这里,使用 CPU 使用率作为指标,并设置目标 CPU 平均利用率为 40%。
- scaleTargetRef 指定了需要自动缩放的目标对象,这里是一个 Deployment,名称为 hap-nginx。
Service,用于将流量路由到后端的 Pod,具体来说:
- type 指定了服务类型为 NodePort,允许外部流量通过节点端口访问服务。
- ports 定义了服务暴露的端口和目标端口。在这里,服务将监听端口 80,并将流量转发到后端 Pod 的端口 80。
- selector 指定了要将流量路由到哪些 Pod。这里选择了标签为 service: hap-nginx 的 Pod。
Deployment,用于管理运行在 Pod 中的应用程序,具体来说:
- replicas 指定了期望的 Pod 副本数,这里设置为 1。
- selector 定义了标签选择器,用于选择由该 Deployment 管理的 Pod。在这里,选择器匹配标签为 service: hap-nginx 的 Pod。
- template 定义了 Pod 的模板,包括标签和容器规格。在这里,定义了一个名为 hap-nginx 的容器,使用最新版本的 nginx 镜像,并设置了容器的 CPU 和内存资源请求与限制。
执行:
kubectl apply -f 1.yaml |
表示已成功将 YAML 文件 /home/as/桌面/1.yaml 中定义的 Horizontal Pod Autoscaler、Service 和 Deployment 应用到集群中。
6. 查看状态信息
查看服务运行在哪个节点上:
kubectl get pods -o wide |
访问:
虽然显示运行在 worker1 上,但使用 worker1 的 ip 和 worker2 的 ip 都可以访问。
7. 安装 ab 压测工具
ab(Apache Benchmark)是 apache 自带的一款功能强大的测试工具,常用的参数为-n 和-c。
ab -n 1000 -c 100 url # 将会发送 1000 个请求(-n 1000)给指定的服务,同时并发地发送 100 个请求(-c 100) |
直接通过yum安装apache:
yum install httpd -y ab -V |
8. 开始压测
ab -n 100000 -c 800 http://192.168.136.130:30080/ #-c:并发数 #-n:总请求数 |
可以看到已经实现了根据CPU 动态扩容了。
如果想在扩容后重新设置只起固定数量的pod,不可以删除,删除后会重启相同数量的pod
kubectl scale deployment hap-nginx --replicas=1 |
hap-nginx Deployment 的副本数量设置为 1,停止其他相关的 Pod 的运行
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)