节点选择器
学习目标
- 理解 nodeSelector 的作用和使用场景
- 掌握如何使用标签选择节点
- 了解 nodeSelector 的局限性
核心概念
一句话解释
nodeSelector 通过标签匹配,将 Pod 调度到具有特定标签的节点上。
基本用法
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeSelector: # 指定节点选择器
disktype: ssd # 要求节点有 disktype=ssd 标签
zone: east # 要求节点有 zone=east 标签
containers:
- name: app
image: nginx
调度流程
┌─────────────────────────────────────────────────────────┐
│ 调度过程 │
├─────────────────────────────────────────────────────────┤
│ │
│ Pod: nodeSelector: {disktype: ssd, zone: east} │
│ │ │
│ v │
│ ┌─────────────┬─────────────┬─────────────┐ │
│ │ Node A │ Node B │ Node C │ │
│ │ disktype=hdd│ disktype=ssd│ disktype=ssd│ │
│ │ zone=east │ zone=west │ zone=east │ │
│ │ X │ X │ ✓ │ │
│ └─────────────┴─────────────┴─────────────┘ │
│ │ │
│ v │
│ Pod 调度到 Node C │
└─────────────────────────────────────────────────────────┘
节点标签管理
# 查看节点标签
kubectl get nodes --show-labels
# 给节点添加标签
kubectl label nodes node1 disktype=ssd
kubectl label nodes node1 zone=east
# 删除节点标签
kubectl label nodes node1 disktype-
# 修改标签值
kubectl label nodes node1 disktype=hdd --overwrite
常用节点标签
# 内置标签
kubernetes.io/hostname: node1 # 主机名
topology.kubernetes.io/zone: zone-a # 可用区
topology.kubernetes.io/region: us-east # 区域
node.kubernetes.io/instance-type: t3.medium # 实例类型
# 自定义标签示例
disktype: ssd # 磁盘类型
gpu: "true" # 是否有 GPU
environment: production # 环境
workload: compute # 工作负载类型
多条件匹配
# 所有条件都必须满足(AND 关系)
spec:
nodeSelector:
disktype: ssd
zone: east
gpu: "true"
# 节点必须同时具有这三个标签
使用场景
1. 硬件要求
- GPU 工作负载调度到 GPU 节点
- 高性能计算调度到大内存节点
2. 环境隔离
- 生产环境调度到专用节点
- 测试环境调度到测试节点
3. 合规要求
- 数据本地化(调度到特定区域)
- 特定硬件要求
4. 成本优化
- 使用 Spot 实例运行非关键工作负载
实践练习
练习 1:创建带标签的节点
# 给节点添加标签
kubectl label nodes node1 disktype=ssd
kubectl label nodes node1 zone=east
kubectl label nodes node2 disktype=hdd
kubectl label nodes node2 zone=west
# 验证标签
kubectl get nodes --show-labels
练习 2:使用 nodeSelector 调度
# pod-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
nodeSelector:
disktype: ssd
containers:
- name: nginx
image: nginx
# 部署并验证
kubectl apply -f pod-nodeselector.yaml
kubectl get pod nginx-ssd -o wide
# 应该被调度到 node1(disktype=ssd)
练习 3:验证不匹配情况
# pod-nodeselector-fail.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-gpu
spec:
nodeSelector:
gpu: "true"
disktype: ssd
zone: north # 不存在这个标签
containers:
- name: nginx
image: nginx
# 部署并观察
kubectl apply -f pod-nodeselector-fail.yaml
kubectl get pod nginx-gpu
# 状态应该是 Pending
# 查看调度失败原因
kubectl describe pod nginx-gpu | grep -A 5 Events
练习 4:Deployment 中使用 nodeSelector
# deployment-nodeselector.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
nodeSelector:
environment: production
containers:
- name: web
image: nginx
nodeSelector 的局限性
1. 硬性约束
- 必须匹配所有标签(AND 关系)
- 不支持"偏好"或"软性"要求
2. 不支持复杂逻辑
- 不支持 OR 条件
- 不支持 NOT 条件
- 不支持 in/notin 操作符
3. 缺乏灵活性
- 无法表达"优先但不强制"
- 无法指定权重
替代方案:
- nodeAffinity:支持复杂逻辑和软性约束
- podAffinity/podAntiAffinity:Pod 间亲和性
常见问题
1. Pod 一直 Pending
# 检查节点标签
kubectl get nodes --show-labels
# 检查 Pod 的 nodeSelector
kubectl get pod <pod-name> -o yaml | grep -A 5 nodeSelector
# 检查是否有匹配的节点
kubectl get nodes -l disktype=ssd,zone=east
2. 标签命名规范
# 标签键格式
prefix/name: value
# 示例
app.kubernetes.io/name: myapp
kubernetes.io/hostname: node1
# 规则:
# - 前缀可选,最多 253 字符
# - 名称最多 63 字符
# - 只能包含字母、数字、-、_、.
# - 值最多 63 字符
小结
| 要点 | 说明 |
|---|---|
| nodeSelector | 通过标签选择节点 |
| 匹配方式 | 所有条件必须满足(AND) |
| 使用场景 | 硬件要求、环境隔离、合规要求 |
| 局限性 | 只支持硬性约束,逻辑简单 |
| 替代方案 | nodeAffinity 支持更复杂的调度策略 |
练习编辑器
bash
Loading...