k8s nodeSelector&affinity

本文介绍了Kubernetes中Pod调度到特定Node的两种方法:nodeSelector与affinity。详细解析了NodeAffinity、PodAffinity及PodAntiAffinity的配置方式,并通过示例展示了如何利用这些特性精确控制Pod的部署位置。
1.分配pod到node的方法
通过node label selector实现约束pod运行到指定节点,有两种方法 nodeSelector 以及affinity 
2.nodeSelector 是k8s早起提供的节点选择器实现
1)首先为nodes打对应的label
kubectl label nodes master disktype=ssd
2)创建yaml文件
cat >> nginx-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
EOF

创建pod
kubectl create -f nginx-pod.yaml
节点默认的label
kubectl get nodes -o yaml 可以看到默认节点的label,也可以使用这些label进行约束
alpha.kubernetes.io/fluentd-ds-ready: "true"
beta.kubernetes.io/arch: amd64
beta.kubernetes.io/os: linux
disktype: ssd
kubeadm.alpha.kubernetes.io/role: master
kubernetes.io/hostname: master


3, affinity 
根据限制方式有两种affinity:
requiredDuringSchedulingIgnoredDuringExecution (硬限制)
条件必须满足从而调度到一个节点
preferredDuringSchedulingIgnoredDuringExecution (软限制)
条件不满足则调度到不满足条件的节点

IgnoredDuringExecution意味着当节点label改变后,pod将继续运行在这个不满足labelselector的node上面,将来会提供RequiredDuringExecution,让node驱逐不满足affinity条件的pod

根据类型有

NodeAffinity
PodAffinity
PodAntiAffinity


NodeAffinity

下面这个例子将运行pod到kubernetes.io/e2e-az-name值为e2e-az1 或e2e-az2的节点上面

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
      {
        "nodeAffinity": {
          "requiredDuringSchedulingIgnoredDuringExecution": {
            "nodeSelectorTerms": [
              {
                "matchExpressions": [
                  {
                    "key": "kubernetes.io/e2e-az-name",
                    "operator": "In",
                    "values": ["e2e-az1", "e2e-az2"]
                  }
                ]
              }
            ]
          }
        }
      }
    another-annotation-key: another-annotation-value
spec:
  containers:
  - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0


我们可以看到NodeSelectorTerms可以有多个,之间是或的关系,满足任意一个既满足,,MatchExpressions也可以有多个,他们之间是且的关系 必须都满足

preferredDuringSchedulingIgnoredDuringExecution 例子:
apiVersion: v1
kind: Pod
metadata:
  name: with-labels
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
    {
       "nodeAffinity": {
          "preferredDuringSchedulingIgnoredDuringExecution": [
                {
                    "weight" : 1,
                    "preference": {
                        "matchExpressions": [
                            {
                                "key": "disktype",
                                "operator": "In",
                                "values": ["ssd"]
                            }
                        ]
                    }
                }
            ]
        }
    }
    another-annotation-key: another-annotation-value
spec:
  containers:
  - name: test-affinity
    env:
      - name: MYSQL_ROOT_PASSWORD
        value: pass
    image: mysql

preferredDuringSchedulingIgnoredDuringExecution值为列表,根据权重决定顺序
MatchExpressions 值为列表 关系为且,必须都满足

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

这个例子意思是首先node需要有 failure-domain.beta.kubernetes.io/zone label 不能有kubernetes.io/hostname label  切改节点上需要有一个pod 有一个security=S1的label
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
        {
          "podAffinity": {
            "requiredDuringSchedulingIgnoredDuringExecution": [
              {
                "labelSelector": {
                  "matchExpressions": [
                    {
                      "key": "security",
                      "operator": "In",
                      "values": ["S1"]
                    }
                  ]
                },
                "topologyKey": "failure-domain.beta.kubernetes.io/zone"
             }
            ]
           },
          "podAntiAffinity": {
            "requiredDuringSchedulingIgnoredDuringExecution": [
              {
                "labelSelector": {
                  "matchExpressions": [
                    {
                      "key": "security",
                      "operator": "In",
                      "values": ["S2"]
                    }
                  ]
                },
                "topologyKey": "kubernetes.io/hostname"
             }
            ]
           }
         }
spec:
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0



具体字段的定义以及关系可以参考k8s源码的定义

type Affinity struct {
    NodeAffinity *NodeAffinity
    PodAffinity *PodAffinity
    PodAntiAffinity *PodAntiAffinity
}
type NodeAffinity struct {
    RequiredDuringSchedulingIgnoredDuringExecution *NodeSelector
    PreferredDuringSchedulingIgnoredDuringExecution []PreferredSchedulingTerm
}

type PodAffinity struct {
    RequiredDuringSchedulingIgnoredDuringExecution []PodAffinityTerm
    PreferredDuringSchedulingIgnoredDuringExecution []WeightedPodAffinityTerm
}

type PodAntiAffinity struct {
    RequiredDuringSchedulingIgnoredDuringExecution []PodAffinityTerm
    PreferredDuringSchedulingIgnoredDuringExecution []WeightedPodAffinityTerm
}

