TKE 实践亲和性与反亲和性

2020-09-08 15:44:31 浏览数 (1)

通常情况下在Kubernetes 集群中部署一个Pod, 默认调度器将会自动进行合理的调度(例如, 将Pod分散到节点上, 根据节点上的资源情况进行分配), 但是有时候我们需要更加细粒度的控制pod的调度. 比如一组pod需要最终调度到拥有SSD/GPU的硬盘的机器上,或者将两个不同的服务(服务间直接通信比较频繁)的pod 调度到同样的节点上 (比如gitlab.这里就需要 Kubernetes里面的亲和性来解决,亲和性分为2类: nodeAffinitypodAffinity.

nodeSelector

最简单的推荐形式是使用nodeSelector 来满足我们的需求. labelkubernetes 中一个非常重要的一个概念. 使用label 可以非常方便的管理集群中资源. 例如常见的使用label 对node节点打标签方面对于不同计算资源的pod进行调度。还有一个是常见的service 就是通过匹配label 进行选择pod。pod的调度也可以根据节点标签进行选择部署. nodeSelector 是 PodSpec 的一个字段。 它包含键值对的映射。为了使 pod 可以在某个节点上运行,该节点的标签中必须包含这里的每个键值对(它也可以具有其他标签)。最常见的用法的是一对键值对。

TKE中查看和添加标签

在控制台中查看标签: 节点管理--> 节点--> 详情

k8s-labels01.pngk8s-labels01.png

在控制台中添加/修改/删除标签: 节点管理--> 节点--> 编辑标签

image.pngimage.png

备注: TKE node节点上默认标签不允许修改

在命令行中查看/添加/删除标签

通过 --show-labels 可以查看当前 nodes 的 labels

代码语言:txt复制
 ~  kubectl get nodes --show-labels                                                                                                           日  9/ 6 15:49:15 2020
NAME        STATUS   ROLES    AGE    VERSION          LABELS
10.0.0.10   Ready    <none>   82d    v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-ea2t8uz1,diqu=bj,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,group=devops,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.10,kubernetes.io/os=linux

我们可以通过 kubectl label node 命令给指定 node 添加 labels

代码语言:txt复制
 ~  kubectl label nodes 10.0.0.10 disk=ssd                                                                                                                                                              1159ms  日  9/ 6 15:51:24 2020
node/10.0.0.10 labeled
 ~  kubectl get nodes 10.0.0.10 --show-labels                                                                                                                                                            383ms  日  9/ 6 15:51:36 2020
NAME        STATUS   ROLES    AGE   VERSION          LABELS
10.0.0.10   Ready    <none>   82d   v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-ea2t8uz1,diqu=bj,disk=ssd,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,group=devops,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.10,kubernetes.io/os=linux

实践案例--测试 pod 并指定 nodeSelector 选项绑定节点

使用命令行进行创建:

创建 test-nodeselector.yaml 文件

代码语言:txt复制
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    k8s-app: test-nodeselector
    qcloud-app: test-nodeselector
  name: test-nodeselector

spec:
  progressDeadlineSeconds: 600
  replicas: 1
  selector:
    matchLabels:
      k8s-app: test-nodeselector
      qcloud-app: test-nodeselector
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        k8s-app: test-nodeselector
        qcloud-app: test-nodeselector
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: test-nodeselector
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      nodeSelector:
        disk: ssd
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

kubectl apply -f test-nodeselector.yaml

这个例子中:

代码语言:txt复制
      nodeSelector:
        disk: ssd

这个例子就是告诉 kubernetes 调度的时候把 pod 放到有 SSD 磁盘的机器上。除了自己定义的 label 之外,kubernetes 还会自动给集群中的节点添加一些 label,比如:

  • kubernetes.io/hostname:节点的 hostname 名称
  • beta.kubernetes.io/os: 节点安装的操作系统
  • beta.kubernetes.io/arch:节点的架构类型
  • …… 不同版本添加的 label 会有不同,这些 label 和手动添加的没有区别,可以通过 --show-labels 查看,也能够用在 nodeSelector 中。

nodeSelector 的方式比较简单直观,但是不够灵活。我们推荐使用下面讲到的 Node Affinity ,请关注每个版本的 release note。


Node Affinity

nodeAffinity 节点亲和性, 与之相对应的是Anti-Affinity, 这个方式比nodeSelector 更加灵活, 有以下优势:

  • 匹配更多的逻辑组合(不仅仅是"完全相等")
  • 调度分为硬策略和软策略

硬策略requiredDuringSchedulingIgnoredDuringExecution: 必须满足的条件,如果没有满足条件的节点, 就不断重试直到满足条件为止. 软策略preferredDuringSchedulingIgnoredDuringExecution: 调度器尝试执行如果没有找到满足要求的节点的话,Pod就会忽略这条规则, 继续完成调度,简单来说就是能满足条件最好, 没有满足就忽略,继续往下执行. gnoredDuringExecution部分意味着,类似于 nodeSelector 的工作原理,如果节点的标签在运行时发生变更,从而不再满足 pod 上的亲和规则,那么 pod 将仍然继续在该节点上运行。与之对应的是requiredDuringSchedulingRequiredDuringExecution. 如果运行的pod所在的节点不再满足条件, kubernetes 会把pod从该节点删除, 重新选择符合要求的节点.

实践案例 -- nodeAffinity

例如: 我们部署一个pod 要求调度到满足以下条件

必须满足以下条件(标签):

  • disk=ssd
  • device=gpu

尽量满足的条件(标签):

  • zone=bj

Node节点 标签如下:

代码语言:txt复制
NAME        STATUS   ROLES    AGE    VERSION          LABELS
10.0.0.10   Ready    <none>   83d    v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-ea2t8uz1,diqu=bj,disk=ssd,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,group=devops,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.10,kubernetes.io/os=linux
10.0.0.14   Ready    master   83d    v1.16.3-tke.8    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-ep4ulpc5,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.14,kubernetes.io/node-role-etcd=true,kubernetes.io/os=linux,node-role.kubernetes.io/master=true
10.0.0.30   Ready    <none>   31d    v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-9o9sx4jz,diqu=sh,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,gitlab=dev,group=devops,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.30,kubernetes.io/os=linux
10.0.0.31   Ready    <none>   28d    v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-3jd96e1x,device=gpu,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.31,kubernetes.io/os=linux,nvidia-device-enable=enable
10.0.0.34   Ready    <none>   28d    v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-hodl5idj,device=gpu,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.34,kubernetes.io/os=linux,nvidia-device-enable=enable
10.0.0.4    Ready    master   83d    v1.16.3-tke.8    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-jngdgb43,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.4,kubernetes.io/node-role-etcd=true,kubernetes.io/os=linux,node-role.kubernetes.io/master=true
10.0.0.45   Ready    <none>   28d    v1.16.3-tke.10   app=public,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-diha6wb3,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.45,kubernetes.io/os=linux
10.0.0.8    Ready    master   83d    v1.16.3-tke.8    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-lasqw15t,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.8,kubernetes.io/node-role-etcd=true,kubernetes.io/os=linux,node-role.kubernetes.io/master=true
10.0.0.9    Ready    <none>   5d1h   v1.16.3-tke.10   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-kr44unor,device=gpu,disk=ssd,failure-domain.beta.kubernetes.io/region=bj,failure-domain.beta.kubernetes.io/zone=800001,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.0.0.9,kubernetes.io/os=linux,zone=bj

TKE控制台创建:

nodeaffinity.pngnodeaffinity.png

部署之后pod按照亲和性规则被调度到了10.0.0.9 这个node节点上,符合预期.

image.pngimage.png

在命令行中手动创建:

创建test-nodeaffinity.yaml 文件

代码语言:txt复制
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  generation: 1
  labels:
    k8s-app: test-nodeaffinity
    qcloud-app: test-nodeaffinity
  name: test-nodeaffinity
  namespace: default

spec:
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: test-nodeaffinity
      qcloud-app: test-nodeaffinity
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        k8s-app: test-nodeaffinity
        qcloud-app: test-nodeaffinity
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: zone
                operator: In
                values:
                - bj
            weight: 1
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disk
                operator: In
                values:
                - ssd
              - key: device
                operator: In
                values:
                - gpu
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: test-nodeaffinity
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:

部署: kubectl apply -f test-nodeaffinity.yaml

需要注意的是 nodeSelectorTerms 下的多个 matchExpressionsOR 的关系,就是说其中一个满足的话pod就可以调度在该节点, key 之间的关系是 AND 必须同时满足 如下图所示(1和2 之间是OR, A和B之间是AND)

nodeaffinity02.pngnodeaffinity02.png

这里的匹配逻辑是 label 的值在某个列表中,可选的操作符有:

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Exists:某个 label 存在
  • DoesNotExist: 某个 label 不存在
  • Gt:label 的值大于某个值(字符串比较)
  • Lt:label 的值小于某个值(字符串比较)

preferredDuringSchedulingIgnoredDuringExecution 中的 weight 字段值的范围是 1-100。对于每个符合所有调度要求(资源请求,RequiredDuringScheduling 亲和表达式等)的节点,调度器将遍历该字段的元素来计算总和,并且如果节点匹配对应的MatchExpressions,则添加“权重”到总和。然后将这个评分与该节点的其他优先级函数的评分进行组合。总分最高的节点是最优选的。

Pod Affinity

上面的方式是让pod灵活的去选择调度到哪个Node节点上; 但有些场景希望调度的时候需要考虑pod之间的关系,

不仅仅只pod-node的关系.比如服务A和服务B交互频繁, 我们希望尽量调度到同一个机房,地域. 相对应的例如: 服务c和服务d, 尽力互斥, 不让c和d在同一个主机或者地域.

nodeAffinity 一样, podAffinity 目前有两种类型的pod亲和和反亲和:

  • requiredDuringSchedulingIgnoredDuringExecution 亲和的一个示例是“将服务 A 和服务 B 的 pod 放置在同一区域,因为它们之间进行大量交流”
  • preferredDuringSchedulingIgnoredDuringExecution 反亲和的示例将是“将此服务的 pod 跨区域分布

Pod 间亲和通过 PodSpec 中 affinity 字段下的 podAffinity 字段进行指定。而 pod 间反亲和通过 PodSpec 中 affinity 字段下的 podAntiAffinity 字段进行指定。

Pod 亲和实践

场景 1:

服务A和服务B, B的标签(db=mysql),期望得调度规则服务A被调度到的节点至少已经运行一个标签为db=mysql的pod 并且该节点拥有failure-domain.beta.kubernetes.io/zone key的标签.

服务B(test-podaffinity-a.yaml):

代码语言:txt复制
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    db: mysql
    k8s-app: test-podaffinity-a
    qcloud-app: test-podaffinity-a
  name: test-podaffinity-a
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      db: mysql
      k8s-app: test-podaffinity-a
      qcloud-app: test-podaffinity-a
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        db: mysql
        k8s-app: test-podaffinity-a
        qcloud-app: test-podaffinity-a
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: test-podaffinity-a
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}

