内容简介:我们知道在默认情况下,pod 的调度会由 scheduler-crontroller 根据节点资源和优先级来自动完成。但是有一些场景,我们希望把特定的 pod 调度到特定的节点,就不能让 scheduler 自动完成。这个时候我们可以利用 k8s 的有这样一个场景,在我们的集群里部署了 Prometheus, 但是随着集群规模的扩大 Prometheus 需要抓取的指标数量十分巨大。这样部署 Prometheus 的实例 I/O 压力会很大,这样会导致实例本身变得不够稳定。这样一来跟 Prometheus
我们知道在默认情况下,pod 的调度会由 scheduler-crontroller 根据节点资源和优先级来自动完成。但是有一些场景,我们希望把特定的 pod 调度到特定的节点,就不能让 scheduler 自动完成。这个时候我们可以利用 k8s 的 NodeSelector 或者 NodeAffinity 来实现。
有这样一个场景,在我们的集群里部署了 Prometheus, 但是随着集群规模的扩大 Prometheus 需要抓取的指标数量十分巨大。这样部署 Prometheus 的实例 I/O 压力会很大,这样会导致实例本身变得不够稳定。这样一来跟 Prometheus 部署在同一个实例上的服务就容易受到影响,导致不可用。所以,我们应该把 Prometheus 这样占用资源很多的服务与其他服务隔离开来。解决办法也是很自然的想法,就是把 Promethues 这样的服务固定到某些实例上,且其他服务不会漂移到这样的实例上。
NodeSelector
使用 NodeSelector 是最简单的方式。原理就是我们给 node 打上标签,NodeSelector 是 pod spec 的一个字段,只要给它赋值 node 对应的标签。scheduler 就只会把 pod 调度到具有该标签的 node 上。
-
节点打标签
# 列出节点 kubectl get no # 打标签 kubectl label no node3 test_label=yes # 查看标签 kubectl get no node3 --show-labels # 删除标签 kubectl label no node3 test_label-
-
配置添加 NodeSelector
apiVersion: v1 kind: Pod metadata: name: hello-service labels: env: test spec: containers: - name: hello-sevice image: xxxx/hello-service:latest imagePullPolicy: IfNotPresent nodeSelector: #Add this field test_label: yes
NodeAffinity
NodeAffinity 应用上和 NodeSelector 相似。与后者相比优点是:
- 语法支持的操作符丰富 (in, NotIn, Exists, DoesNotExit, Gt, Lt)
-
规则可以更灵活,可以不是硬性要求,简单说就是即使不满足条件也能调度成功
具体 NodeAffinity 支持的策略包括: - requiredDuringSchedulingIgnoredDuringExecution :必须满足指定的规则才可以调度Pod到Node上(功能与nodeSelector很像,语法不同),相当于硬限制。
-
preferredDuringSchedulingIgnoredDuringExecution
:强调优先级,可以设置权重,但不是强制的,相当于软限制。
示例配置apiVersion: v1 kind: Deployment metadata: name: dep-affinity spec: replicas: 1 template: metadata: labels: app: test-app spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 preferredDuringSchedulingIgnoredDuringExecution: # 软限制 - weight: 1 preference: matchExpressions: - key: test_label operator: In values: - yes containers: - name: dep-affinity image: xxxx/hello-service:latest
需要注意的地方
- 如果同时定义了 nodeSelector 和 nodeAffinity,那么必须两个条件都得到满足,pod 才能最终运行在指定的 node 上。
- 如果 nodeAffinity 指定了多个 nodeSelectorTerms,那么只需要其中一个能够匹配成功即可。
- 如果 nodeSelectorTerms 中有多个 matchExpressions,则一个节点必须满足所有 matchExpressions 才能运行该 pod。
- 如果一个 pod 所在的节点在Pod运行期间标签发生了变化,不再符合该 pod 的亲和性需求,pod 不会进行重新调度,继续在该节点上运行。
podAffinity and podAntiAffinity
根据正在节点上运行的 pod 的标签来对 pod 进行调度而不是使用 node 的标签。简单说就是根据已存在 pod 来决定要不要和它部署在同一 node 上。 生效策略与 NodeAffinity 一样有硬限制(requiredDuringSchedulingIgnoredDuringExecution)和软限制(preferredDuringSchedulingIgnoredDuringExecution)
示例配置如下
apiVersion: v1 kind: Pod metadata: name: pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: test_pod operator: In values: - pod1 topologyKey: failure-domain.beta.kubernetes.io/zone podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: kubernetes.io/hostname containers: - name: pod-affinity image: xxxxx/hello-service:latest
上面的 podAffinity 表示被调度 pod 只能运行在集群中的特定节点上,这些节点已经至少运行一个具有”test_pod=pod1”标签的 pod,并且和这些节点在同一个 zone;
podAntiAffinity 表示如果 node 上已经有 “app=nignx”标签的 pod, 则优先不调度到该节点。
需要注意的地方
为了性能考虑只允许一些有限的topologyKey,默认情况下,有以下几个:
- kubernetes.io/hostname
- failure-domain.beta.kubernetes.io/zone
-
failure-domain.beta.kubernetes.io/region
除了设置 LabelSelector 和 topologyKey,还可以指定 namespace 列表来进行限制,同样,使用 LabelSelector 对 namespace 进行选择。namespace 的定义和LabelSelector及 topologyKey 同级。 省略namespace的设置,表示使用定义了 affinity/anti-affinity 的 pod 所在的 namespace。 如果namespace设置为空值(””),则表示所有namespace。
在所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions 全部满足之后,系统才能将Pod调度到某个Node上。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- LWN: 利用address space隔离来改善container方案安全性
- MySQL -- RR隔离与RC隔离
- MySQL -- 事务隔离
- MySQL事务隔离
- 架构设计:隔离术
- I 是接口隔离原则
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。