k8s hpa
Contents
HPA
pod数扩容和缩减可以使用kubectl scale进行操作,这个是完全手动操作的,k8s提供一个自动scale,Horizontal Pod Autoscaling(Pod 水平自动伸缩),简称 HPA ,HPA 通过监控分析一些控制器控制的所有 Pod 的负载变化情况来确定是否需要调整 Pod 的副本数量
HPA(Horizontal Pod Autoscaler)是kubernetes的一种资源对象,能够根据某些指标对在statefulset、replicacontroller、replicaset等集合中的pod数量进行动态伸缩,使运行在上面的服务对指标的变化有一定的自适应能力。
HPA目前支持四种类型的指标,分别是Resource、Object、External、Pods
注意:Pod的自动缩放不适用于无法缩放的对象。
HPA 是一个控制器(Controller),它周期性(默认每 15 秒)检查目标 Pod 的指标数据,并将其与用户定义的目标值进行比较。
- 扩容 (Scale Up):当指标高于阈值时,增加 Pod 副本数。
- 缩容 (Scale Down):当指标低于阈值时,减少 Pod 副本数。
HPA 本身不采集数据,它依赖以下组件获取指标:
- Metrics Server:提供基础资源指标(CPU、内存)。这是大多数集群的标配。
- Custom Metrics API / External Metrics API:通常由 Prometheus Adapter 或其他监控系统提供,用于支持自定义指标(如 QPS、队列长度、延迟)。
HPA 可以控制实现了 /scale 子资源的控制器,主要包括:
-
Deployment -
ReplicaSet -
StatefulSet -
ReplicationController注意:HPA 不能直接控制
Pod或DaemonSet。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
# HPA的伸缩对象描述,HPA会动态修改该对象的pod数量
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
# HPA的最小pod数量和最大pod数量
minReplicas: 1
maxReplicas: 10
# 监控的指标数组,支持多种类型的指标共存
metrics:
# Object类型的指标
- type: Object
object:
metric:
# 指标名称
name: requests-per-second
# 监控指标的对象描述,指标数据来源于该对象
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
# Value类型的目标值,Object类型的指标只支持Value和AverageValue类型的目标值
target:
type: Value
value: 10k
# Resource类型的指标
- type: Resource
resource:
name: cpu
# Utilization类型的目标值,Resource类型的指标只支持Utilization和AverageValue类型的目标值
target:
type: Utilization
averageUtilization: 50
# Pods类型的指标
- type: Pods
pods:
metric:
name: packets-per-second
# AverageValue类型的目标值,Pods指标类型下只支持AverageValue类型的目标值
target:
type: AverageValue
averageValue: 1k
# External类型的指标
- type: External
external:
metric:
name: queue_messages_ready
# 该字段与第三方的指标标签相关联
selector:
matchLabels:
env: "stage"
app: "myapp"
# External指标类型下只支持Value和AverageValue类型的目标值
target:
type: AverageValue
averageValue: 30
亲和性与反亲和性
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-with-affinity
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: nginx
image: nginx:1.27
resources:
requests:
cpu: "100m"
memory: "128Mi"
# ======================================================================
# 核心部分:亲和性配置 (Affinity)
# ======================================================================
affinity:
# ------------------------------------------------------------------
# 1. 节点亲和性 (Node Affinity)
# 目的:让 Pod 优先调度到带有特定标签的节点上 (例如:高性能节点)
# ------------------------------------------------------------------
nodeAffinity:
# 【必需】规则:如果不满足,Pod 绝对不会被调度到这里
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
# 含义:Pod 必须调度到标签为 disktype=ssd 的节点上
# 【偏好】规则:尽量满足,如果不满足也可以调度到其他节点
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # 权重 (1-100),越高越优先
preference:
matchExpressions:
- key: zone
operator: In
values:
- cn-hangzhou-a
# 含义:如果有 cn-hangzhou-a 的节点,优先选它;没有也无所谓
# ------------------------------------------------------------------
# 2. Pod 亲和性 (Pod Affinity)
# 目的:让当前 Pod 尽量和“其他特定 Pod”调度在同一个节点上
# 场景:缓存应用紧挨着后端应用,减少网络延迟
# ------------------------------------------------------------------
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis-cache
topologyKey: "kubernetes.io/hostname"
# 含义:当前 Pod 必须和标签为 app=redis-cache 的 Pod 运行在【同一台节点】上
# ------------------------------------------------------------------
# 3. Pod 反亲和性 (Pod Anti-Affinity) ⭐ 最常用 (配合 HPA)
# 目的:让当前 Pod 尽量【远离】“其他特定 Pod”
# 场景:高可用。当 HPA 扩容出 3 个副本时,确保它们不在同一台机器上
# ------------------------------------------------------------------
podAntiAffinity:
# 【软策略】(推荐用于生产环境)
# 含义:尽量分开,但如果资源紧张,允许挤在一起 (避免死锁导致无法扩容)
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-app
topologyKey: "kubernetes.io/hostname"
# 含义:尽量不和 app=web-app 的其他 Pod 在同一台节点 (hostname) 上
# 【硬策略】(慎用)
# 含义:绝对不允许在一起。如果找不到空闲节点,Pod 将一直处于 Pending 状态
# 风险:如果集群只有 1 个节点,且设置了硬策略,新副本永远无法启动
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-app
topologyKey: "topology.kubernetes.io/zone"
# 含义:绝对不允许和 app=web-app 的其他 Pod 在同一个【可用区 (Zone)】内
# 这实现了跨可用区的高可用容灾
# ==============================================================================
# 关键概念解释:
# 1. requiredDuringScheduling... (硬策略):
# - 必须满足。不满足则不调度 (Pending)。
# - 风险:可能导致无法扩容。
#
# 2. preferredDuringScheduling... (软策略):
# - 尽量满足。不满足也能调度。
# - 推荐:配合 HPA 使用时,通常首选“软策略”,防止因资源不足导致扩容失败。
#
# 3. topologyKey (拓扑域):
# - kubernetes.io/hostname: 指具体的某一台物理/虚拟机节点。
# - topology.kubernetes.io/zone: 指可用区 (如 杭州可用区A)。
# - topology.kubernetes.io/region: 指地域 (如 华东1)。
# ==============================================================================