Pod调度
Pod 调度是 Kubernetes 中的一个核心概念,它涉及到 Kubernetes 集群中的一个或多个节点上调度运行 Pod 的过程。Pod 是 Kubernetes 中的最小部署单元,通常包含一个或多个容器。调度过程决定了哪个 Pod 应该在哪个节点上运行,以满足集群的资源需求和策略约束。
在Kubernetes中,Pod的调度是一个复杂的过程,涉及到多种因素和规则。为了控制Pod运行在特定的节点上,或者满足特定的亲和性要求,Kubernetes提供了以下几种调度方式:
-
自动调度:这是默认的调度方式,Scheduler会根据集群的资源状况和Pod的资源需求,自动选择最合适的节点来运行Pod。
-
定向调度:
-
NodeName:通过指定Pod应该运行在哪个节点上,可以强制Pod运行在特定的Node上。这可以通过在Pod的配置中设置
spec.nodeName
属性来实现。 -
NodeSelector:允许你根据节点的标签(Labels)来选择节点。通过在Pod的配置中设置
spec.nodeSelector
属性,可以指定Pod应该运行在带有特定标签的节点上。
-
-
亲和性调度:
-
NodeAffinity:这是一种更复杂的亲和性规则,它允许你根据节点的属性来选择节点。NodeAffinity可以指定必须满足的条件(requiredDuringSchedulingIgnoredDuringExecution)或者仅仅是偏好(preferredDuringSchedulingIgnoredDuringExecution)。
-
PodAffinity:允许你根据其他Pod的属性来选择节点,确保Pod被调度到与某些其他Pod在同一节点上或者在不同的节点上,这取决于你定义的是affinity还是anti-affinity规则。
-
PodAntiAffinity:与PodAffinity相反,它确保Pod不会被调度到已经运行了具有匹配标签的Pod的节点上。
-
-
污点(Taints)和容忍(Tolerations):
-
Taints:是附加到节点上的一种标记,可以阻止没有相应容忍的Pod被调度到该节点上。
-
Tolerations:是Pod的一个属性,它允许Pod容忍(忽略)节点上的污点,从而可以被调度到这些节点上。
-
定向调度
定向调度,指的是利用在Pod上声明NodeName或者nodeSelector,以此将Pod调度到期望的node节点上。注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,只不过pod运行失败而已。
-
NodeName:当你在Pod的配置中指定了
nodeName
字段,你实际上是在告诉Kubernetes调度器,这个Pod必须被调度到具有该名称的特定节点上。如果该节点不存在,或者由于某种原因(如资源不足)无法在该节点上运行Pod,那么Pod将无法被调度,并且会保持在Pending状态。
测试:
定向调度到node1
[root@k8s-master ~]# vim pod-nodename.yaml
[root@k8s-master ~]# cat pod-nodename.yaml
---
apiVersion: v1
kind: Pod
metadata:name: pod-nodenamenamespace: dev
spec:nodeName: k8s-node1 #强制调度到node1containers:- name: nginximage: nginx:1.17.1[root@k8s-master ~]# kubectl apply -f pod-nodename.yaml
pod/pod-nodename created
[root@k8s-master ~]# kubectl get pods -n dev -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodename 0/1 ContainerCreating 0 6s <none> k8s-node1 <none> <none>
pod-nodename 1/1 Running 0 28s 10.244.36.74 k8s-node1 <none> <none>
^C[root@k8s-master ~]# kubectl describe pods pod-nodename -n dev
Name: pod-nodename
Namespace: dev
Priority: 0
Node: k8s-node1/192.168.58.232
Start Time: Wed, 15 Jan 2025 05:04:33 -0500
Labels: <none>
Annotations: cni.projectcalico.org/containerID: d34c6f83c9bd4d37cf9cdde8c252a547931f9c7c8b8bce0c329743e82b0e8789cni.projectcalico.org/podIP: 10.244.36.74/32cni.projectcalico.org/podIPs: 10.244.36.74/32
Status: Running
IP: 10.244.36.74
IPs:IP: 10.244.36.74
Containers:nginx:Container ID: docker://1c4e9ddb8478bbb8c5df49ea21034ebb574db6fbc4fe1676e6920ee2b475562fImage: nginx:1.17.1Image ID: docker-pullable://nginx@sha256:b4b9b3eee194703fc2fa8afa5b7510c77ae70cfba567af1376a573a967c03dbbPort: <none>Host Port: <none>State: RunningStarted: Wed, 15 Jan 2025 05:05:01 -0500Ready: TrueRestart Count: 0Environment: <none>Mounts:/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-xt7mq (ro)
Conditions:Type StatusInitialized True Ready True ContainersReady True PodScheduled True
Volumes:kube-api-access-xt7mq:Type: Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds: 3607ConfigMapName: kube-root-ca.crtConfigMapOptional: <nil>DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Pulling 61s kubelet Pulling image "nginx:1.17.1"Normal Pulled 37s kubelet Successfully pulled image "nginx:1.17.1" in 23.842724632sNormal Created 36s kubelet Created container nginxNormal Started 35s kubelet Started container nginx
定向调度到node3,虽然node3不存在,但是会强制调度到node3,但是容器不会启动
[root@k8s-master ~]# kubectl delete -f pod-nodename.yaml
pod "pod-nodename" deleted
[root@k8s-master ~]# kubectl apply -f pod-nodename.yaml
pod/pod-nodename created
[root@k8s-master ~]# kubectl get pods -n dev -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodename 0/1 Pending 0 5s <none> k8s-node3 <none> <none>
pod-nodename 0/1 Terminating 0 41s <none> k8s-node3 <none> <none>
pod-nodename 0/1 Terminating 0 41s <none> k8s-node3 <none> <none>
^C[root@k8s-master ~]#
[root@k8s-master ~]#
[root@k8s-master ~]# cat pod-nodename.yaml
---
apiVersion: v1
kind: Pod
metadata:name: pod-nodenamenamespace: dev
spec:nodeName: k8s-node3 #强制调度到node3containers:- name: nginximage: nginx:1.17.1
-
NodeSelector 指导调度:
nodeSelector
是一种标签选择器,它允许你指定一组标签,调度器会根据这些标签选择一个合适的节点来运行 Pod。如果存在多个带有匹配标签的节点,调度器会根据其他调度策略(如亲和性、反亲和性规则)来选择最佳节点。如果找不到任何匹配的节点,Pod 同样会处于 Pending 状态。
[root@k8s-master ~]# kubectl label nodes k8s-node1 nodeenv=dev
node/k8s-node1 labeled
[root@k8s-master ~]# kubectl label nodes k8s-node2 nodeenv=test
node/k8s-node2 labeled
[root@k8s-master ~]# vim pod-nodeselector.yaml
[root@k8s-master ~]# kubectl apply -f pod-nodeselector.yaml
pod/pod-nodeselector created
[root@k8s-master ~]# kubectl get pods -n dev
No resources found in dev namespace.
[root@k8s-master ~]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
pod-nodeselector 1/1 Running 0 28s
[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodeselector 1/1 Running 0 35s 10.244.36.75 k8s-node1 <none> <none>
[root@k8s-master ~]# cat pod-nodeselector.yaml
---
apiVersion: v1
kind: Pod
metadata:name: pod-nodeselectornamespace: test
spec:nodeSelector:nodeenv: devcontainers:- name: nginximage: nginx:1.17.1
- 如果到调度到一个没有的标签会调度失败
这里调度到了标签为dev1的node进行测试,但是没有这个dev1的node
[root@k8s-master ~]# vim pod-nodeselector.yaml
[root@k8s-master ~]# kubectl delete -f pod-nodeselector.yaml
pod "pod-nodeselector" deleted
[root@k8s-master ~]# kubectl apply -f pod-nodeselector.yaml
pod/pod-nodeselector created
[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodeselector 0/1 Pending 0 6s <none> <none> <none> <none>
[root@k8s-master ~]# kubectl get pods -n test -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodeselector 0/1 Pending 0 13s <none> <none> <none> <none>
^C[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodeselector 0/1 Pending 0 2m5s <none> <none> <none>
[root@k8s-master ~]# cat pod-nodeselector.yaml
---
apiVersion: v1
kind: Pod
metadata:name: pod-nodeselectornamespace: test
spec:nodeSelector:nodeenv: dev1containers:- name: nginximage: nginx:1.17.1