3. 节点选择基础:nodeName、nodeSelector、节点标签与选择器的基础用法
在 Kubernetes 集群中,Pod 被调度到哪个节点运行,默认由调度器根据资源请求、优先级、污点容忍度等策略自动决定。但在生产环境中,我们经常需要将 Pod 精确绑定到特定节点——例如,将 GPU 密集型任务调度到装有 GPU 的节点,或将有状态服务调度到具有本地 SSD 的节点。本章介绍三种最基础的节点选择机制:nodeName、节点标签(Labels) 与 nodeSelector。
3.1 节点标签:给节点打上“身份牌”
节点标签是 Kubernetes 中用于标识节点属性的键值对(Key-Value)。标签本身不直接决定调度行为,但它是 nodeSelector、NodeAffinity 等调度规则的基础。每个节点可以拥有多个标签,例如:
kubectl label nodes node-1 disktype=ssd
kubectl label nodes node-2 gpu=true
kubectl label nodes node-3 region=us-east-1
常见的节点标签分类:
| 标签类别 | 示例 Key | 示例 Value | 用途说明 |
|---|---|---|---|
| 硬件属性 | disktype |
ssd / hdd |
区分存储类型,引导 IO 密集型 Pod |
| GPU/加速器 | gpu |
true / false |
标记 GPU 节点,用于 AI 训练 Pod |
| 地理位置 | region / zone |
us-east-1 / az-a |
实现地域亲和性,降低网络延迟 |
| 节点角色 | node-role.kubernetes.io/worker |
true |
区分控制面节点与工作节点 |
| 操作系统 | os |
linux / windows |
多操作系统集群中引导正确镜像 |
node.kubernetes.io/、topology.kubernetes.io/。避免使用无意义的标签(如 foo=bar),保持标签语义清晰、可维护。
3.2 nodeName:最直接的“硬绑定”
nodeName 是 Pod 规范中最简单的节点选择字段。它直接指定 Pod 必须运行在哪个节点上,完全绕过调度器。使用方式如下:
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
nodeName: node-1
containers:
- name: nginx
image: nginx:latest
特点与限制:
- 优先级最高: 一旦设置
nodeName,调度器不会介入,即使节点资源不足,Pod 也会被强制调度(然后可能因资源不足而挂起)。 - 不灵活: 节点名称可能因集群扩缩容而改变,不适合动态环境。
- 适用场景: 测试调试、系统组件(如 kube-proxy)、需要固定节点标识的遗留应用。
nodeName,因为它破坏了调度器的弹性调度能力。如果节点宕机,使用 nodeName 的 Pod 将无法自动迁移到其他节点。
3.3 nodeSelector:基于标签的简单匹配
nodeSelector 是 Kubernetes 提供的最简单的基于标签的节点选择机制。它通过 Pod 规范中的 nodeSelector 字段,指定一组键值对约束,调度器只会将 Pod 调度到所有标签都匹配的节点上。
apiVersion: v1
kind: Pod
metadata:
name: nginx-gpu
spec:
nodeSelector:
gpu: "true"
disktype: ssd
containers:
- name: nginx
image: nginx:latest
上述 Pod 只会被调度到同时具有 gpu=true 和 disktype=ssd 标签的节点上。如果没有任何节点满足条件,Pod 将一直处于 Pending 状态。
3.4 三种选择机制对比
| 机制 | 匹配方式 | 绕过调度器 | 灵活性 | 推荐场景 |
|---|---|---|---|---|
nodeName |
精确节点名称 | 是 | 低 | 调试、系统组件、固定节点 |
nodeSelector |
标签键值精确匹配 | 否 | 中 | 简单硬件/地域约束 |
NodeAffinity(后续章节) |
标签表达式(In/NotIn/Exists) | 否 | 高 | 复杂调度策略、软约束 |
3.5 节点选择流程示意图
下图展示了 Pod 从创建到绑定节点的完整选择路径,以及 nodeName 和 nodeSelector 在其中的作用位置:
3.6 标签选择器操作实战
除了在 Pod 定义中使用 nodeSelector,Kubernetes 还提供了 kubectl 命令行工具来灵活操作节点标签:
- 添加标签:
kubectl label nodes node-1 disktype=ssd - 覆盖标签:
kubectl label nodes node-1 disktype=hdd --overwrite - 删除标签:
kubectl label nodes node-1 disktype-(key 后加减号) - 查看节点标签:
kubectl get nodes --show-labels - 按标签筛选节点:
kubectl get nodes -l disktype=ssd
kubectl get nodes -l disktype=ssd 中的 -l 是标签选择器,用于查询节点;而 Pod 中的 nodeSelector 是调度约束,用于过滤可调度节点。两者语法相同,但作用对象不同。
3.7 常见问题与避坑指南
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Pod 一直 Pending | 没有节点满足 nodeSelector 标签条件 |
检查节点标签是否存在:kubectl get nodes --show-labels |
| Pod 调度到错误节点 | 标签值拼写错误或大小写不匹配 | 标签值区分大小写,使用 kubectl describe node 确认 |
| 节点标签被意外覆盖 | 多个管理员同时操作标签 | 使用 RBAC 限制标签修改权限,或使用自动化标签管理工具 |
nodeName 导致 Pod 无法迁移 |
节点宕机后 Pod 无法重新调度 | 优先使用 nodeSelector 或 NodeAffinity 替代 |
3.8 小结
nodeName 和 nodeSelector 是 Kubernetes 节点选择的基础工具。前者提供硬绑定能力,适合特殊场景;后者通过节点标签实现简单的约束过滤,是生产环境中控制 Pod 分布的首选入门方案。掌握节点标签的管理与选择器语法,是后续学习节点亲和性(NodeAffinity)、Pod 间亲和性(PodAffinity)以及拓扑分布约束(TopologySpreadConstraints)的基石。