部署: kubectl apply -f test-podaffinity-a.yaml ,

代码语言:txt复制
 ~/d/k/tests  kubectl get po test-podaffinity-a-6db995f99b-zlsqt -o wide                                                        1037ms  二  9/ 8 05:43:02 2020
NAME                                  READY   STATUS    RESTARTS   AGE    IP             NODE        NOMINATED NODE   READINESS GATES
test-podaffinity-a-6db995f99b-zlsqt   1/1     Running   0          134m   172.16.1.172   10.0.0.34   <none>           <none>

服务A(with-pod-affinity.yaml):

代码语言:txt复制
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: db
            operator: In
            values:
            - mysql
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: failure-domain.beta.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: nginx:latest

部署: kubectl apply -f with-pod-affinity.yaml

查看事件日志: kubectl get events --sort-by=.metadata.creationTimestamp -w

代码语言:txt复制
LAST SEEN   TYPE      REASON                OBJECT                  MESSAGE
<unknown>   Normal    Scheduled             pod/with-pod-affinity   Successfully assigned default/with-pod-affinity to 10.0.0.34
12m         Normal    Pulling               pod/with-pod-affinity   Pulling image "nginx:latest"
12m         Normal    Pulled                pod/with-pod-affinity   Successfully pulled image "nginx:latest"
12m         Normal    Created               pod/with-pod-affinity   Created container with-pod-affinity
12m         Normal    Started               pod/with-pod-affinity   Started container with-pod-affinity

