Pod 分配给节点的几种机制
1、节点选择器 nodeSelector
功能:选择具有指定标签的node节点创建pod。
如果一个pod对象指定了spec.nodeSelector属性,则要求这个pod只能运行在指定的标签node上;如果指定的标签不存在,则pod将无法创建成功。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: registry.cn-shanghai.aliyuncs.com/yuanqh/public:nginx
imagePullPolicy: IfNotPresent
nodeSelector:
appType: nginx
这个例子中要求node必须有label为 appType=nginx,才能启动pod
我们发现k8s的node默认有很多内置的节点标签
kubernetes.io/hostname
failure-domain.beta.kubernetes.io/zone
failure-domain.beta.kubernetes.io/region
topology.kubernetes.io/zone
topology.kubernetes.io/region
beta.kubernetes.io/instance-type
node.kubernetes.io/instance-type
kubernetes.io/os
kubernetes.io/arch
这些标签的值是特定于云供应商的,因此不能保证可靠。 例如,kubernetes.io/hostname 的值在某些环境中可能与节点名称相同, 但在其他环境中可能是一个不同的值。
2、node亲和性
requiredDuringSchedulingIgnoredDuringExecution
位置:pod.spec.affinity.nodeAffinity
.requiredDuringSchedulingIgnoredDuringExecution
表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中IgnoreDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,pod也会继续运行。
requiredDuringSchedulingRequiredDuringExecution
与 requiredDuringSchedulingIgnoredDuringExecution 完全相同, 只是它会将 Pod 从不再满足 Pod 的节点亲和性要求的节点上驱逐。具体实现版本不清楚
preferredDuringSchedulingIgnoredDuringExecution
位置:pod.spec.affinity.nodeAffinity
.preferredDuringSchedulingIgnoredDuringExecution
表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。
preferredDuringSchedulingRequiredDuringExecution
与preferredDuringSchedulingIgnoredDuringExecution相同,只是如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点。具体实现版本不清楚
综上可知:
*RequiredDuringExecution | 表示支持根据标签动态调整pod的行为。 |
---|---|
*IgnoredDuringExecution | 表示第一次部署pod的行为,后续node标签变化,将不会主动影响pod |
下面是官方的一个例子
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
此节点亲和性规则表示,Pod 只能放置在具有标签键 kubernetes.io/e2e-az-name
且标签值为 e2e-az1 或 e2e-az2 的节点上。 另外,在满足这些标准的节点中,具有标签键为 another-node-label-key
且标签值为 another-node-label-value 的节点应该优先使用。
这里的匹配逻辑是label在某个列表中,可选的操作符有:
- In: label的值在某个列表中
- NotIn:label的值不在某个列表中
- Exists:某个label存在
- DoesNotExist:某个label不存在
- Gt:label的值大于某个值(字符串比较)
- Lt:label的值小于某个值(字符串比较)
3、pod亲和性和反亲和性
如果 X 节点上已经运行了一个或多个 满足规则 Y 的 Pod, 则这个 Pod 应该(或者在反亲和性的情况下不应该)运行在 X 节点。
与节点亲和性一样,当前有两种类型的 Pod 亲和性与反亲和性,即 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,分别表示“硬性”与“软性”要求。 请参阅前面节点亲和性部分中的描述。
位置:pod.spec.affinity.podAffinity
.requiredDuringSchedulingIgnoredDuringExecution
pod.spec.affinity.podAffinity
.preferredDuringSchedulingIgnoredDuringExecution
和node亲和性的配置区别就是node换成了pod
下面是官方的一个例子
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: k8s.gcr.io/pause:2.0
其中topologyKey代表启用了拓扑约束
配置 topologyKey
: topology.kubernetes.io/zone 表示集群中至少有一个节点具有键 topology.kubernetes.io/zone,才能调度pod到该节点,而每个不同的标签有不同的含义。
原则上,topologyKey 可以是任何合法的标签键。 然而,出于性能和安全原因,topologyKey 受到一些限制:
- 对于 Pod 亲和性而言,在 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 不允许为空。
- 对于 Pod 反亲和性而言,requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 都不可以为空。
- 对于 requiredDuringSchedulingIgnoredDuringExecution 要求的 Pod 反亲和性, 准入控制器 LimitPodHardAntiAffinityTopology 被引入以确保 topologyKey 只能是 kubernetes.io/hostname。如果你希望 topologyKey 也可用于其他定制 拓扑逻辑,你可以更改准入控制器或者禁用之。
- 除上述情况外,topologyKey 可以是任何合法的标签键。
需要注意:
Pod 间亲和性与反亲和性需要大量的处理,这可能会显著减慢大规模集群中的调度。 我们不建议在超过数百个节点的集群中使用它们。
Pod 反亲和性需要对节点进行一致的标记,即集群中的每个节点必须具有适当的标签能够匹配 topologyKey。如果某些或所有节点缺少指定的 topologyKey 标签,可能会导致意外行为。
反亲和性和亲和性类似
可以参考下面的例子
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