K8S入门篇-资源调度

一、Job

1 Job可以干什么

Job可以干什么?在容器启动或退出时做一些任务。Job可以并行执行。

1、需要等待后执行的任务

2、导入SQL文件

3、创建用户、清理表

........等等

 

示例:

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的命令如下:

kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"

  

对应的yaml文件如下:

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参数测试

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

 

 

 

恢复挂起:

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容器配置解析

 

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 初始化容器示例

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工具的容器,用于排查问题或故障。

开启临时容器功能:

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

  

 临时容器使用

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这个节点。

kubectl taint nodes node1 key1=value1:NoSchedule

 

若要移除上述命令所添加的污点,你可以执行:

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

#完全匹配

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"

#模糊匹配

tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoSchedule"

  

 

5.6 toleration实例

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 已经在节点上运行)。

 例如,假设您给一个节点添加了如下污点

kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

  

假定有一个 Pod,它有两个容忍度:

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 还能继续在节点上运行的时间。

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

  这表示如果这个 Pod 正在运行,同时一个匹配的污点被添加到其所在的节点, 那么 Pod 还将继续在节点上运行 3600 秒,然后被驱逐。 如果在此之前上述污点被删除了,则 Pod 不会被驱逐。

5.9 容忍的匹配方式

#方式一、完全匹配 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的标签进行节点选择。比如:

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。

 

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 设置在解释规则时要使用的逻辑操作符。 你可以使用 InNotInExistsDoesNotExistGt 和 Lt 之一作为操作符。

NotIn 和 DoesNotExist 可用来实现节点反亲和性行为。 你也可以使用节点污点 将 Pod 从特定节点上驱逐。

说明:

如果你同时指定了 nodeSelector 和 nodeAffinity,两者 必须都要满足, 才能将 Pod 调度到候选节点上。

如果你指定了多个与 nodeAffinity 类型关联的 nodeSelectorTerms, 只要其中一个 nodeSelectorTerms 满足的话,Pod 就可以被调度到节点上。

如果你指定了多个与同一 nodeSelectorTerms 关联的 matchExpressions, 则只有当所有 matchExpressions 都满足时 Pod 才可以被调度到节点上。

 

weight 权重

 你可以为 preferredDuringSchedulingIgnoredDuringExecution 亲和性类型的每个实例设置 weight 字段,其取值范围是 1 到 100。 当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则, 并将对应表达式的 weight 值加和。

最终的加和值会添加到该节点的其他优先级函数的评分之上。 在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高。

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配置;如果有多个匹配,则需要都满足;)
  • 尽量调度到物理机上
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部署到不同的节点上

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使用

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。

 

 

 

 

posted @ 2022-10-26 17:29  skyflask  阅读(203)  评论(0编辑  收藏  举报