8、k8s nodename和nodeSelector调度pod

1、nodeName调度pod

在k8s中,NodeName是每个Node节点的唯一标识符,它是一个字符串,通常是节点的主机名(hostname)。在创建Pod时,可以通过指定nodeName字段来将Pod调度到特定的Node节点上。

指定pod节点运行在具体node上,接下来我将如下的pod直接调度到k8s-node-1上:

bash 复制代码
vi pod-node.yaml
bash 复制代码
apiVersion: v1 # Kubernetes API 版本 v1
kind: Pod # 资源类型为 Pod
metadata: # 元数据部分
  name: demo-pod # Pod 名称
  namespace: default # 所属命名空间(默认)
  labels: # 标签集合,用于筛选和分组
    app: busybox-tomcat # 应用标签
    env: pro # 环境标签(生产环境)
spec: # Pod 规格定义
  nodeName: k8s-node-1 # 指定调度到名为 k8s-node-1的节点
  containers: # 容器列表,定义 Pod 中运行的容器
  - name: tomcat # 第一个容器名称
    ports: # 容器端口配置
    - containerPort: 8080 # 容器内部监听的端口号
    image: tomcat:8.5.34-jre8-alpine # 使用的镜像及标签
    imagePullPolicy: IfNotPresent # 镜像拉取策略:仅当本地不存在时才拉取
  - name: busybox # 第二个容器名称
    image: busybox:latest # 使用的镜像及标签
    imagePullPolicy: IfNotPresent # 镜像拉取策略同前
    command: # 容器启动命令(覆盖镜像默认的 CMD)
    - "/bin/sh" # 调用 sh 解释器
    - "-c" # 执行后续字符串中的命令
    - "sleep 36000" # 休眠 36000 秒(即 10 小时),保持容器运行
bash 复制代码
 kubectl apply -f pod-node.yaml
bash 复制代码
# 查看所有pod信息
kubectl get pods -o wide

刚创建这个pod的时候,Status是ContainerCreating,因为要拉取镜像等一系些列操作。

接着看下这个pod的详细信息

bash 复制代码
kubectl describe pods  demo-pod

可以看到这个pod的基本信息,有ip有labels等等,在最下面的event,可以看到这个pod里面有两个容器,第一个是tomcat,第二个是busybox,这两个容器正好对应pod-node.yaml中的配置。先pull tomcat的镜像,然后再pullbusybox的镜像。这个就是创建这个pod的过程。

再执行命令,查看pod信息

bash 复制代码
# 查看所有pod信息
kubectl get pods -o wide

pod的status已经是running状态,且直接被调度到k8s-node-1节点,按照pod-node.yaml中指定的节点进行了调度。

2、nodeSelector调度pod

在k8s中,nodeSelector是一种用于在Pod级别上选择运行节点的方法。通过使用nodeSelector字段,可以指定一组键值对(标签),以便将Pod调度到具有匹配标签的节点上运行。每个节点都可以使用一组标签进行标识,这些标签可以根据硬件规格、操作系统、地理位置或其他特定的属性来定义。当创建Pod时,可以通过在Pod的配置中指定nodeSelector字段,来告诉k8s调度器选择具有匹配标签的节点来运行该Pod。

在实现nodeSelector调度pod之前,先把刚刚创建的那个pod给删除,执行如下命令:

bash 复制代码
kubectl delete pod demo-pod --force --grace-period=0

然后编辑刚刚那个pod-node.yaml文件,将使用nodeSelector调度pod到带有指定标签的节点,假设带有指定标签的节点是一个GPU服务器节点,且属于zh-easy区域,如下nodeSelector中就打上了这两个标签

bash 复制代码
apiVersion: v1 # Kubernetes API 版本 v1
kind: Pod # 资源类型为 Pod
metadata: # 元数据部分
  name: demo-pod # Pod 名称
  namespace: default # 所属命名空间(默认)
  labels: # 标签集合,用于筛选和分组
    app: busybox-tomcat # 应用标签
    env: pro # 环境标签(生产环境)
spec: # Pod 规格定义
  nodeSelector: # 节点选择器(与 containers 同级)
    vm-type: gpu  # Label 标签
    region: zh-east # Label 标签
  containers: # 容器列表,定义 Pod 中运行的容器
  - name: tomcat # 第一个容器名称
    ports: # 容器端口配置
    - containerPort: 8080 # 容器内部监听的端口号
    image: tomcat:8.5.34-jre8-alpine # 使用的镜像及标签
    imagePullPolicy: IfNotPresent # 镜像拉取策略:仅当本地不存在时才拉取
  - name: busybox # 第二个容器名称
    image: busybox:latest # 使用的镜像及标签
    imagePullPolicy: IfNotPresent # 镜像拉取策略同前
    command: # 容器启动命令(覆盖镜像默认的 CMD)
    - "/bin/sh" # 调用 sh 解释器
    - "-c" # 执行后续字符串中的命令
    - "sleep 36000" # 休眠 36000 秒(即 10 小时),保持容器运行