从调度结果上看符合预期

在这个 pod 的 affinity 配置定义了一条 pod 亲和规则和一条 pod 反亲和规则。在此示例中,podAffinity 配置为 requiredDuringSchedulingIgnoredDuringExecution,然而 podAntiAffinity 配置为 preferredDuringSchedulingIgnoredDuringExecution。pod 亲和规则表示,仅当节点和至少一个已运行且有key为“db”且值为“mysql”的标签的 pod 处于同一区域时,才可以将该 pod 调度到节点上。(更确切的说,如果节点 N 具有带有key failure-domain.beta.kubernetes.io/zone 和某个值 V 的标签,则 pod 有资格在节点 N 上运行,以便集群中至少有一个节点具有key failure-domain.beta.kubernetes.io/zone 和值为 V 的节点正在运行具有key “db”和值“mysql”的标签的 pod。)pod 反亲和规则表示,如果节点已经运行了一个具有key “security”和值“S2”的标签的 pod,则该 pod 不希望将其调度到该节点上。(如果 topologyKey 为 failure-domain.beta.kubernetes.io/zone,则意味着当节点和具有key “security”和值“S2”的标签的 pod 处于相同的区域,pod 不能被调度到该节点上。)

Pod 亲和与反亲和的合法操作符有 In,NotIn,Exists,DoesNotExist

