K8S入门篇-资源调度
作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/16829271.html
目录
一、Job
1 Job可以干什么
二、CronJob
2.1 创建CronJob
2.2 CronJob参数
2.3 suspend参数测试
三、InitContainer
3.1 初始化容器的用途
3.2 Init容器和PostStart的区别
3.3 Init容器和普通容器的区别
3.4 Init容器配置解析
3.5 初始化容器示例
四、临时容器(EphemeralContainers)
五、污点和容忍
5.1 调度的场景
5.2 什么是污点和容忍度?
5.3 污点和容忍度的作用?
5.4 给节点打污点
5.5 在pod 中定义容忍度
5.6 toleration实例
5.7 多个污点的匹配原则
5.8 设置NoExcute 的驱逐时间
5.9 容忍的匹配方式
5.10 基于污点的驱逐
六、affinity
6.1 将pod指派给node
6.2 亲和性与反亲和性
6.2 pod间亲和和反亲和
一、Job
1 Job可以干什么
Job可以干什么?在容器启动或退出时做一些任务。Job可以并行执行。
1、需要等待后执行的任务
2、导入SQL文件
3、创建用户、清理表
........等等
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | cat job-pi.yaml apiVersion: batch /v1 kind: Job metadata: labels: job-name: echo -pi name: echo -pi namespace: default spec: #suspend: true # 1.21+ #ttlSecondsAfterFinished: 100 backoffLimit: 4 completions: 10 parallelism: 3 template: spec: containers: - name: pi image: perl:5.34.0 command : [ "perl" , "-Mbignum=bpi" , "-wle" , "print bpi(2000)" ] imagePullPolicy: Always resources: {} restartPolicy: Never |
查看job:
注意事项:
二、CronJob
CronJob用于以时间为基准周期性地执行任务,这些自动化任务和运行在Linux或UNIX系统上的CronJob一样。CronJob对于创建定期和重复任务非常有用,例如执行备份任务、周期性调度程序接口、发送电子邮件等。
对于Kubernetes 1.8以前的版本,需要添加--runtime-config=batch/v2alpha1=true参数至APIServer中,然后重启APIServer和Controller Manager用于启用API,对于1.8以后的版本无须修改任何参数,可以直接使用,本节的示例基于1.8以上的版本。
2.1 创建CronJob
创建CronJob有两种方式,一种是直接使用kubectl创建,一种是使用yaml文件创建。
使用kubectl创建CronJob的命令如下:
1 | kubectl run hello --schedule= "*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster" |
对应的yaml文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | apiVersion: batch /v1beta1 kind: CronJob metadata: name: hello spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: hello image: busybox args: - /bin/sh - -c - date ; echo Hello from the Kubernetes cluster restartPolicy: OnFailure |
本例创建一个每分钟执行一次、打印当前时间和Hello from the Kubernetes cluster的计划任务。
查看创建的CronJob:
kubectl get cj
kubectl logs hello-27779598-pzznh
2.2 CronJob参数
2.3 suspend参数测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | apiVersion: batch /v1beta1 kind: CronJob metadata: name: hello spec: schedule: "*/1 * * * *" suspend: true #加上suspend参数 jobTemplate: spec: template: spec: containers: - name: hello image: busybox args: - /bin/sh - -c - date ; echo Hello from the Kubernetes cluster restartPolicy: OnFailure |
再次查看cronjob,超过1分钟后,也没有继续执行:
查看是否被挂起:
kubectl get cronjob/hello -oyaml
恢复挂起:
1 | kubectl patch cronjob /hello -- type =strategic --patch '{"spec":{"suspend":false}}' |
再次查看是否被挂起:
三、InitContainer
3.1 初始化容器的用途
在主应用启动之前,做一些初始化的操作,比如创建文件、修改内核参数、等待依赖程序启动或其他需要在主程序启动之前需要做的工作。
3.2 Init容器和PostStart的区别
PostStart:依赖主应用的环境,而且并不一定先于Command运行【如果执行失败,则主容器会不断重启】
InitContainer:不依赖主应用的环境,可以有更高的权限和更多的工具,一定会在主应用启动之前完成【如果执行失败的话,主容器是不会执行的】
3.3 Init容器和普通容器的区别
Init 容器与普通的容器非常像,除了如下几点:
- 它们总是运行到完成;
- 上一个运行完成才会运行下一个;
- 如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,但是Pod 对应的 restartPolicy 值为 Never,Kubernetes 不会重新启动 Pod。
- Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe
3.4 Init容器配置解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | apiVersion: apps /v1 kind: StatefulSet metadata: name: es-cluster spec: serviceName: elasticsearch replicas: 3 selector: matchLabels: app: elasticsearch template: metadata: labels: app: elasticsearch spec: volumes: - name: data #设置一个emptyDir类型的共享目录,用于容器间内容共享 emptyDir: {} initContainers: #定义初始化容器 - name: fix-permissions image: busybox #定义一个容器,用于修改目录权限 command : [ "sh" , "-c" , "chown -R 1000:1000 /usr/share/elasticsearch/data" ] securityContext: privileged: true volumeMounts: #进行目录挂载 - name: data mountPath: /usr/share/elasticsearch/data - name: increase-vm-max-map #修改内核参数 image: busybox command : [ "sysctl" , "-w" , "vm.max_map_count=262144" ] securityContext: privileged: true - name: increase-fd- ulimit # 修改内核参数 image: busybox command : [ "sh" , "-c" , "ulimit -n 65536" ] securityContext: privileged: true containers: #实际使用的容器 - name: elasticsearch #image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.3 image: dotbalo /es :2.4.6-cluster imagePullPolicy: Always resources: limits: cpu: 1000m requests: cpu: 100m ports: - containerPort: 9200 name: rest protocol: TCP - containerPort: 9300 name: inter-node protocol: TCP volumeMounts: - name: data #挂载数据目录,由于是以普通用户启动,所以没权限修改所属用户和组,需要通过初始化容器来进行所属组和用户 mountPath: /usr/share/elasticsearch/data env : - name: "cluster.name" value: "pscm-cluster" - name: "CLUSTER_NAME" value: "pscm-cluster" - name: "discovery.zen.minimum_master_nodes" value: "2" - name: "MINIMUM_MASTER_NODES" value: "2" - name: "node.name" valueFrom: fieldRef: fieldPath: metadata.name - name: "NODE_NAME" valueFrom: fieldRef: fieldPath: metadata.name - name: "discovery.zen.ping.unicast.hosts" value: "es-cluster-0.elasticsearch, es-cluster-1.elasticsearch, es-cluster-2.elasticsearch" #- name: ES_JAVA_OPTS # value: "-Xms512m -Xmx512m" |
3.5 初始化容器示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | apiVersion: apps /v1 kind: Deployment metadata: labels: app: test -init name: test -init namespace: kube-public spec: replicas: 3 selector: matchLabels: app: test -init template: metadata: labels: app: test -init spec: volumes: - name: data emptyDir: {} initContainers: - command : - sh - -c - touch /mnt/test-init .txt image: nginx imagePullPolicy: IfNotPresent name: init- touch volumeMounts: - name: data mountPath: /mnt - command : - sh - -c - for i in ` seq 1 100`; do echo $i; sleep 1; done image: nginx imagePullPolicy: IfNotPresent name: echo containers: - image: nginx imagePullPolicy: IfNotPresent name: test -init volumeMounts: - name: data mountPath: /mnt |
我们创建了2个初始化容器,第一个是创建一个文件;第二个是打印一串数字。
四、临时容器(EphemeralContainers)
在pod里面注入一个具有很多debug工具的容器,用于排查问题或故障。
开启临时容器功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Master节点 vi /usr/lib/systemd/system/kube-apiserver .service --feature-gates=EphemeralContainers= true vi /usr/lib/systemd/system/kube-controller-manager .service --feature-gates=EphemeralContainers= true vi /usr/lib/systemd/system/kube-scheduler .service --feature-gates=EphemeralContainers= true 所有节点 vi /usr/lib/systemd/system/kube-proxy .service --feature-gates=EphemeralContainers= true vi /etc/kubernetes/kubelet-conf .yml featureGates: EphemeralContainers: true 重启所有服务 System restart kube-apiserver kube-controller-manager kube-scheduler kube-proxy kubelet |
临时容器使用
1 | K8s 1.20+ kubectl debug redis-new-5b577b46c7-2jv4j -ti --image=debug-tools |
五、污点和容忍
5.1 调度的场景
Master节点:保证master组件正常运行,一般不建议生产pod调度到master上。
新增节点:灰度一些pod上来看看是否正常
维护节点:节点维护时,临时不让新的pod调度上来
特殊节点:比如ssd机器、GPU机器等特殊属性的节点,只能指定pod调度上来
5.2 什么是污点和容忍度?
污点(Taint) 是应用在节点之上的,从这个名字就可以看出来,是为了排斥pod 所存在的。
容忍度(Toleration)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。
5.3 污点和容忍度的作用?
Taint(污点)和 Toleration(容忍)可以作用于node和 pod 上,其目的是优化pod在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有taint的node和pod是互斥关系,而具有节点亲和性关系的node和pod是相吸的。另外还有可以给node节点设置label,通过给pod设置nodeSelector将pod调度到具有匹配标签的节点上。
Taint 和 toleration 相互配合,可以用来避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的 pod,是不会被该节点接受的。如果将toleration应用于pod上,则表示这些pod可以(但不要求)被调度到具有相应taint的节点上。
5.4 给节点打污点
给节点node1
增加一个污点,它的键名是key1
,键值是value1
,效果是NoSchedule
。 这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到node1
这个节点。
1 | kubectl taint nodes node1 key1=value1:NoSchedule |
若要移除上述命令所添加的污点,你可以执行:
1 2 3 | kubectl taint nodes node1 key1=value1:NoSchedule- kubectl taint nodes node1 key1:NoSchedule- |
二者都可以,k8s不会看value值,只会对比key和effect。
5.5 在pod 中定义容忍度
可以在 PodSpec 中定义 Pod 的容忍度。 下面两个容忍度均与上面例子中使用kubectl taint
命令创建的污点相匹配, 因此如果一个 Pod 拥有其中的任何一个容忍度都能够被分配到node1
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #完全匹配 tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" #模糊匹配 tolerations: - key: "key1" operator: "Exists" effect: "NoSchedule" |
5.6 toleration实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | apiVersion: v1 kind: Pod metadata: name: nginx labels: env : test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent tolerations: - key: "ssd" #存在ssd这个key,且effect为NoSchedule的节点,可以被容忍,也就是可以被调度上去。 operator: "Exists" effect: "NoSchedule" |
operator
的默认值是 Equal
。
一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:
- 如果
operator
是Exists
(此时容忍度不能指定value
) - 如果
operator
是Equal
,则它们的value
应该相等 - 如果
operator
不指定,则默认为Equal
注意:
- 如果一个容忍度的
key
为空且 operator 为Exists
, 表示这个容忍度与任意的 key 、value 和 effect 都匹配,即这个容忍度能容忍任意 taint。 - 如果
effect
为空,则可以与所有键名key1
的效果相匹配。
effect 的参数含义
- NoSchedule 新的不能容忍的pod不能再调度过来,但是之前运行在node节点中的Pod不受影响
- NoExecute 新的不能容忍的pod不能调度过来,老的pod也会被驱逐
- PreferNoScheduler 表示尽量不调度到污点节点中去
5.7 多个污点的匹配原则
可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置。
Kubernetes 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历, 过滤掉那些 Pod 中存在与之相匹配的容忍度的污点。余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点,特别是以下情况:
- 如果未被过滤的污点中存在至少一个 effect 值为
NoSchedule
的污点, 则 Kubernetes 不会将 Pod 分配到该节点。 - 如果未被过滤的污点中不存在 effect 值为
NoSchedule
的污点, 但是存在 effect 值为PreferNoSchedule
的污点, 则 Kubernetes 会 尝试 不将 Pod 分配到该节点。 - 如果未被过滤的污点中存在至少一个 effect 值为
NoExecute
的污点, 则 Kubernetes 不会将 Pod 分配到该节点(如果 Pod 还未在节点上运行), 或者将 Pod 从该节点驱逐(如果 Pod 已经在节点上运行)。
例如,假设您给一个节点添加了如下污点
1 2 3 | kubectl taint nodes node1 key1=value1:NoSchedule kubectl taint nodes node1 key1=value1:NoExecute kubectl taint nodes node1 key2=value2:NoSchedule |
假定有一个 Pod,它有两个容忍度:
1 2 3 4 5 6 7 8 9 | tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" |
上述 Pod 不会被分配到 node1 节点,因为其没有容忍度和第三个污点相匹配。
但是如果在给节点添加上述污点之前,该 Pod 已经在上述节点运行, 那么它还可以继续运行在该节点上,因为第三个污点是三个污点中唯一不能被这个 Pod 容忍的。
5.8 设置NoExcute 的驱逐时间
通常情况下,如果给一个节点添加了一个 effect 值为NoExecute
的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐, 任何可以忍受这个污点的 Pod 都不会被驱逐。
但是,如果 Pod 存在一个 effect 值为NoExecute
的容忍度指定了可选属性tolerationSeconds
的值,则表示在给节点添加了上述污点之后, Pod 还能继续在节点上运行的时间。
1 2 3 4 5 6 | tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" tolerationSeconds: 3600 |
这表示如果这个 Pod 正在运行,同时一个匹配的污点被添加到其所在的节点, 那么 Pod 还将继续在节点上运行 3600 秒,然后被驱逐。 如果在此之前上述污点被删除了,则 Pod 不会被驱逐。
5.9 容忍的匹配方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #方式一、完全匹配 key为ssd,且值是true,effect是NoSchedule tolerations: - key: "ssd" operator: "Equal" value: "true" effect: "NoSchedule" #方式二、不完全匹配 key存在,且effect为NoSchedule tolerations: - key: "ssd" operator: "Exists" effect: "NoSchedule" #方式三、大范围匹配 key存在就行,不推荐为内置Taint tolerations: - key: "ssd" operator: "Exists" #方式四、匹配所有,不推荐!! tolerations: - operator: "Exists" #方式五、完全匹配 key为ssd,且值是true,effect是NoSchedule,保留时间配置,1小时后就迁移走 tolerations: - key: "ssd" operator: "Equal" value: "true" effect: "NoExecute" tolerationSeconds: 3600 |
5.10 基于污点的驱逐
这是在每个 Pod 中配置的在节点出现问题时的驱逐行为。
前文提到过污点的 effect 值 NoExecute
会影响已经在节点上运行的 Pod
- 如果 Pod 没有配置忍受 effect 值为
NoExecute
的污点,那么 Pod 将马上被驱逐 - 如果 Pod 配置了忍受 effect 值为
NoExecute
的污点,但是在容忍度定义中没有指定tolerationSeconds
,则 Pod 还会一直在这个节点上运行。 - 如果 Pod 配置了忍受 effect 值为
NoExecute
的污点,而且指定了tolerationSeconds
, 则 Pod 还能在这个节点上继续运行这个指定的时间长度。
当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:
node.kubernetes.io/not-ready
:节点未准备好。这相当于节点状态Ready
的值为 "False
"。node.kubernetes.io/unreachable
:节点控制器访问不到节点. 这相当于节点状态Ready
的值为 "Unknown
"。node.kubernetes.io/memory-pressure
:节点存在内存压力。node.kubernetes.io/disk-pressure
:节点存在磁盘压力。node.kubernetes.io/pid-pressure
: 节点的 PID 压力。node.kubernetes.io/network-unavailable
:节点网络不可用。node.kubernetes.io/unschedulable
: 节点不可调度。node.cloudprovider.kubernetes.io/uninitialized
:如果 kubelet 启动时指定了一个 "外部" 云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。
在节点被驱逐时,节点控制器或者 kubelet 会添加带有NoExecute
效应的相关污点。 如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点。
六、affinity
6.1 将pod指派给node
我们前面知道了,有nodeSelector来对pod进行节点选择,但是这种方法比较粗狂,只能根据node的标签进行节点选择。比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | apiVersion: v1 kind: Pod metadata: name: nginx labels: env : test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: #pod部署在具备disktype=ssd的节点上 disktype: ssd |
如果我们需要更复杂的方式进行pod调度到node时,只有nodeSelector还是不够,我们需要更丰富的方法来进行调度。这里就是亲和性和反亲和性。
6.2 亲和性与反亲和性
nodeSelector
提供了一种最简单的方法来将 Pod 约束到具有特定标签的节点上。 亲和性和反亲和性扩展了你可以定义的约束类型。使用亲和性与反亲和性的一些好处有:
- 亲和性、反亲和性语言的表达能力更强。
nodeSelector
只能选择拥有所有指定标签的节点。 亲和性、反亲和性为你提供对选择逻辑的更强控制能力。【逻辑能力更强】 - 你可以标明某规则是“硬需求”或者“软需求”,这样调度器在无法找到匹配节点时仍然调度该 Pod。【选择方式更多】
- 你可以使用节点上(或其他拓扑域中)运行的其他 Pod 的标签来实施调度约束, 而不是只能使用节点本身的标签。这个能力让你能够定义规则允许哪些 Pod 可以被放置在一起。【灵活组合】
亲和性功能由两种类型的亲和性组成:
- 节点亲和性功能类似于
nodeSelector
字段,但它的表达能力更强,并且允许你指定软规则。 - Pod 间亲和性/反亲和性允许你根据其他 Pod 的标签来约束 Pod。
6.3 节点亲和性
节点亲和性概念上类似于 nodeSelector
, 它使你可以根据节点上的标签来约束 Pod 可以调度到哪些节点上。 节点亲和性有两种:
requiredDuringSchedulingIgnoredDuringExecution
: 调度器只有在规则被满足的时候才能执行调度。此功能类似于nodeSelector
, 但其语法表达能力更强。preferredDuringSchedulingIgnoredDuringExecution
: 调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点,调度器仍然会调度该 Pod。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io /zone operator: In values: - antarctica-east1 - antarctica-west1 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: registry.k8s.io /pause :2.0 |
pod会被调度到这样的node上:
- 节点必须包含一个键名为
topology.kubernetes.io/zone
的标签, 并且该标签的取值必须为antarctica-east1
或antarctica-west1
。 - 节点最好具有一个键名为
another-node-label-key
且取值为another-node-label-value
的标签。
你可以使用 operator
字段来为 Kubernetes 设置在解释规则时要使用的逻辑操作符。 你可以使用 In
、NotIn
、Exists
、DoesNotExist
、Gt
和 Lt
之一作为操作符。
NotIn
和 DoesNotExist
可用来实现节点反亲和性行为。 你也可以使用节点污点 将 Pod 从特定节点上驱逐。
说明:
如果你同时指定了 nodeSelector
和 nodeAffinity
,两者 必须都要满足, 才能将 Pod 调度到候选节点上。
如果你指定了多个与 nodeAffinity
类型关联的 nodeSelectorTerms
, 只要其中一个 nodeSelectorTerms
满足的话,Pod 就可以被调度到节点上。
如果你指定了多个与同一 nodeSelectorTerms
关联的 matchExpressions
, 则只有当所有 matchExpressions
都满足时 Pod 才可以被调度到节点上。
weight 权重
你可以为 preferredDuringSchedulingIgnoredDuringExecution
亲和性类型的每个实例设置 weight
字段,其取值范围是 1 到 100。 当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则, 并将对应表达式的 weight
值加和。
最终的加和值会添加到该节点的其他优先级函数的评分之上。 在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | apiVersion: v1 kind: Pod metadata: name: with-affinity-anti-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io /os operator: In values: - linux preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: label-1 operator: In values: - key-1 - weight: 50 #优先调度 preference: matchExpressions: - key: label-2 operator: In values: - key-2 containers: - name: with-node-affinity image: registry.k8s.io /pause :2.0 |
案例2:尽量调度到ssd,非gpu的机器上
通过节点亲和力,调度到期望的节点上:
- 尽量调度到ssd,且不是gpu的机器上(优先匹配,通过优先级weight配置;如果有多个匹配,则需要都满足;)
- 尽量调度到物理机上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | apiVersion: apps /v1 kind: Deployment metadata: labels: app: prefer-ssd name: prefer-ssd namespace: kube-public spec: replicas: 1 selector: matchLabels: app: prefer-ssd template: metadata: creationTimestamp: null labels: app: prefer-ssd spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: ssd operator: In values: - "true" - key: gpu operator: NotIn values: - "true" weight: 14 - preference: matchExpressions: - key: type operator: In values: - physical weight: 10 containers: - env : - name: TZ value: Asia /Shanghai - name: LANG value: C.UTF-8 image: nginx imagePullPolicy: IfNotPresent name: prefer-ssd |
6.2 pod间亲和和反亲和
案例1:通过反亲和将同一个项目的pod部署到不同的节点上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | apiVersion: apps /v1 kind: Deployment metadata: labels: app: must-be- diff -nodes #deployment的标签,可以和pod的不同 name: must-be- diff -nodes namespace: kube-public spec: replicas: 3 selector: matchLabels: app: must-be- diff -nodes template: metadata: labels: app: must-be- diff -nodes spec: affinity: podAntiAffinity: #配置pod反亲和 requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: #具有app=must-be-diff-nodes的节点不在本节点上调度,也就是每个节点确保只有1个同项目的pod - key: app operator: In values: - must-be- diff -nodes topologyKey: kubernetes.io /hostname containers: - image: nginx imagePullPolicy: IfNotPresent name: must-be- diff -nodes |
案例2 topologyKey使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | apiVersion: apps /v1 kind: Deployment metadata: labels: app: must-be- diff -zone name: must-be- diff -zone namespace: kube-public spec: replicas: 4 selector: matchLabels: app: must-be- diff -zone template: metadata: labels: app: must-be- diff -zone spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - must-be- diff -zone topologyKey: region containers: - image: nginx imagePullPolicy: IfNotPresent name: must-be- diff -zone |
实现效果:通过pod反亲和实现:同一个应用部署在不同地区,每个地区1个pod。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器