Kubernetes自动伸缩的两种模式
Kubernetes的自动伸缩能力分为两个层面:Pod级别的水平自动伸缩(HPA)和节点级别的集群自动伸缩(CA/Cluster Autoscaler)。HPA根据CPU、内存或自定义指标调整Deployment的Pod副本数,CA则根据Pending Pod的需求向云供应商申请新节点。两者配合使用才能实现真正的弹性——HPA扩出Pod,Pod因资源不足进入Pending,CA检测到Pending Pod后拉起新节点。生产环境还需要VPA(垂直自动伸缩)处理Pod资源请求与实际使用偏差过大的问题,但VPA默认不会自动调整运行中Pod的资源限制(会重启Pod),需谨慎开启。
HPA配置实战与指标选择
HPA最常用的指标是CPU利用率,但对Web服务而言,CPU利用率并不能完全反映负载状态——一个QPS=1000但CPU只有30%的服务,可能连接池和队列已经接近饱和。更合理的做法是配置基于QPS或请求延迟的自定义指标。
# 基于CPU利用率的HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# 基于Prometheus自定义指标(QPS)的HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa-qps
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 100
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "500" # 每Pod平均500 QPS时触发扩容
自定义指标需要部署Prometheus Adapter(组件名称:prometheus-adapter),它将Prometheus中的指标通过Kubernetes Metrics API暴露给HPA控制器。关键配置是rules字段,定义PromQL查询与Kubernetes指标名称的映射。
# prometheus-adapter values.yaml
rules:
custom:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "http_requests_total"
as: "http_requests_per_second"
metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
Cluster Autoscaler节点扩缩容策略
Cluster Autoscaler的核心逻辑:扫描所有Pending状态的Pod,根据Pod的资源请求和调度约束(nodeSelector、亲和性、污点容忍)找到最合适的节点规格,向云API创建新实例。缩容时扫描利用率低于阈值的节点,将其上的Pod优雅迁移后释放节点。
CA有几个关键参数需要调优:scan-interval(扫描间隔,默认10秒)决定扩容灵敏度;scale-down-delay-after-add(新节点加入多久后允许缩容,默认10分钟)防止节点刚加入就被缩掉;node-group-auto-discovery决定CA能操作的节点组范围。缩容安全期(scale-down-unneeded-time,默认10分钟)保证低利用率节点持续一段时间后才被回收,避免流量抖动引发频繁扩缩。
# Cluster Autoscaler部署示例(AWS EKS场景)
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
template:
spec:
containers:
- image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.30.0
name: cluster-autoscaler
command:
- ./cluster-autoscaler
- --scale-down-delay-after-add=5m
- --scale-down-unneeded-time=10m
- --scale-down-utilization-threshold=0.5
- --expander=least-waste # 选择浪费最少资源的节点组
- --balance-similar-node-groups
- --skip-nodes-with-system-pods=false
env:
- name: AWS_REGION
value: us-west-2
资源配额与LimitRange设计
多租户Kubernetes集群中,ResourceQuota限制命名空间的资源总量,LimitRange限制单个Pod的资源范围。两者配合使用可以防止某个团队或应用占用过多资源导致其他工作负载无法调度。
# 命名空间资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "100" # 最多100核CPU请求
requests.memory: 200Gi # 最多200Gi内存请求
limits.cpu: "200" # 最多200核CPU限制
limits.memory: 400Gi # 最多400Gi内存限制
pods: "500" # 最多500个Pod
persistentvolumeclaims: "50" # 最多50个PVC
services.loadbalancers: "5" # 最多5个LoadBalancer
# 单Pod资源范围限制
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: team-a
spec:
limits:
- type: Container
default: # 默认limit
cpu: "2"
memory: 4Gi
defaultRequest: # 默认request
cpu: "500m"
memory: 512Mi
max: # 单容器最大值
cpu: "16"
memory: 32Gi
min: # 单容器最小值
cpu: "100m"
memory: 128Mi
PriorityClass与抢占调度
当集群资源紧张时,Kubernetes通过PriorityClass决定哪些Pod优先保留,哪些可以被驱逐。核心业务设置高优先级,批处理/离线任务设置低优先级。当高优先级Pod无法调度时,调度器会驱逐节点上的低优先级Pod腾出空间——这就是抢占机制。
# 定义优先级类
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: critical
value: 1000000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "核心在线业务,可抢占低优先级Pod"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: batch-job
value: 100
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "离线批处理任务,可被高优先级Pod抢占"
# Pod中指定优先级
apiVersion: v1
kind: Pod
metadata:
name: api-server
spec:
priorityClassName: critical
containers:
- name: app
image: my-api:latest
resources:
requests:
cpu: "4"
memory: 8Gi
PodDisruptionBudget保障服务连续性
节点维护、升级、缩容都会驱逐Pod。PodDisruptionBudget(PDB)限制自愿中断(Voluntary Disruption)同时影响的Pod数量,保证服务在节点操作期间仍有足够的可用副本。PDB只约束自愿中断(kubectl drain、集群升级),不约束节点故障等非自愿中断。
# PDB配置:至少保持3个可用副本
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-api-pdb
namespace: production
spec:
minAvailable: 3
selector:
matchLabels:
app: web-api
# 另一种写法:最多允许1个不可用
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: worker-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: background-worker
HPA伸缩抖动与稳定性窗口
HPA的一个常见问题是伸缩抖动——流量波动导致副本数频繁增减,Pod刚创建完就被缩掉,下一波流量来又得重新扩容。解决方案是配置behavior字段中的稳定窗口(stabilizationWindowSeconds),让HPA在指标波动期间保持当前副本数不变。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa-stable
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 缩容前观察5分钟
policies:
- type: Percent
value: 10 # 每次最多缩10%的副本
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0 # 扩容不做等待
policies:
- type: Percent
value: 100 # 每次最多翻倍
periodSeconds: 60
- type: Pods
value: 4 # 或每次至少加4个Pod
periodSeconds: 60
selectPolicy: Max # 取两种策略的最大值
集群伸缩的监控告警
自动伸缩不是”配完就不管了”。需要建立监控看板跟踪:当前副本数与HPA目标副本数是否一致(不一致说明Pod创建受阻)、Pending Pod持续时间(超过5分钟说明CA未生效或云API限流)、节点扩缩频率(1小时内扩缩超过3次说明需要调整阈值或稳定窗口)。Grafana看板配合Prometheus告警规则,在伸缩异常时及时通知值班人员。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-zi-dong-shen-suo-yu-zi-yuan-pei-e-guan-li/