在Kubernetes中,Pod的调度是一个核心且复杂的过程,它直接决定了应用负载在集群中的分布与运行状态。掌握影响调度的关键因素,对于集群稳定性、资源利用率和应用性能都至关重要。本文将深入解析直接影响Pod调度的六大核心机制,包括 nodeName、hostNetwork、hostPort、resources、Taints(污点)与 Tolerations(容忍),并通过实战案例帮助你彻底搞懂它们的工作原理和使用场景。如果你想了解更多关于容器化和集群管理的知识,可以参考云栈社区上的其他文章。
1 nodeName:强制调度到指定节点
1.1 作用及说明
nodeName 用于强制指定 Pod 应该运行在特定的节点上。它绕过了 Kubernetes 调度器,直接由对应节点的 Kubelet 接管 Pod 的生命周期。
[root@k8s-master01 ~]# kubectl explain pod.spec.nodeName
KIND: Pod
VERSION: v1
FIELD: nodeName <string>
DESCRIPTION:
NodeName indicates in which node this pod is scheduled. If empty, this pod
is a candidate for scheduling by the scheduler defined in schedulerName.
Once this field is set, the kubelet for this node becomes responsible
for the lifecycle of this pod. This field should not be used to express a desire
for the pod to be scheduled on a specific node.
https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodename
常见应用场景:某些应用需要在特定硬件上运行,比如 GPU 或特定的网络接口。在调试阶段方便日志、数据等信息的收集,调度到指定的节点。
1.2 nodeName实战案例
#资源清单
[root@k8s-master01 /data/manifests/pod-scheduler]# cat 01-scheduler-nodeName.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-deploy-nodename
spec:
replicas: 3
selector:
matchLabels:
app: dinginx-deploy-nodename
template:
metadata:
labels:
app: dinginx-deploy-nodename
spec:
# 指定节点进行调度,此过程scheduler不参与调度的;
# 节点不存在,资源不足pod资源不会被调度;
nodeName: k8s-node01.dinginx.org
containers:
- image: harbor.dinginx.org/dinginx/nginx:latest
name: nginx
创建后验证资源,可以看到所有 Pod 实例都被强制调度到了指定的 k8s-node01.dinginx.org 节点上。
#验证资源
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dinginx-deploy-nodename-65d675bc8-2mck2 1/1 Running 0 8s 10.244.1.232 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-nodename-65d675bc8-85vmf 1/1 Running 0 8s 10.244.1.231 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-nodename-65d675bc8-kz4qq 1/1 Running 0 8s 10.244.1.230 k8s-node01.dinginx.org <none> <none>
注意:nodeName 是强绑定,如果目标节点不存在或资源不足,Pod 将处于 Pending 状态,调度器不会将其调度到其他节点。
2 hostNetwork:共享宿主机网络
2.1 说明及作用
hostNetwork: true 表示 Pod 直接使用宿主机网络命名空间,而不是通过 CNI 插件创建的虚拟网络。这意味着 Pod 的 IP 地址就是宿主机的 IP 地址。
[root@k8s-master01 ~]# kubectl explain deploy.spec.template.spec.hostNetwork
GROUP: apps
KIND: Deployment
VERSION: v1
FIELD: hostNetwork <boolean>
DESCRIPTION:
Host networking requested for this pod. Use the host‘s network namespace.
When using HostNetwork you should specify ports so the scheduler is aware.
When `hostNetwork` is true, specified `hostPort` fields in port definitions
must match `containerPort`, and unspecified `hostPort` fields in port
definitions are defaulted to match `containerPort`. Default to false.
也就是说开启 hostNetwork 后,Pod 会共享宿主机网络命名空间,而不是使用独立的 Pod 网络。
2.2 hostNetwork实战案例
#资源清单
[root@k8s-master01 /data/manifests/pod-scheduler]# cat 02-scheduler-hostNetwork.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-deploy-hostnetwork
spec:
replicas: 3
selector:
matchLabels:
app: dinginx-deploy-hostnetwork
template:
metadata:
labels:
app: dinginx-deploy-hostnetwork
spec:
# 直接使用宿主机网卡
hostNetwork: true
# 同时建议设置,因为默认 hostNetwork 会继承宿主机 DNS。
dnsPolicy: ClusterFirstWithHostNet
containers:
- image: harbor.dinginx.org/dinginx/nginx:latest
name: nginx
应用该配置后查看资源状态,你会发现一个有趣的现象。
#查看资源,会发现一个资源失败
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dinginx-deploy-hostnetwork-7c8d57d48d-gqsxj 1/1 Running 0 13s 11.0.1.12 k8s-node02.dinginx.org <none> <none>
dinginx-deploy-hostnetwork-7c8d57d48d-scfxj 1/1 Running 0 13s 11.0.1.11 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-hostnetwork-7c8d57d48d-t9pnd 0/1 Error 1 (9s ago) 13s 11.0.1.12 k8s-node02.dinginx.org <none> <none>
注意:hostNetwork 模式下,Pod 使用宿主机的网络栈和端口。同一节点上如果调度了多个使用相同端口(如Nginx默认80端口)的 Pod,虽然调度可能成功,但会因为端口冲突导致容器启动失败。在设计和调度这类涉及到宿主机资源和计算力的应用时,需要格外小心。
3 hostPort:映射宿主机端口
3.1 作用及说明
hostPort 将容器端口映射到宿主机的一个特定端口上。这使得外部客户端可以通过 宿主机IP:hostPort 直接访问 Pod 内的服务,而无需经过 Service。
[root@k8s-master01 ~]# kubectl explain deploy.spec.template.spec.containers.ports.hostPort
GROUP: apps
KIND: Deployment
VERSION: v1
FIELD: hostPort <integer>
DESCRIPTION:
Number of port to expose on the host. If specified, this must be a valid
port number, 0 < x < 65536. If HostNetwork is specified, this must match
ContainerPort. Most containers do not need this.
3.2 hostPort实战案例
#资源清单
[root@k8s-master01 /data/manifests/pod-scheduler]# cat 03-scheduler-hostPort.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-deploy-hostport
spec:
replicas: 3
selector:
matchLabels:
app: dinginx-deploy-hostport
template:
metadata:
labels:
app: dinginx-deploy-hostport
spec:
containers:
- image: harbor.dinginx.org/dinginx/nginx:latest
name: nginx
ports:
- containerPort: 80
# 宿主机端口被占用则不能被调度
hostPort: 8080
应用后验证,会发现一个 Pod 处于 Pending 状态。
#验证资源,会发现dinginx-deploy-hostport-796796db98-rld88容器Pending状态
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dinginx-deploy-hostport-796796db98-bc4cm 1/1 Running 0 7s 10.244.1.234 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-hostport-796796db98-rld88 0/1 Pending 0 7s <none> <none> <none> <none>
dinginx-deploy-hostport-796796db98-x6556 1/1 Running 0 7s 10.244.2.105 k8s-node02.dinginx.org <none> <none>
查看该 Pod 的事件日志,可以明确看到调度失败的原因。
#查看日志
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe pods dinginx-deploy-hostport-796796db98-rld88
#...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 71s default-scheduler 0/3 nodes are available: 1 node(s) had untolerated taint(s), 2 node(s) didn‘t have free ports for the requested pod ports. no new claims to deallocate, preemption: 0/3 nodes are available: 1 Preemption is not helpful for scheduling, 2 No preemption victims found for incoming pod.
# 表示node上没有空闲的ports
调度影响:Kubernetes 调度器会检查每个节点上请求的 hostPort 是否可用。如果某个节点上该端口已被占用(例如被另一个 Pod 或系统进程占用),则 Pod 无法调度到该节点。当所有节点都无可用端口时,Pod 就会陷入 Pending 状态。成功调度的 Pod 则可以通过宿主机 IP 和端口直接访问。
#访问方式,curl http://hostip:8080 -Ik
[root@k8s-master01 /data/manifests/pod-scheduler]# curl k8s-node02.dinginx.org:8080 -Ik
HTTP/1.1 200 OK
Server: nginx/1.29.3
Date: Mon, 09 Feb 2026 06:45:00 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Oct 2025 12:05:10 GMT
Connection: keep-alive
ETag: "6900b176-267"
Accept-Ranges: bytes
4 resources:资源请求与限制
4.1 resources作用及说明
resources 用于声明 Pod 对 CPU 和内存的资源请求(requests)与限制(limits)。这是调度器做出决策的最关键依据之一,直接影响 Pod 能否被调度、运行是否稳定,以及节点资源是否会被过度使用导致雪崩。
[root@k8s-master01 ~]# kubectl explain deploy.spec.template.spec.containers.resources
GROUP: apps
KIND: Deployment
VERSION: v1
FIELD: resources <ResourceRequirements>
DESCRIPTION:
Compute Resources required by this container. Cannot be updated. More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
ResourceRequirements describes the compute resource requirements.
FIELDS:
claims <[]ResourceClaim>
Claims lists the names of resources, defined in spec.resourceClaims, that
are used by this container.
This field depends on the DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
limits <map[string]Quantity> #简单来说 Pod 最多能使用多少资源
Limits describes the maximum amount of compute resources allowed. More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
requests <map[string]Quantity> #简单来说 Pod 至少需要多少资源
Requests describes the minimum amount of compute resources required. If
Requests is omitted for a container, it defaults to Limits if that is
explicitly specified, otherwise to an implementation-defined value. Requests
cannot exceed Limits. More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
#如果不限制requests的值,则会和limits保持一致
- requests:调度器根据此值为 Pod 选择有足够“可分配”资源的节点。这是 Pod 的“资源保障”。
- limits:容器运行时(如 containerd)根据此值设置 cgroup 限制。
- CPU:超过限制会被限速(throttling)。
- 内存:超过限制可能导致容器被 OOMKilled。
4.2 resources实战案例
#资源清单
[root@k8s-master01 /data/manifests/pod-scheduler]# cat 04-scheduler-resources.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-deploy-resources
spec:
replicas: 3
selector:
matchLabels:
app: dinginx-deploy-resources
template:
metadata:
labels:
app: dinginx-deploy-resources
spec:
containers:
- image: harbor.dinginx.org/dinginx/nginx:latest
name: nginx
resources:
# 要求最多cpu:1;内存使用512M
# 如果不限制requests的值,则会和limits保持一致
# 设置资源上限可以超过物理节点,但实际使用建议参考物理节点大小。
limits:
cpu: 1
memory: "512Mi"
# 要求至少cpu:0.5;内存256M
requests:
cpu: 0.5
memory: "256Mi"
应用配置并验证,可以看到 Pod 被成功调度。通过 describe 命令查看详细信息,确认资源配置已生效。
#验证资源
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dinginx-deploy-resources-84c7587cc6-bj5xz 1/1 Running 0 64s 10.244.1.239 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-resources-84c7587cc6-g8c4z 1/1 Running 0 63s 10.244.1.240 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-resources-84c7587cc6-ltzwz 1/1 Running 0 65s 10.244.2.131 k8s-node02.dinginx.org <none> <none>
#查看容器详细信息,资源配额符合预期
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe pods dinginx-deploy-resources-84c7587cc6-ltzwz
#...
Containers:
nginx:
#...
Limits:
cpu: 1
memory: 512Mi
Requests:
cpu: 500m
memory: 256Mi
5 Taints(污点):节点主动拒绝Pod
5.1 Taints作用及说明
Taint(污点)是施加在节点(Node)上的属性,其核心作用是让节点能够“主动拒绝”不能“容忍”该污点的 Pod 调度上来。这是一种节点驱赶 Pod 的机制。
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint --help
#...
Usage:
kubectl taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N [options]
#支持三种effect(影响度):
NoSchedule:
👉 不允许新 Pod 调度进来,已经在的 Pod 不动,没容忍的新 Pod 直接拒绝
PreferNoSchedule
👉尽量不调度,但不是强制,实在没节点,也可能调度
NoExecute
👉 直接驱逐 Pod,
没容忍的 Pod:已在运行 → 被踢走、新 Pod → 禁止调度
5.2 查看节点污点并给节点打污点
首先查看集群节点的污点情况。
#查看集群污点情况
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe nodes |grep -i taints -A5
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: k8s-master01.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:34:05 +0800
--
Taints: <none>
Unschedulable: false
Lease:
HolderIdentity: k8s-node01.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:34:04 +0800
--
Taints: <none>
Unschedulable: false
Lease:
HolderIdentity: k8s-node02.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:33:56 +0800
给 k8s-node01 打上一个污点。
#给节点打污点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint node k8s-node01.dinginx.org app=dinginx:NoSchedule
node/k8s-node01.dinginx.org tainted
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe nodes k8s-node01.dinginx.org |grep -i taints -A5
Taints: app=dinginx:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: k8s-node01.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:38:18 +0800
此时,创建一个没有任何容忍配置的新 Deployment,其 Pod 将不会被调度到 k8s-node01。
#创建新资源
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl apply -f 05-scheduler-Taints.yaml
deployment.apps/dinginx-deploy-taints created
#新创建的资源被调度到k8s-node02节点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dinginx-deploy-resources-84c7587cc6-bj5xz 1/1 Running 0 3h39m 10.244.1.239 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-resources-84c7587cc6-g8c4z 1/1 Running 0 3h39m 10.244.1.240 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-resources-84c7587cc6-ltzwz 1/1 Running 0 3h39m 10.244.2.131 k8s-node02.dinginx.org <none> <none>
dinginx-deploy-taints-bf46fb57c-7t9l8 1/1 Running 0 4s 10.244.2.91 k8s-node02.dinginx.org <none> <none>
dinginx-deploy-taints-bf46fb57c-r7jkv 1/1 Running 0 4s 10.244.2.92 k8s-node02.dinginx.org <none> <none>
dinginx-deploy-taints-bf46fb57c-zk668 1/1 Running 0 4s 10.244.2.90 k8s-node02.dinginx.org <none> <none>
注意:污点对使用 nodeName 强制调度的 Pod 不生效。
5.3 删除与修改污点
删除污点需要在污点声明末尾加上 -。
#查看节点污点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe nodes k8s-master01.dinginx.org|grep -A5 Taints
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: k8s-master01.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:44:49 +0800
#删除污点,最好使用全称
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint node k8s-master01.dinginx.org node-role.kubernetes.io/control-plane:NoSchedule-
node/k8s-master01.dinginx.org untainted
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe nodes k8s-master01.dinginx.org|grep -A5 Taints
Taints: <none> #查看污点已删除
Unschedulable: false
Lease:
HolderIdentity: k8s-master01.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:46:20 +0800
要修改一个已存在的污点(相同 Key 和 Effect),需要使用 --overwrite 参数。
# 打污点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint node k8s-master01.dinginx.org app=dinginx001:NoSchedule
node/k8s-master01.dinginx.org tainted
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint node k8s-master01.dinginx.org app=dinginx002:NoSchedule
error: node k8s-master01.dinginx.org already has app taint(s) with same effect(s) and --overwrite is false
# 需加上--overwrite
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint node k8s-master01.dinginx.org app=dinginx002:NoSchedule --overwrite
node/k8s-master01.dinginx.org modified
# 查看污点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe nodes k8s-master01.dinginx.org|grep -A5 Taints
Taints: app=dinginx002:NoSchedule #污点已修改
Unschedulable: false
Lease:
HolderIdentity: k8s-master01.dinginx.org
AcquireTime: <unset>
RenewTime: Mon, 09 Feb 2026 18:50:15 +0800
# 影响度不同,即使key=value相同,也属于不同的污点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl taint node k8s-master01.dinginx.org app=dinginx001:PreferNoSchedule
node/k8s-master01.dinginx.org tainted
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl describe nodes k8s-master01.dinginx.org|grep -A5 Taints
Taints: app=dinginx002:NoSchedule
app=dinginx001:PreferNoSchedule
Unschedulable: false
Lease:
HolderIdentity: k8s-master01.dinginx.org
AcquireTime: <unset>
三种影响度(Effect)的实战效果略有不同,但核心逻辑一致:污点是节点设置的“准入条件”。
6 污点容忍(Tolerations):Pod的通行证
6.1 作用及说明
Toleration(容忍)是 Pod 级别的属性。当节点上存在 Taint(污点)时,只有声明了相应 Toleration 的 Pod 才被允许调度到该节点,或继续在该节点上运行。可以把它理解为 Pod 进入特定“污染区”的通行证。
[root@k8s-master01 ~]# kubectl explain deploy.spec.template.spec.tolerations
GROUP: apps
KIND: Deployment
VERSION: v1
FIELD: tolerations <[]Toleration>
DESCRIPTION:
If specified, the pod‘s tolerations.
The pod this Toleration is attached to tolerates any taint that matches the
triple <key,value,effect> using the matching operator <operator>.
FIELDS:
effect <string>
enum: NoExecute, NoSchedule, PreferNoSchedule
Effect indicates the taint effect to match. Empty means match all taint
effects. When specified, allowed values are NoSchedule, PreferNoSchedule and
NoExecute.
...
6.2 Toleration实战案例
假设集群节点有如下污点:
#为节点打新的污点
[root@k8s-master01 ~]# kubectl describe nodes |grep Taints -A2
Taints: app=dinginx002:NoSchedule
Unschedulable: false
Lease:
--
Taints: app=dinginx:NoSchedule
top=dinginx111:NoSchedule
Unschedulable: false
--
Taints: top=dinginx111:NoSchedule
app=dinginx110:PreferNoSchedule
Unschedulable: false
如果不配置容忍,创建新 Pod 将会失败。
现在,创建一个带有容忍配置的 Deployment,使其能够调度到指定的节点。
#资源清单
[root@k8s-master01 /data/manifests/pod-scheduler]# cat 06-scheduler-Toleration.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-deploy-toleration
spec:
replicas: 3
selector:
matchLabels:
app: dinginx-deploy-toleration
template:
metadata:
labels:
app: dinginx-deploy-toleration
spec:
tolerations:
# 配置node01节点的容忍
- key: "app"
value: "dinginx"
effect: "NoSchedule"
# 配置node02节点的容忍
- key: "top"
value: "dinginx111"
effect: "NoSchedule"
# 无视污点,直接无视所有污点,不推荐使用。
#- operator: Exists
containers:
- image: harbor.dinginx.org/dinginx/nginx:latest
name: nginx
应用该配置后查看 Pod 分布。由于配置了容忍,Pod 可以调度到 k8s-node01。k8s-node02 虽然有匹配的 top=dinginx111:NoSchedule 污点,但因为同时存在 app=dinginx110:PreferNoSchedule 污点,调度器会优先选择没有 PreferNoSchedule 污点的节点(即 k8s-node01)。
#创建资源
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl apply -f 06-scheduler-Toleration.yaml
#查看资源,k8s-node02因存在PreferNoSchedule,故不会优先调度到此节点
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dinginx-deploy-toleration-7c6f965c5c-8v4nq 1/1 Running 0 58s 10.244.1.250 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-toleration-7c6f965c5c-klsj5 1/1 Running 0 58s 10.244.1.251 k8s-node01.dinginx.org <none> <none>
dinginx-deploy-toleration-7c6f965c5c-lbcff 1/1 Running 0 56s 10.244.1.252 k8s-node01.dinginx.org <none> <none>
总结:污点(Taints)与容忍(Tolerations)共同构成了 Kubernetes 中一套强大的 Pod 与节点间“互选”机制,常用于实现专用节点、故障隔离、灰度发布等高级调度场景。理解并熟练运用这六大核心调度要素,是掌握 Kubernetes 集群管理能力的关键一步。