由于性能和安全的原因,topologyKey 有以下限制:

  • 对于亲和与 requiredDuringSchedulingIgnoredDuringExecution 要求的 pod 反亲和,topologyKey 不允许为空。
  • 对于 requiredDuringSchedulingIgnoredDuringExecution 要求的 pod 反亲和,准入控制器 LimitPodHardAntiAffinityTopology 被引入来限制 topologyKey 不为 kubernetes.io/hostname。如果你想使它可用于自定义拓扑结构,你必须修改准入控制器或者禁用它。
  • 对于 preferredDuringSchedulingIgnoredDuringExecution 要求的 pod 反亲和,空的 topologyKey 被解释为“所有拓扑结构”(这里的“所有拓扑结构”限制为 kubernetes.io/hostname,failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合)
  • 除上述情况外,topologyKey 可以是任何合法的标签键.

场景 2:

Pod 间亲和和反亲和结合Replicasets, StatefulSets,Deployments使用.

例如 一个web服务使用了redis(3副本)作为缓存, 希望web服务尽可能与redis调度到同一节点.

下面是一个简单 redis deployment 的 yaml 代码段,它有三个副本和选择器标签 app=store。Deployment 配置了 PodAntiAffinity,用来确保调度器不会将副本调度到单个节点上。

代码语言:txt复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  replicas: 3
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine

下面 webserver deployment 的 yaml 代码段中配置了 podAntiAffinity 和 podAffinity。这将通知调度器将它的所有副本与具有 app=store 选择器标签的 pod 放置在一起。这还确保每个 web 服务器副本不会调度到单个节点上。

代码语言:txt复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx:latest

node1

node2

node3

webserver-1

webserver-2

webserver-3

cache-1

cache-2

cache-3

查看结果: kubectl get pods -o wide

代码语言:txt复制
NAME                           READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
redis-cache-6bc7d5b59d-sg87g   1/1     Running   0          18m   172.16.1.176   10.0.0.34   <none>           <none>
redis-cache-6bc7d5b59d-sjv5m   1/1     Running   0          18m   172.16.2.18    10.0.0.9    <none>           <none>
redis-cache-6bc7d5b59d-w5xr7   1/1     Running   0          18m   172.16.1.9     10.0.0.45   <none>           <none>
web-server-7dffcf98d7-6fwhq    1/1     Running   0          15m   172.16.1.10    10.0.0.45   <none>           <none>
web-server-7dffcf98d7-mhrcg    1/1     Running   0          15m   172.16.1.177   10.0.0.34   <none>           <none>
web-server-7dffcf98d7-w6h9g    1/1     Running   0          15m   172.16.2.19    10.0.0.9    <none>           <none>

上面的例子使用 PodAntiAffinity 规则和 topologyKey: "kubernetes.io/hostname" 来部署 redis 集群以便在同一主机上没有两个实例。 更多文档请参考官方文档

结束

k8s 提供了亲和反亲和性给我们的调度提供了更细粒度的控制. 这里需要注意的是pod间亲和和反亲和确实带来了不少便利,但是pod间的亲和和反亲和需要大量的处理, 这可能会显著减慢大规模集群中的调度。 不建议在超过数百个节点的集群中使用pod 间 的亲和和反亲和

欢迎大家关注本栏目,我们专注于Kubernetes生态,持续给大家分享。

参考资料

  • https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
  • https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
  • https://coreos.com/fleet/docs/latest/affinity.html

0 人点赞