bash 复制代码
 kubectl apply -f pod-node.yaml

这时候可以看到这个pod现在并没有running而是Pending,这表示pod没有创建成功处于挂起状态,原因是在yaml配置文件中使用了nodeSelector,并添加了两个标签,当k8s调度的时候,整个集群当中没有任何节点有指定的标签,那么现在我在k8s-node-2上加上这两个指定标签,则k8s就会将这个pod调度到k8s-node-2上。

bash 复制代码
kubectl label nodes k8s-node-2 vm-type=gpu
kubectl label nodes k8s-node-2 region=zh-east

我先打第一个标签,然后再查看pod信息,发现打一个标签还是没有启动

然后打第二个标签,就会正常启动,少打一个标签都无法调度成功

3、nodeName和NodeSelector调度pod对比

k8s中 nodeNamenodeSelector 都是用于将 Pod 调度到特定节点的机制,但它们在调度方式、灵活性和使用场景上有显著差异。

对比维度 nodeName(指定节点) nodeSelector(节点选择器)
调度方式 硬性指定 ,直接绑定到特定节点名称,绕过调度器(Scheduler) 标签筛选,由调度器根据节点标签自动选择匹配的节点
核心机制 pod.spec.nodeName = "node-01" pod.spec.nodeSelector = {disktype: "ssd"}
典型场景 • 调试/测试,需要固定某个节点 • 自定义调度器场景 • 临时应急,快速将 Pod 指派到特定节点 • 按硬件类型调度(GPU/SSD 节点) • 环境隔离(生产/测试环境分离) • 按可用区/地域部署 • DaemonSet 过滤可部署节点
✅ 优势 • 配置极简 • 确定性高 ,100% 保证调度到目标节点 • 可绕过 Taints(污点)约束 灵活性强 ,按标签动态匹配 • 高可用 :节点故障时可调度到其他匹配节点 • 节点可分组管理,易于维护和扩展
❌ 劣势 节点不存在时 Pod 无法运行 ,甚至被自动删除 • 节点资源不足时 Pod 启动失败 (OOM/CPU 不足) • 节点名称在云环境中不可靠 (节点可能被替换/重命名) • 无高可用能力,单点故障风险高 无匹配标签时 Pod 无法调度 • 需要提前维护节点标签 • 仅支持精确匹配=),不支持复杂逻辑(与/或/排除)
  1. 官方推荐 :Kubernetes 官方推荐使用 nodeSelector 作为最简单的节点选择约束方式,而 nodeName 主要面向自定义调度器或高级用例

  2. 优先级 :若同时设置 nodeNamenodeSelectornodeName 优先级更高,Pod 会被强制调度到指定节点。

  3. 生产环境建议强烈不建议 在 Deployment 或 StatefulSet 等工作负载中设置 nodeName,应优先使用 nodeSelectornodeAffinity

  4. 进阶选择 :当 nodeSelector 的精确匹配无法满足需求时(如需要"或"逻辑、优先级偏好等),可升级使用 nodeAffinity(节点亲和性),它提供了更丰富的调度规则。

相关推荐
cg.family2 天前
K8s内部pod间的负载均衡原理
k8s
w200512244 天前
Pod管理
linux·服务器·云原生·容器·k8s·podman
国医中兴5 天前
电子病历的时序数据分析:ClickHouse在临床指标监控中的落地
微服务·云原生·容器·kubernetes·k8s
m0_525724725 天前
端到端 GitOps + 金丝雀流程测评报告
云原生·自动化·k8s·devops
tangyal6 天前
kubernetes(k8s)基础理论与集群部署
kubernetes·k8s·部署·node·理论·pod·集群cluster
深念Y7 天前
Makefile vs go run:Go 项目构建方式对比
java·开发语言·golang·k8s·编译·流水线·cicd
智码看视界8 天前
Day59-阿里云ACK实战:生产级K8s集群部署与运维
运维·阿里云·kubernetes·k8s·日志监控·容器运维·阿里云ack
养海绵宝宝的小蜗8 天前
Pod 管理总结
k8s
张洛闻Eren8 天前
云原生k8s【第六课】:K8s 访问控制
运维·docker·云原生·容器·kubernetes·k8s