如何指定pod的运行节点?

2020-10-25  本文已影响0人  一瓶多先生

一般情况下kubernets可以通过kube-scheduler默认的调度策略合理的将pod分配到可用的节点上, 但是随着pod数量的增加以及不同pod对资源的使用情况不同我们需要更加合理的分配集群中的资源, 所以对一些pod运行节点的控制是由必要的。

源于硬件和软件层多样性,我们需要将某个 pod 调度到某些特定的节点上,例如指定机房,存储类型,网络类型等等:

有两种方法 nodeSelector以及affinity 可以实现对应的需求

1.node label规划

K8S中pod的调度都是通过节点label实现的 , 所以对于除必要的节点label外对于其它用途也要做一些规划

Shortcut Description
department 部门名称
edgenode 是否为边缘节点
dedicated 节点用途

设置参数

Shortcut Description
department devops,o2o,
edgenode true
dedicated job,edgenode,model,app,addons

为 node 设置 taint 与 label:

kubectl taint nodes node -l edgenode=true dedicated=edgenode department=devops edgenode=true:NoSchedule

or

kubectl label nodes node edgenode=true dedicated=edgenode department=devops
kubectl taint nodes node edgenode=true:NoSchedule

删除taint:

kubectl taint nodes node edgenode:NoSchedule-

删除node的label

kubectl label node node edgenode-

查看 node上的 taint:

kubectl describe nodes node

查看node1的label

kubectl get  nodes  --show-labels

2.nodeSelector

kubernetes中是通过label-selector机制进行节点选择,由scheduler调度策略MatchNodeSelector进行label匹配,调度pod到目标节点,该匹配规则是强制约束。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-test
  labels:
    k8s-app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        department: devops 
      containers:
      - name: nginx
        image: nginx:1.7.9

3.affinity

affinity类型

类型包括:

限制方式:

匹配逻辑label

如果nodeAffinity中nodeSelector有多个选项,节点满足任何一个条件即可;如果matchExpressions有多个选项,则节点必须同时满足这些选项才能运行pod 。需要说明的是,node并没有anti-affinity这种东西,因为NotIn和DoesNotExist能提供类似的功能。

NodeAffinity

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-test
  labels:
    k8s-app: nginx
spec:
  replicas: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: department
                operator: In
                values:
                - model
            weight: 1
          - preference:
              matchExpressions:
              - key: dedicated
                operator: In
                values:
                - app
            weight: 5
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: department
                operator: In
                values:
                - devops
      containers:
      - name: nginx
        image: nginx:1.7.9

这个 pod 同时定义了requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution两种nodeAffinity。第一个要求 pod 运行在特定 devops 的节点上,第二个希望节点最好有对应的department:model和dedicated:app标签, 根据权重决定了顺序NodeSelectorTerms可以有多个,之间是或的关系,满足任意一个既满足,MatchExpressions也可以有多个,他们之间是且的关系 必须都满足
preferredDuringSchedulingIgnoredDuringExecution值为列表,根据权重决定顺序MatchExpressions值为列表 关系为且,必须都满足

PodAffinity && PodAntiAffinity

PodAffinit是根据通过已运行在节点上的pod的标签而不是node的标签来决定被调度pod的运行节点,因为pod运行在指定的namespace所以需要自己指定运行pod的namesapce

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
  labels:
    app: pod-affinity-pod
spec:
  containers:
  - name: with-pod-affinity
    image: nginx
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - busybox-pod
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - node-affinity-pod
          topologyKey: kubernetes.io/hostname

上面这个例子中的 POD 需要调度到某个指定的主机上,至少有一个节点上运行了这样的 POD:这个 POD 有一个app=busybox-pod的 label。podAntiAffinity则是希望最好不要调度到这样的节点:这个节点上运行了某个 POD,而这个 POD 有app=node-affinity-pod的 label。根据前面两个 POD 的定义,我们可以预见上面这个 POD 应该会被调度到一个busybox-pod被调度的节点上,而node-affinity-pod被调度到了该节点以外的节点

污点(Taints)与容忍(tolerations)

对于nodeAffinity无论是硬策略还是软策略方式,都是调度 POD 到预期节点上,而Taints恰好与之相反,如果一个节点标记为 Taints ,除非 POD 也被标识为可以容忍污点节点,否则该 Taints 节点不会被调度pod。

比如用户希望把 Master 节点保留给 Kubernetes 系统组件使用,或者把一组具有特殊资源预留给某些 POD,则污点就很有用了,POD 不会再被调度到 taint 标记过的节点。taint 标记节点举例如下:

$ kubectl taint nodes kube-node key=value:NoSchedule
node "kube-node" tainted

如果仍然希望某个 POD 调度到 taint 节点上,则必须在 Spec 中做出Toleration定义,才能调度到该节点,举例如下:

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

effect 共有三个可选项,可按实际需求进行设置:

example

traefik 部署

设置label 和 taint, edgenode为特殊属性的节点所以需要设置taint

kubectl taint nodes node  edgenode=true:NoSchedule --overwrite 
kubectl  label nodes node department=devops edgenode=true service=traefik 

资源文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-test
  labels:
    k8s-app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: dedicated
                operator: In 
                values: 
                - edgenode

              - key: department
                operator: In
                values:
                - devops

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

      containers:
      - name: nginx
        image: nginx:1.7.9

运维应用部署

运维服务部署在固定的几台主机上, 每个主机设置department的label, 部署服务时指定该label

设置label

kubectl  label nodes node department=devops

资源文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-test
  labels:
    k8s-app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity: 
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
                - key: department
                  operator: In
                  values:
                  - devops
      containers:
      - name: nginx
        image: nginx:1.7.9

pod尽可能的分配到多个节点上

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 1
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - nginx
                topologyKey: kubernetes.io/hostname

      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

pod强制分配到不同的node节点上

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - weight: 1
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - nginx
                topologyKey: kubernetes.io/hostname

      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

不同应用就近部署, 如app=nginx 和 app=frontend部署到相同节点

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - weight: 1
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - nginx
                topologyKey: kubernetes.io/hostname

      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

参考

上一篇 下一篇

猜你喜欢

热点阅读