type PreferredSchedulingTerm struct {
    Weight int32
    Preference NodeSelectorTerm
}

type NodeSelector struct {
    NodeSelectorTerms []NodeSelectorTerm
}
type NodeSelectorTerm struct {
    MatchExpressions []NodeSelectorRequirement
}
type NodeSelectorRequirement struct {
    Key string
    Operator NodeSelectorOperator
    Values []string
}

const (
    NodeSelectorOpIn           NodeSelectorOperator = "In"
    NodeSelectorOpNotIn        NodeSelectorOperator = "NotIn"
    NodeSelectorOpExists       NodeSelectorOperator = "Exists"
    NodeSelectorOpDoesNotExist NodeSelectorOperator = "DoesNotExist"
    NodeSelectorOpGt           NodeSelectorOperator = "Gt"
    NodeSelectorOpLt           NodeSelectorOperator = "Lt"
)

type PodAffinityTerm struct {
    LabelSelector *metav1.LabelSelector
    Namespaces []string
    TopologyKey string
}

type LabelSelector struct {
    MatchLabels map[string]string 
    MatchExpressions []LabelSelectorRequirement 
}


type LabelSelectorRequirement struct {
    Key string 
    Operator LabelSelectorOperator 
    Values []string 
}

const (
    LabelSelectorOpIn           LabelSelectorOperator = "In"
    LabelSelectorOpNotIn        LabelSelectorOperator = "NotIn"
    LabelSelectorOpExists       LabelSelectorOperator = "Exists"
    LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
)

type WeightedPodAffinityTerm struct {
    Weight int32
    PodAffinityTerm PodAffinityTerm
}

type PodAffinityTerm struct {
    LabelSelector *metav1.LabelSelector
    Namespaces []string
    TopologyKey string
}


<think>好的,我现在需要帮助用户解决如何在Kubernetes StatefulSet中配置NodeSelector的问题。首先,我得回想一下用户提供的引用内容,看看有没有相关的信息。 引用[1]提到使用kubectl apply来创建zk StatefulSet,引用[2]和[3]涉及Service的配置和StatefulSet的基本结构,引用[4]则是关于查看和更新StatefulSet的命令。用户的问题是关于NodeSelector的配置,这在之前的引用中没有直接提到,但可能需要结合Kubernetes的官方文档知识。 我知道,NodeSelector是用于将Pod调度到特定节点的一种机制,通常在Pod模板的spec部分指定。对于StatefulSet来说,配置应该也是在Pod模板里添加nodeSelector字段,然后指定对应的标签。例如,在YAML文件中,应该在spec.template.spec下加入nodeSelector,并设置键值对。 接下来,我需要确认是否正确,是否有其他需要注意的地方。比如,确保节点已经打上了对应的标签,用户需要使用kubectl label nodes命令给节点打标签。另外,可能需要提醒用户更新现有的StatefulSet是否需要删除并重新创建,或者是否可以动态更新。根据Kubernetes的机制,StatefulSet的某些字段可以动态更新,但可能需要使用apply命令或者edit命令。 然后,用户可能需要一个具体的示例,比如在StatefulSet的YAML中添加nodeSelector部分。比如在spec.template.spec下添加: nodeSelector: disktype: ssd 同时,需要确保节点上有disktype=ssd的标签。 另外,用户可能想知道如何验证配置是否生效,比如通过describe pod查看调度到的节点,或者检查Events部分是否有错误。 可能的问题还包括,如果NodeSelector指定的标签不存在,Pod会处于Pending状态,这时候需要检查节点标签是否正确。 总结步骤应该是:1. 给目标节点打标签;2. 在StatefulSet的Pod模板中添加nodeSelector;3. 应用配置;4. 验证Pod调度情况。 最后,生成相关问题时,可以考虑NodeSelector的其他用法、动态更新策略、与亲和性的区别,或者如何排查调度失败的问题。</think>在Kubernetes StatefulSet中配置NodeSelector需要通过Pod模板的$spec.template.spec$字段实现。以下是具体操作步骤: ### 方法步骤 1. **标记目标节点** 使用命令为节点添加标签(例如选择带有SSD磁盘的节点): ```bash kubectl label nodes <node-name> disktype=ssd ``` 2. **修改StatefulSet配置** 在StatefulSet的YAML文件中,在$spec.template.spec$层级添加`nodeSelector`字段: ```yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: zk spec: serviceName: zk-headless replicas: 3 template: metadata: labels: app: zookeeper spec: nodeSelector: # 关键配置 disktype: ssd # 匹配节点的标签 containers: - name: zk image: zookeeper:3.6 ``` 3. **应用配置变更** 通过声明式更新触发调度策略生效: ```bash kubectl apply -f zk-statefulset.yaml ``` ### 验证方法 - 查看Pod调度结果: ```bash kubectl get pods -o wide | grep zk- ``` - 检查Pod事件日志: ```bash kubectl describe pod zk-0 | grep Node-Selectors ``` ### 原理说明 NodeSelector通过硬性匹配标签实现Pod调度[^3],若目标节点不存在对应标签,Pod将保持Pending状态。此方法与`affinity`相比属于基础调度策略,适用于简单场景[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值