4.3. 使用关联性和反关联性规则相对于其他 pod 放置 pod
关联性是 pod 的一个属性,用于控制它们希望调度到的节点。反关联性是 pod 的一个属性,用于阻止 pod 调度到某个节点上。
在 OpenShift Container Platform 中,可以借助 pod 关联性和 pod 反关联性来根据其他 pod 上的键/值标签限制 pod 有资格调度到哪些节点。
4.3.1. 了解 pod 关联性
您可以借助 pod 关联性和 pod 反关联性来根据其他 pod 上的键/值标签限制 pod 有资格调度到哪些节点。
- 如果新 pod 上的标签选择器与当前 pod 上的标签匹配,pod 关联性可以命令调度程序将新 pod 放置到与其他 pod 相同的节点上。
- 如果新 pod 上的标签选择器与当前 pod 上的标签匹配,pod 反关联性可以阻止调度程序将新 pod 放置到与具有相同标签的 pod 相同的节点上。
例如,您可以使用关联性规则,在服务内或相对于其他服务中的 pod 来分散或聚拢 pod。如果特定服务的 pod 的性能已知会受到另一服务的 pod 影响,那么您可以利用反关联性规则,防止前一服务的 pod 调度到与后一服务的 pod 相同的节点上。或者,您可以将服务的 pod 分散到节点间、可用性区域或可用性集,以减少相关的故障。
标签选择器可能与带有多个 pod 部署的 pod 匹配。在配置反关联性规则时,请使用标签的唯一组合以避免匹配的 pod。
pod 关联性规则有两种,即必要规则和偏好规则。
必须满足必要规则,pod 才能调度到节点上。偏好规则指定在满足规则时调度程序会尝试强制执行规则,但不保证一定能强制执行成功。
根据 pod 优先级和抢占设置,调度程序可能无法在不违反关联性要求的前提下为 pod 找到适合的节点。若是如此,pod 可能不会被调度。
要防止这种情况,请仔细配置优先级相同的 pod 的 pod 关联性。
您可以通过 Pod
规格文件配置 pod 关联性/反关联性。您可以指定必要规则或偏好规则,或同时指定这两种规则。如果您同时指定,节点必须首先满足必要规则,然后尝试满足偏好规则。
以下示例显示了配置了 pod 关联性和反关联性的 Pod
规格。
在本例中,pod 关联性规则指明,只有当节点至少有一个已在运行且具有键 security
和值 S1
的标签的 pod 时,pod 才可以调度到这个节点上。pod 反关联性则表示,如果节点已在运行带有键 security
和值 S2
.的标签的 pod,则 pod 将偏向于不调度到该节点上。
具有 pod 关联性的 Pod
配置文件示例
apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault affinity: podAffinity: 1 requiredDuringSchedulingIgnoredDuringExecution: 2 - labelSelector: matchExpressions: - key: security 3 operator: In 4 values: - S1 5 topologyKey: topology.kubernetes.io/zone containers: - name: with-pod-affinity image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
具有 pod 反关联性的 Pod
配置文件示例
apiVersion: v1 kind: Pod metadata: name: with-pod-antiaffinity spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault affinity: podAntiAffinity: 1 preferredDuringSchedulingIgnoredDuringExecution: 2 - weight: 100 3 podAffinityTerm: labelSelector: matchExpressions: - key: security 4 operator: In 5 values: - S2 topologyKey: kubernetes.io/hostname containers: - name: with-pod-affinity image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
如果节点标签在运行时改变,使得不再满足 pod 上的关联性规则,pod 会继续在该节点上运行。
4.3.2. 配置 pod 关联性规则
以下步骤演示了一个简单的双 pod 配置,它创建一个带有某标签的 pod,以及一个使用关联性来允许随着该 pod 一起调度的 pod。
您不能直接将关联性添加到调度的 pod 中。
流程
创建 pod 规格中具有特定标签的 pod:
使用以下内容创建 YAML 文件:
apiVersion: v1 kind: Pod metadata: name: security-s1 labels: security: S1 spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: security-s1 image: docker.io/ocpqe/hello-pod securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault
创建 pod。
$ oc create -f <pod-spec>.yaml
在创建其他 pod 时,配置以下参数以添加关联性:
使用以下内容创建 YAML 文件:
apiVersion: v1 kind: Pod metadata: name: security-s1-east # ... spec: affinity: 1 podAffinity: requiredDuringSchedulingIgnoredDuringExecution: 2 - labelSelector: matchExpressions: - key: security 3 values: - S1 operator: In 4 topologyKey: topology.kubernetes.io/zone 5 # ...
- 1
- 添加 pod 关联性。
- 2
- 配置
requiredDuringSchedulingIgnoredDuringExecution
参数或preferredDuringSchedulingIgnoredDuringExecution
参数。 - 3
- 指定必须满足的
key
和values
。如果您希望新 pod 与其他 pod 一起调度,请使用与第一个 pod 上标签相同的key
和values
参数。 - 4
- 指定一个
operator
。运算符可以是In
、NotIn
、Exists
或DoesNotExist
。例如,使用运算符In
来要求节点上存在该标签。 - 5
- 指定
topologyKey
,这是一个预填充的 Kubernetes 标签,供系统用于表示这样的拓扑域。
创建 pod。
$ oc create -f <pod-spec>.yaml
4.3.3. 配置 pod 反关联性规则
以下步骤演示了一个简单的双 pod 配置,它创建一个带有某标签的 pod,以及一个使用反关联性偏好规则来尝试阻止随着该 pod 一起调度的 pod。
您不能直接将关联性添加到调度的 pod 中。
流程
创建 pod 规格中具有特定标签的 pod:
使用以下内容创建 YAML 文件:
apiVersion: v1 kind: Pod metadata: name: security-s1 labels: security: S1 spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: security-s1 image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
创建 pod。
$ oc create -f <pod-spec>.yaml
在创建其他 pod 时,配置以下参数:
使用以下内容创建 YAML 文件:
apiVersion: v1 kind: Pod metadata: name: security-s2-east # ... spec: # ... affinity: 1 podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: 2 - weight: 100 3 podAffinityTerm: labelSelector: matchExpressions: - key: security 4 values: - S1 operator: In 5 topologyKey: kubernetes.io/hostname 6 # ...
- 1
- 添加 pod 反关联性。
- 2
- 配置
requiredDuringSchedulingIgnoredDuringExecution
参数或preferredDuringSchedulingIgnoredDuringExecution
参数。 - 3
- 对于一个首选的规则,为节点指定一个 1-100 的权重。优先选择权重最高的节点。
- 4
- 指定必须满足的
key
和values
。如果您希望新 pod 不与其他 pod 一起调度,请使用与第一个 pod 上标签相同的key
和values
参数。 - 5
- 指定一个
operator
。运算符可以是In
、NotIn
、Exists
或DoesNotExist
。例如,使用运算符In
来要求节点上存在该标签。 - 6
- 指定
topologyKey
,它是一个预先填充的 Kubernetes 标签,用于表示这样的拓扑域。
创建 pod。
$ oc create -f <pod-spec>.yaml
4.3.4. pod 关联性和反关联性规则示例
以下示例演示了 pod 关联性和 pod 反关联性。
4.3.4.1. Pod 关联性
以下示例演示了具有匹配标签和标签选择器的 pod 的 pod 关联性。
pod team4 具有标签
team:4
。apiVersion: v1 kind: Pod metadata: name: team4 labels: team: "4" # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: ocp image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
pod team4a 在
podAffinity
下具有标签选择器team:4
。apiVersion: v1 kind: Pod metadata: name: team4a # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: team operator: In values: - "4" topologyKey: kubernetes.io/hostname containers: - name: pod-affinity image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
- team4a pod 调度到与 team4 pod 相同的节点上。
4.3.4.2. Pod 反关联性
以下示例演示了具有匹配标签和标签选择器的 pod 的 pod 反关联性。
pod pod-s1 具有标签
security:s1
。apiVersion: v1 kind: Pod metadata: name: pod-s1 labels: security: s1 # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: ocp image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
pod pod-s2 在
podAntiAffinity
下具有标签选择器security:s1
。apiVersion: v1 kind: Pod metadata: name: pod-s2 # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - s1 topologyKey: kubernetes.io/hostname containers: - name: pod-antiaffinity image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
-
pod pod-s2 无法调度到与
pod-s1
相同的节点上。
4.3.4.3. 无匹配标签的 Pod 反关联性
以下示例演示了在没有匹配标签和标签选择器时的 pod 的 pod 关联性。
pod pod-s1 具有标签
security:s1
。apiVersion: v1 kind: Pod metadata: name: pod-s1 labels: security: s1 # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: ocp image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
pod pod-s2 具有标签选择器
security:s2
。apiVersion: v1 kind: Pod metadata: name: pod-s2 # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - s2 topologyKey: kubernetes.io/hostname containers: - name: pod-affinity image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
除非节点上具有带
security:s2
标签的 pod,否则不会调度 pod-s2。如果没有具有该标签的其他 pod,新 pod 会保持在待处理状态:输出示例
NAME READY STATUS RESTARTS AGE IP NODE pod-s2 0/1 Pending 0 32s <none>
4.3.5. 使用 pod 关联性和反关联性来控制安装 Operator 的位置
默认情况下,当安装 Operator 时,OpenShift Container Platform 会随机将 Operator pod 安装到其中一个 worker 节点。然而,在某些情况下,您可能希望该 pod 调度到特定节点或一组节点上。
以下示例描述了您可能希望将 Operator pod 调度到特定节点或一组节点的情况:
-
如果 Operator 需要特定的平台,如
amd64
或arm64
- 如果 Operator 需要特定的操作系统,如 Linux 或 Windows
- 如果您希望 Operator 在同一个主机上或位于同一机架的主机上工作
- 如果您希望 Operator 在整个基础架构中分散,以避免因为网络或硬件问题而停机
您可以通过向 Operator 的 Subscription
对象添加 pod 关联性或反关联性来控制 Operator pod 的安装位置。
以下示例演示了如何使用 pod 反关联性来防止从具有特定标签的 pod 中安装自定义 Metrics Autoscaler Operator:
将 Operator pod 放置到一个或多个特定节点的 Pod 关联性示例
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: openshift-custom-metrics-autoscaler-operator
namespace: openshift-keda
spec:
name: my-package
source: my-operators
sourceNamespace: operator-registries
config:
affinity:
podAffinity: 1
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- test
topologyKey: kubernetes.io/hostname
#...
- 1
- 将 Operator 的 pod 放置到具有
app=test
标签的 pod 的节点上的 pod 关联性。
防止 Operator pod 来自一个或多个特定节点的 Pod 反关联性示例
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: openshift-custom-metrics-autoscaler-operator
namespace: openshift-keda
spec:
name: my-package
source: my-operators
sourceNamespace: operator-registries
config:
affinity:
podAntiAffinity: 1
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: cpu
operator: In
values:
- high
topologyKey: kubernetes.io/hostname
#...
- 1
- 一个 pod 反关联性,它可防止 Operator 的 pod 调度到具有
cpu=high
标签的 pod 的节点上。
流程
要控制 Operator pod 的放置,请完成以下步骤:
- 照常安装 Operator。
- 如果需要,请确保您的节点已标记为正确响应关联性。
编辑 Operator
Subscription
对象以添加关联性:apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: openshift-custom-metrics-autoscaler-operator namespace: openshift-keda spec: name: my-package source: my-operators sourceNamespace: operator-registries config: affinity: podAntiAffinity: 1 requiredDuringSchedulingIgnoredDuringExecution: podAffinityTerm: labelSelector: matchExpressions: - key: kubernetes.io/hostname operator: In values: - ip-10-0-185-229.ec2.internal topologyKey: topology.kubernetes.io/zone #...
- 1
- 添加
podAffinity
或podAntiAffinity
。
验证
要确保 pod 部署到特定的节点上,请运行以下命令:
$ oc get pods -o wide
输出示例
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES custom-metrics-autoscaler-operator-5dcc45d656-bhshg 1/1 Running 0 50s 10.131.0.20 ip-10-0-185-229.ec2.internal <none> <none>