写在前面
本文是 K8s 学习笔记系列的第六篇,介绍 Pod 调度机制和自动扩缩容:标签与选择器、nodeSelector、亲和性、污点与容忍、HPA。前置知识:配置与存储(第五篇)。
一、标签与选择器
标签(Label)是 K8s 最核心的组织机制,几乎所有资源都可以打标签。
1.1 标签规范
1
2
3
4
5
6
7
|
metadata:
labels:
app: web-app # 应用名
env: prod # 环境
tier: frontend # 层级
version: v2.0 # 版本
team: backend # 团队
|
1
2
3
4
5
|
标签规则:
- 前缀可选:team.example.com/role=admin
- 值最多63字符
- 只能字母、数字、-、_、.
- 建议用统一的标签体系
|
1.2 标签操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 查看标签
kubectl get pods --show-labels
kubectl get nodes --show-labels
# 按标签筛选
kubectl get pods -l app=web-app
kubectl get pods -l 'env in (prod, staging)'
kubectl get pods -l 'env!=dev'
kubectl get pods -l 'version in (v1, v2),app=web-app'
# 添加/修改标签
kubectl label pod <pod-name> env=prod
kubectl label pod <pod-name> env=staging --overwrite
# 删除标签
kubectl label pod <pod-name> env-
# 给节点打标签
kubectl label node <node-name> disktype=ssd
kubectl label node <node-name> zone=cn-east-1
|
1.3 选择器在 YAML 中的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# Service 匹配 Pod
spec:
selector:
matchLabels:
app: web-app
# Deployment 匹配 Pod
spec:
selector:
matchLabels:
app: web-app
matchExpressions:
- key: env
operator: In
values: ["prod", "staging"]
|
二、Pod 调度
2.1 调度过程
1
2
3
4
5
|
1. 用户创建 Pod
2. kube-scheduler 监听到未调度的 Pod
3. 过滤:排除不满足条件的节点
4. 打分:对可用节点评分
5. 绑定:将 Pod 绑定到得分最高的节点
|
2.2 nodeSelector(最简单)
直接指定 Pod 调度到有特定标签的节点:
1
2
|
# 给节点打标签
kubectl label node node-1 disktype=ssd
|
1
2
3
|
spec:
nodeSelector:
disktype: ssd # 只调度到有这个标签的节点
|
2.3 nodeAffinity(更灵活)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
spec:
affinity:
nodeAffinity:
# 必须满足(硬性要求)
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values: ["cn-east-1", "cn-east-2"]
# 尽量满足(软性偏好)
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80 # 权重
preference:
matchExpressions:
- key: disktype
operator: In
values: ["ssd"]
|
IgnoredDuringExecution 表示 Pod 已运行后,节点标签变化不会驱逐 Pod。
2.4 podAffinity / podAntiAffinity
控制 Pod 之间的亲和性(倾向在一起或分开):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
spec:
affinity:
# Pod 亲和:倾向调度到已有相同标签 Pod 的节点
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: cache # 和 cache Pod 在同一节点
topologyKey: kubernetes.io/hostname
# Pod 反亲和:避免调度到已有相同 Pod 的节点(分散部署)
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: web-app # 尽量分散到不同节点
topologyKey: kubernetes.io/hostname
|
反亲和在生产中很常用:确保同一 Deployment 的副本分布在不同节点上,一个节点挂了不会影响全部实例。
三、污点与容忍
Taint(污点)让节点排斥 Pod,Toleration(容忍)让 Pod 接受污点。
3.1 节点污点
1
2
3
4
5
6
7
8
9
10
|
# 添加污点
kubectl taint nodes node-1 dedicated=gpu:NoSchedule # 不调度新 Pod
kubectl taint nodes node-1 special=true:NoExecute # 不调度且驱逐已有 Pod
kubectl taint nodes node-1 maintenance=true:NoSchedule
# 查看污点
kubectl describe node node-1 | grep Taints
# 删除污点
kubectl taint nodes node-1 dedicated=gpu:NoSchedule-
|
3.2 污点效果
1
2
3
|
NoSchedule — 不调度新 Pod(已有的不受影响)
PreferNoSchedule — 尽量不调度(不是强制的)
NoExecute — 不调度新 Pod + 驱逐已有的 Pod
|
3.3 Pod 容忍
1
2
3
4
5
6
7
8
9
10
11
12
13
|
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
# 容忍所有污点(DaemonSet 常见配置)
- operator: "Exists"
# 容忍 Master 节点污点
- key: "node-role.kubernetes.io/control-plane"
effect: "NoSchedule"
|
3.4 常见场景
1
2
3
4
|
GPU 节点 → 打 taint dedicated=gpu:NoSchedule,只有标记容忍的 Pod 能调度
Master 节点 → 默认有污点,只有系统组件有容忍
专用节点 → 打 taint 给特定业务,其他 Pod 不受影响
节点维护 → 打 taint NoExecute,驱逐 Pod
|
四、HPA 自动扩缩容
HPA(Horizontal Pod Autoscaler)根据指标自动调整 Pod 副本数。
4.1 基于 CPU 的 HPA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # CPU 使用率超过 70% 就扩容
|
4.2 基于内存的 HPA
1
2
3
4
5
6
7
|
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
|
4.2 多指标组合
1
2
3
4
5
6
7
8
9
10
11
12
13
|
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
|
多指标时,HPA 取需要最多副本的指标。
4.3 命令行创建 HPA
1
2
3
4
5
6
7
8
|
# 快速创建
kubectl autoscale deployment web-app --min=2 --max=10 --cpu-percent=70
# 查看 HPA
kubectl get hpa
# 查看 HPA 详情
kubectl describe hpa web-app-hpa
|
4.4 HPA 工作原理
1
2
3
4
|
1. Metrics Server 采集 Pod 的 CPU/内存指标
2. HPA Controller 定期检查指标(默认15秒)
3. 计算目标副本数 = 当前副本数 × (当前指标值 / 目标值)
4. 调整 Deployment 的 replicas
|
4.5 安装 Metrics Server
1
2
3
4
5
6
7
8
9
|
# minikube
minikube addons enable metrics-server
# 通用安装
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 验证
kubectl top nodes
kubectl top pods
|
4.6 扩缩行为配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
spec:
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # 扩容不等待
policies:
- type: Percent
value: 100 # 一次最多扩容 100%(翻倍)
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 300 # 缩容等待5分钟
policies:
- type: Percent
value: 10 # 一次最多缩容 10%
periodSeconds: 60
|
五、调度场景总结
1
2
3
4
5
|
指定节点 → nodeSelector
灵活调度 → nodeAffinity
Pod 分散 → podAntiAffinity
专用节点 → Taint + Toleration
自动扩缩容 → HPA
|
六、小结
本文学习了 K8s 的调度与扩缩:
- 标签与选择器
- nodeSelector 和 nodeAffinity
- podAffinity / podAntiAffinity
- Taint 和 Toleration
- HPA 自动扩缩容
下一篇将学习安全与 RBAC。