Kubernetes Scheduler(简称k8s Scheduler)是Kubernetes集群中的一个核心组件,它负责将Pod调度到合适的Node上运行,以实现集群资源的优化分配和负载均衡。以下是对k8s Scheduler的详细介绍:
k8s Scheduler的调度流程主要包括以下几个关键步骤:
k8s Scheduler的调度算法和策略可以是多样化的,包括但不限于:
优先级调度:根据Pod的优先级和Node的资源情况,优先调度高优先级的Pod。
公平调度:尽量平衡各个Node的资源使用情况,避免资源过度集中或浪费。
权重调度:根据预设的权重因子,综合考虑多种因素进行调度决策。
节点亲和性:根据节点的标签或特性,将Pod调度到具有相似特性的节点上。
在Kubernetes(k8s)中,节点亲和性(Node Affinity)是一种控制Pod调度到特定节点的高级策略。通过定义节点亲和性规则,管理员可以确保Pod被调度到符合特定条件的节点上,从而实现资源优化、性能提升、故障隔离以及满足特定的合规或业务需求。
一、节点亲和性的基本概念
节点亲和性允许Pod根据节点的标签(Labels)和选择器(Selectors)来指定其应该被调度到的节点。这有助于将Pod与具有特定特征(如硬件类 型、地理位置、操作系统等)的节点关联起来。
二、节点亲和性的类型
节点亲和性可以分为两种类型:
三、节点亲和性的配置
节点亲和性的配置通常通过YAML文件实现,在Pod的spec字段下添加affinity字段,并设置nodeAffinity子字段。以下是一个简单的配置示例:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: my-container
image: my-image
在上述示例中,我们定义了一个Pod,它要求被调度到具有disktype=ssd标签的节点上。这是通过硬亲和性规则实现的,因此如果没有满足条件的 节点,Pod将不会被调度。
四、节点亲和性的应用场景
节点亲和性在多种场景下都非常有用,例如:
五、总结
Kubernetes的节点亲和性提供了一种灵活且强大的方式来控制Pod的调度行为。通过合理配置节点亲和性规则,管理员可以确保Pod被调度到符合特 定条件的节点上,从而实现资源优化、性能提升、故障隔离以及满足特定的合规或业务需求。
Pod亲和性/反亲和性:根据Pod之间的依赖关系或排斥关系,将相关的Pod调度到相同或不同的节点上。
在Kubernetes(简称K8S)中,Pod亲和性(Pod Affinity)是集群调度策略的一个重要组成部分,它允许用户指定某种规则,使得Pod更倾向 于被调度到满足特定条件的节点上运行,或者与已经在特定节点上运行的其他Pod部署在一起。以下是对K8S Pod亲和性的详细解释:
Pod亲和性主要用于处理Pod与Pod之间的关系,它允许Pod表达出希望与其相同或不同标签集的Pod共存于同一节点或拓扑域(如机架、可用区等) 的愿望。这种机制有助于优化资源使用、提高服务可靠性,并满足特定的应用程序需求。
- 二、Pod亲和性的类型
- Pod亲和性可以分为两种类型:
- 硬策略(requiredDuringSchedulingIgnoredDuringExecution):
必须满足条件,比较强硬。
如果没有满足条件的节点,调度器会不断重试,直到找到满足条件的节点为止。
一旦Pod被调度到某个节点,即使后续节点上的Pod标签发生变化,也不会影响已调度Pod的位置。
- 软策略(preferredDuringSchedulingIgnoredDuringExecution):
尽量满足条件,但不强制要求。
如果没有满足条件的节点,Pod仍然可以被调度到其他节点上。
同样,一旦Pod被调度到某个节点,后续节点上的Pod标签变化也不会影响已调度Pod的位置。
Pod亲和性的配置通常通过YAML文件实现,在Pod的spec字段下添加affinity字段,并设置podAffinity子字段。以下是一个简单的配置示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-app
topologyKey: kubernetes.io/hostname
在上述示例中,我们定义了一个Deployment,它包含两个副本的Pod。这些Pod通过Pod亲和性的硬策略被要求调度到与标签app=my-app相同的Pod 所在的节点上。topologyKey设置为kubernetes.io/hostname,表示Pod将被调度到与已存在Pod相同的物理节点上。
Pod亲和性在多种场景下都非常有用,例如:
1. 数据本地性:对于需要频繁访问本地存储的Pod,可以将其与存储服务所在的Pod部署在同一节点上,以减少网络延迟和提高性能。
2. 服务依赖:当Pod之间存在服务依赖关系时,可以使用Pod亲和性将它们部署在同一节点上,以确保服务的可用性和稳定性。
3. 资源优化:通过Pod亲和性,可以将具有相似资源需求的Pod部署在同一节点上,以优化资源使用并减少资源浪费。
在Kubernetes(k8s)中,Scheduler的预选算法是Pod调度过程中的一个重要阶段,负责从集群中所有可用的节点中筛选出能够满足Pod资源需求和其他特定条件的候选节点。这一过程主要基于一系列的预选策略(Predicates)进行。以下是关于k8s Scheduler预选算法的详细解析:
预选算法的工作流程
获取节点列表:
遍历节点并筛选:
默认的预选策略
Kubernetes默认加载了多个预选策略,包括但不限于以下几个:
预选算法的优化
为了提高预选过程的效率,Kubernetes采用了多种优化措施,如:
自定义预选策略
总结
k8s Scheduler的预选算法是Pod调度过程中的关键一环,通过一系列的预选策略对集群中的节点进行筛选,从而确定能够满足Pod需求的候选节点。这一过程不仅确保了Pod能够被调度到合适的节点上运行,还通过多种优化措施提高了调度的效率和性能。
k8s Scheduler的优选算法是在预选算法之后进行的,旨在从通过预选的候选节点中选择出最优的节点来运行Pod。这一过程主要基于一系列的优选函数(Priorities)进行,每个函数都会为候选节点打分,最终选择得分最高的节点作为Pod的运行节点。
优选算法的工作流程
常用的优选函数
Kubernetes提供了多种内置的优选函数,包括但不限于以下几个:
自定义优选函数
综上所述,k8s Scheduler的优选算法通过一系列的优选函数为候选节点打分,并选择得分最高的节点作为Pod的运行节点,从而实现了Pod的优化调度。
Kubernetes支持通过自定义调度器来满足特定的调度需求。开发者可以根据业务需求编写自定义调度器,并将其集成到Kubernetes集群中。Kubernetes提供了调度器框架(Scheduler Framework),简化了自定义调度器的开发。
示例:
创建一个pod
vim 01.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myapp
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
schedulerName: my-scheduler
containers:
- image: wangyanglinux/myapp:v1.0
name: myapp
#一直pending状态 因为没有名为my-scheduler的调度器
[root@master Scheduler]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-75cdc5c7df-7dj56 0/1 Pending 0 4m33s
解决方案
# 在 kubernetes Master 节点开启 apiServer 的代理
[root@master Scheduler]# kubectl proxy --port=8001
Starting to serve on 127.0.0.1:8001
#将当前的apiservice的服务端点暴露出来,暴露出来的端点http直接访问
基于 shell 编写一个自定义调度器
vi my-scheduler.sh
#!/bin/bash
#制定当前服务器地址
SERVER='localhost:8001'
while true;
do
for PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | select(.spec.schedulerName =="my-scheduler") | select(.spec.nodeName == null) | .metadata.name' | tr -d '"')
do
NODES=($(kubectl --server $SERVER get nodes -o json | jq '.items[].metadata.name' | tr -d '"'))
NUMNODES=${#NODES[@]}
CHOSEN=${NODES[$[ $RANDOM % $NUMNODES]]}
curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1","kind":"Binding","metadata": {"name":"'$PODNAME'"},"target": {"apiVersion":"v1","kind": "Node", "name": "'$CHOSEN'"}}' http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/
echo "Assigned $PODNAME to $CHOSEN"
done
sleep 1
done
[root@master Scheduler]# yum install -y epel-release
[root@master Scheduler]# yum install -y jq
[root@master Scheduler]# chmod a+x my-scheduler.sh
[root@master Scheduler]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-75cdc5c7df-8ldv9 0/1 Pending 0 18s
[root@master Scheduler]# ./my-scheduler.sh
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 201
}Assigned myapp-75cdc5c7df-gbt6t to master
[root@master calico]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-75cdc5c7df-gbt6t 1/1 Running 0 44s
在Kubernetes(k8s)中,污点(Taints)和容忍(Tolerations)是两种相互配合的机制,用于控制Pod的调度行为,确保Pod不会被调度到不合适的节点上。以下是对污点和容忍的详细解释:
污点是定义在节点(Node)上的键值对属性,用于让节点拒绝将Pod调度运行于其上,除非Pod有接纳节点污点的容忍度。污点的主要作用是标识节点具有某些不希望的属性,从而阻止Pod被调度到该节点上。
每个污点由一个key、一个可选的value以及一个effect组成,格式为key=value:effect。其中,value可以为空,而effect描述了污点对Pod的作用效果。
Effect的类型
NoSchedule:表示Kubernetes不会将Pod调度到具有该污点的节点上,但已经调度到该节点的Pod不受影响。
PreferNoSchedule:软策略版本的NoSchedule,表示Kubernetes将尽量避免将Pod调度到具有该污点的节点上,但不是强制的。
NoExecute:表示Kubernetes不仅不会将Pod调度到具有该污点的节点上,还会将已经存在于该节点的Pod驱逐出去。
PreferNoSchedule: 表示k8s将尽量避免将pod调度到具有该污点的Node上
设置与去除
污点可以通过kubectl taint命令进行设置和去除。例如,设置污点使用kubectl taint nodes =:命令,去除污点则使用kubectl taint nodes :-命令。
#设置污点
kubectl taint nodes nodeName key=value1:NoSchedule
# 查找污点
kubectl describe node nodeName
Taints: node-role.kubernetes.io/control-plane:NoSchedule
# 删除污点
kubectl taint nodes nodeName key=value1:NoSchedule-
容忍是定义在Pod上的键值对属性,用于配置Pod可以容忍哪些污点。只有当Pod具有对节点污点的容忍度时,它才有可能被调度到该节点上。
每个容忍由一个key、一个可选的operator、一个可选的value以及一个effect组成。其中,operator用于指定与污点value的比较方式,默认为Equal;value用于与污点的value进行匹配;effect则指定了容忍的污点效果。
匹配规则
如果operator是Exists,则无需指定value,表示Pod可以容忍所有具有该key的污点。
如果operator是Equal,则Pod的容忍必须与污点的key和value都匹配。
如果不指定operator,则默认为Equal。
示例
apiVersion: v1
kind: Pod
metadata:
name: tolerant-pod
spec:
containers:
- name: nginx-container
image: nginx:latest
tolerations:
- key: "special"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
tolerationSeconds: 3600 # 3600秒后驱除pod
当不指定value时,表示容忍所有污点value
- key: "key2"
operator: "Exists"
effect: "NoSchedule"
当不指定key值时,表示容忍所有的污点key
tolerations:
- operator: "Exists"
当不指定effect值时,表示容忍所有污点的作用
tolerations:
- key: "key"
operator: "Exists"
多个master存在,防止资源浪费,使用一下命令可将pod部署至master
kubectl taint nodes nodeName node-role.kubenetes.io/master=:NoSchedule-
kubectl taint nodes nodeName node-role.kubenetes.io/master=:PreferNoSchedule
在上面的示例中,Pod tolerant-pod 定义了一个容忍度,表示它可以被调度到具有special=gpu:NoSchedule污点的节点上。
设置pod.spec.nodeName 指定pod强制调度到master上
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodename-test
spec:
replicas: 7
selector:
matchLabels:
app: nodename
template:
metadata:
labels:
app: nodename
spec:
nodeName: master
containers:
- name: myweb
image: wangyanglinux/myapp:v1.0
ports:
- containerPort: 80
设置pod.spec.nodeSelector 通过label-selecotr机制选择节点,由Scheduler策略匹配label,而后调度pod到目标节点,该规则属于强制约束 master如果有noSchedule污点选项 则master有label type=nodeselect也不能在master上创建
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodeselect-test
spec:
replicas: 2
selector: # 选择器
matchLabels:
app: nodeselect
template:
metadata:
labels:
app: nodeselect
spec:
nodeSelector:
type: nodeselect # key:value 节点需要有此标签
containers:
- name: myweb
image: wangyanglinux/myapp:v1.0
ports:
- containerPort: 80
污点和容忍是Kubernetes中用于控制Pod调度行为的两种重要机制。通过给节点设置污点,可以阻止不希望的Pod被调度到该节点上;通过在Pod上定义容忍度,可以使得Pod能够容忍节点的污点,从而被调度到该节点上。这两种机制相互配合,实现了对Pod调度行为的灵活控制。
综上所述,k8s Scheduler是Kubernetes集群中至关重要的组件之一,它通过精细的调度策略和高可用性配置,确保了集群资源的合理分配和高效利用。