From 5bbc2a38763643cc188fec24e2fab4953e5f93cd Mon Sep 17 00:00:00 2001 From: xliuqq Date: Mon, 29 Apr 2024 23:02:22 +0800 Subject: [PATCH] fix conflict and use nodeAffinity Signed-off-by: xliuqq --- api/v1alpha1/openapi_generated.go | 21 +- api/v1alpha1/status.go | 2 +- api/v1alpha1/zz_generated.deepcopy.go | 6 +- .../fluid/crds/data.fluid.io_databackups.yaml | 199 +++++++++++++++++- .../fluid/crds/data.fluid.io_dataloads.yaml | 199 +++++++++++++++++- .../crds/data.fluid.io_datamigrates.yaml | 199 +++++++++++++++++- .../crds/data.fluid.io_dataprocesses.yaml | 199 +++++++++++++++++- .../crd/bases/data.fluid.io_databackups.yaml | 199 +++++++++++++++++- config/crd/bases/data.fluid.io_dataloads.yaml | 199 +++++++++++++++++- .../crd/bases/data.fluid.io_datamigrates.yaml | 199 +++++++++++++++++- .../bases/data.fluid.io_dataprocesses.yaml | 199 +++++++++++++++++- pkg/dataflow/affinity.go | 60 +++--- pkg/dataflow/affinity_test.go | 60 +++++- pkg/dataflow/helper.go | 77 +++++-- pkg/dataflow/helper_test.go | 68 ++++-- pkg/utils/affinity.go | 18 +- pkg/utils/affinity_test.go | 39 +++- 17 files changed, 1816 insertions(+), 127 deletions(-) diff --git a/api/v1alpha1/openapi_generated.go b/api/v1alpha1/openapi_generated.go index afd9d5fa217..48895ed460d 100644 --- a/api/v1alpha1/openapi_generated.go +++ b/api/v1alpha1/openapi_generated.go @@ -4983,20 +4983,10 @@ func schema_fluid_cloudnative_fluid_api_v1alpha1_OperationStatus(ref common.Refe Ref: ref("github.com/fluid-cloudnative/fluid/api/v1alpha1.WaitingStatus"), }, }, - "nodeLabels": { + "nodeAffinity": { SchemaProps: spec.SchemaProps{ - Description: "NodeAffinity defines the node labels for operation pods", - Type: []string{"object"}, - AdditionalProperties: &spec.SchemaOrBool{ - Allows: true, - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, + Description: "NodeAffinity records the node affinity for operation pods", + Ref: ref("k8s.io/api/core/v1.NodeAffinity"), }, }, }, @@ -5004,7 +4994,7 @@ func schema_fluid_cloudnative_fluid_api_v1alpha1_OperationStatus(ref common.Refe }, }, Dependencies: []string{ - "github.com/fluid-cloudnative/fluid/api/v1alpha1.Condition", "github.com/fluid-cloudnative/fluid/api/v1alpha1.WaitingStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + "github.com/fluid-cloudnative/fluid/api/v1alpha1.Condition", "github.com/fluid-cloudnative/fluid/api/v1alpha1.WaitingStatus", "k8s.io/api/core/v1.NodeAffinity", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, } } @@ -5057,7 +5047,8 @@ func schema_fluid_cloudnative_fluid_api_v1alpha1_Prefer(ref common.ReferenceCall return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Prefer defines the label key and weight for generating a PreferredSchedulingTerm.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ diff --git a/api/v1alpha1/status.go b/api/v1alpha1/status.go index cd04c958d73..e778303e5f3 100644 --- a/api/v1alpha1/status.go +++ b/api/v1alpha1/status.go @@ -152,7 +152,7 @@ type OperationStatus struct { // WaitingStatus stores information about waiting operation. WaitingFor WaitingStatus `json:"waitingFor,omitempty"` - // NodeAffinity defines the node labels for operation pods + // NodeAffinity records the node affinity for operation pods NodeAffinity *corev1.NodeAffinity `json:"nodeAffinity,omitempty"` } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 94e22bf744f..64da768cfa8 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -2157,10 +2157,8 @@ func (in *OperationStatus) DeepCopyInto(out *OperationStatus) { in.WaitingFor.DeepCopyInto(&out.WaitingFor) if in.NodeAffinity != nil { in, out := &in.NodeAffinity, &out.NodeAffinity - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } + *out = new(v1.NodeAffinity) + (*in).DeepCopyInto(*out) } } diff --git a/charts/fluid/fluid/crds/data.fluid.io_databackups.yaml b/charts/fluid/fluid/crds/data.fluid.io_databackups.yaml index 40601554472..5cb07ae1d5f 100644 --- a/charts/fluid/fluid/crds/data.fluid.io_databackups.yaml +++ b/charts/fluid/fluid/crds/data.fluid.io_databackups.yaml @@ -77,6 +77,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -200,10 +202,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/charts/fluid/fluid/crds/data.fluid.io_dataloads.yaml b/charts/fluid/fluid/crds/data.fluid.io_dataloads.yaml index 1c97a4eb692..ab1830d1bd3 100644 --- a/charts/fluid/fluid/crds/data.fluid.io_dataloads.yaml +++ b/charts/fluid/fluid/crds/data.fluid.io_dataloads.yaml @@ -965,6 +965,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -1129,10 +1131,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/charts/fluid/fluid/crds/data.fluid.io_datamigrates.yaml b/charts/fluid/fluid/crds/data.fluid.io_datamigrates.yaml index 3e2567e39d6..cd681238160 100644 --- a/charts/fluid/fluid/crds/data.fluid.io_datamigrates.yaml +++ b/charts/fluid/fluid/crds/data.fluid.io_datamigrates.yaml @@ -1031,6 +1031,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -1244,10 +1246,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/charts/fluid/fluid/crds/data.fluid.io_dataprocesses.yaml b/charts/fluid/fluid/crds/data.fluid.io_dataprocesses.yaml index 5e63346e74d..19b28fc219b 100644 --- a/charts/fluid/fluid/crds/data.fluid.io_dataprocesses.yaml +++ b/charts/fluid/fluid/crds/data.fluid.io_dataprocesses.yaml @@ -9316,6 +9316,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -9419,10 +9421,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/config/crd/bases/data.fluid.io_databackups.yaml b/config/crd/bases/data.fluid.io_databackups.yaml index 40601554472..5cb07ae1d5f 100644 --- a/config/crd/bases/data.fluid.io_databackups.yaml +++ b/config/crd/bases/data.fluid.io_databackups.yaml @@ -77,6 +77,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -200,10 +202,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/config/crd/bases/data.fluid.io_dataloads.yaml b/config/crd/bases/data.fluid.io_dataloads.yaml index 1c97a4eb692..ab1830d1bd3 100644 --- a/config/crd/bases/data.fluid.io_dataloads.yaml +++ b/config/crd/bases/data.fluid.io_dataloads.yaml @@ -965,6 +965,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -1129,10 +1131,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/config/crd/bases/data.fluid.io_datamigrates.yaml b/config/crd/bases/data.fluid.io_datamigrates.yaml index 3e2567e39d6..cd681238160 100644 --- a/config/crd/bases/data.fluid.io_datamigrates.yaml +++ b/config/crd/bases/data.fluid.io_datamigrates.yaml @@ -1031,6 +1031,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -1244,10 +1246,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/config/crd/bases/data.fluid.io_dataprocesses.yaml b/config/crd/bases/data.fluid.io_dataprocesses.yaml index 5e63346e74d..19b28fc219b 100644 --- a/config/crd/bases/data.fluid.io_dataprocesses.yaml +++ b/config/crd/bases/data.fluid.io_dataprocesses.yaml @@ -9316,6 +9316,8 @@ spec: type: string prefer: items: + description: Prefer defines the label key and weight for + generating a PreferredSchedulingTerm. properties: name: type: string @@ -9419,10 +9421,199 @@ spec: successfully completed format: date-time type: string - nodeLabels: - additionalProperties: - type: string - description: NodeLabels defines the node labels for operation pods + nodeAffinity: + description: NodeAffinity records the node affinity for operation + pods + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes + that satisfy the affinity expressions specified by this field, + but it may choose a node that violates one or more of the expressions. + The node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term matches all + objects with implicit weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches no objects (i.e. is also + a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field + are not met at scheduling time, the pod will not be scheduled + onto the node. If the affinity requirements specified by this + field cease to be met at some point during pod execution (e.g. + due to an update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The + terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by + node's labels. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by + node's fields. + items: + description: A node selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: Represents a key's relationship to + a set of values. Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the + operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator + is Gt or Lt, the values array must have a single + element, which will be interpreted as an integer. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object type: object phase: description: Phase describes current phase of operation diff --git a/pkg/dataflow/affinity.go b/pkg/dataflow/affinity.go index 36ba1894add..0bade545698 100644 --- a/pkg/dataflow/affinity.go +++ b/pkg/dataflow/affinity.go @@ -54,7 +54,7 @@ func InjectAffinityByRunAfterOp(c client.Client, runAfter *datav1alpha1.Operatio return currentAffinity, fmt.Errorf("unknown policy for affinity strategy: %s", runAfter.AffinityStrategy.Policy) } -func injectPreferredAffinity(runAfter *datav1alpha1.OperationRef, nodeLabels map[string]string, currentAffinity *v1.Affinity) (*v1.Affinity, error) { +func injectPreferredAffinity(runAfter *datav1alpha1.OperationRef, prevOpNodeAffinity *v1.NodeAffinity, currentAffinity *v1.Affinity) (*v1.Affinity, error) { var preferTerms []v1.PreferredSchedulingTerm prefer := runAfter.AffinityStrategy.Prefer if prefer == nil { @@ -65,20 +65,26 @@ func injectPreferredAffinity(runAfter *datav1alpha1.OperationRef, nodeLabels map }, } } + // currently, only has one element. + podNodeSelectorTerm := prevOpNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0] + for _, item := range prefer { - if value, ok := nodeLabels[item.Name]; ok { - preferTerms = append(preferTerms, v1.PreferredSchedulingTerm{ - Weight: item.Weight, - Preference: v1.NodeSelectorTerm{ - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: item.Name, - Operator: v1.NodeSelectorOpIn, - Values: []string{value}, + key := item.Name + for _, expression := range podNodeSelectorTerm.MatchExpressions { + if expression.Key == key { + preferTerms = append(preferTerms, v1.PreferredSchedulingTerm{ + Weight: item.Weight, + Preference: v1.NodeSelectorTerm{ + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: expression.Key, + Operator: expression.Operator, + Values: expression.Values, + }, }, }, - }, - }) + }) + } } } return utils.InjectPreferredSchedulingTermsToAffinity(preferTerms, currentAffinity), nil @@ -90,28 +96,26 @@ func injectRequiredAffinity(runAfter *datav1alpha1.OperationRef, prevOpNodeAffin return currentAffinity, nil } - var terms []v1.NodeSelectorTerm + var matchExpressions []v1.NodeSelectorRequirement keys := runAfter.AffinityStrategy.Require if keys == nil { keys = []string{common.K8sNodeNameLabelKey} } - for _, key := range keys { - - for match := range prevOpNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + // currently, only has one element. + podNodeSelectorTerm := prevOpNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0] - } - - if value, ok := nodeLabels[key]; ok { - terms = append(terms, v1.NodeSelectorTerm{ - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: key, - Operator: v1.NodeSelectorOpIn, - Values: []string{value}, + for _, key := range keys { + for _, expression := range podNodeSelectorTerm.MatchExpressions { + if expression.Key == key { + matchExpressions = append(matchExpressions, + v1.NodeSelectorRequirement{ + Key: expression.Key, + Operator: expression.Operator, + Values: expression.Values, }, - }, - }) + ) + } } } - return utils.InjectNodeSelectorTermsToAffinity(terms, currentAffinity), nil + return utils.InjectNodeSelectorRequirements(matchExpressions, currentAffinity), nil } diff --git a/pkg/dataflow/affinity_test.go b/pkg/dataflow/affinity_test.go index e5fa372d5e0..e7b70f2b025 100644 --- a/pkg/dataflow/affinity_test.go +++ b/pkg/dataflow/affinity_test.go @@ -106,8 +106,20 @@ func TestInjectAffinityByRunAfterOp(t *testing.T) { Namespace: "default", }, Status: datav1alpha1.OperationStatus{ - NodeAffinity: map[string]string{ - common.K8sNodeNameLabelKey: "node01", + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: common.K8sNodeNameLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node01"}, + }, + }, + }, + }, + }, }, }, }, @@ -152,8 +164,20 @@ func TestInjectAffinityByRunAfterOp(t *testing.T) { Namespace: "default", }, Status: datav1alpha1.OperationStatus{ - NodeAffinity: map[string]string{ - "k8s.rack": "rack01", + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "k8s.rack", + Operator: v1.NodeSelectorOpIn, + Values: []string{"rack01"}, + }, + }, + }, + }, + }, }, }, }, @@ -204,10 +228,30 @@ func TestInjectAffinityByRunAfterOp(t *testing.T) { Namespace: "test", }, Status: datav1alpha1.OperationStatus{ - NodeAffinity: map[string]string{ - common.K8sNodeNameLabelKey: "node01", - common.K8sZoneLabelKey: "zone01", - common.K8sRegionLabelKey: "region01", + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: common.K8sNodeNameLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node01"}, + }, + { + Key: common.K8sZoneLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"zone01"}, + }, + { + Key: common.K8sRegionLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"region01"}, + }, + }, + }, + }, + }, }, }, }, diff --git a/pkg/dataflow/helper.go b/pkg/dataflow/helper.go index 3b3b813ddfc..71d1cd427de 100644 --- a/pkg/dataflow/helper.go +++ b/pkg/dataflow/helper.go @@ -25,65 +25,104 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func GenerateNodeLabels(c client.Client, pod *corev1.Pod) (map[string]string, error) { - var result = map[string]string{} +func GenerateNodeLabels(c client.Client, pod *corev1.Pod) (*corev1.NodeAffinity, error) { if pod == nil { - return result, nil + return nil, nil } nodeName := pod.Spec.NodeName if len(nodeName) == 0 { - return result, nil + return nil, nil } - // node name - result[common.K8sNodeNameLabelKey] = nodeName var node corev1.Node err := c.Get(context.TODO(), types.NamespacedName{Name: nodeName}, &node) if err != nil { - return result, fmt.Errorf("error to get node %s: %v", nodeName, err) + return nil, fmt.Errorf("error to get node %s: %v", nodeName, err) } + + // node name + nodeAffinity := &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: common.K8sNodeNameLabelKey, + Operator: corev1.NodeSelectorOpIn, + Values: []string{nodeName}, + }, + }, + }, + }, + }, + } + // region region, exist := node.Labels[common.K8sRegionLabelKey] if exist { - result[common.K8sRegionLabelKey] = region + nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions = + append(nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions, + corev1.NodeSelectorRequirement{ + Key: common.K8sRegionLabelKey, + Operator: corev1.NodeSelectorOpIn, + Values: []string{region}, + }) } // zone zone, exist := node.Labels[common.K8sZoneLabelKey] if exist { - result[common.K8sZoneLabelKey] = zone + nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions = + append(nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions, + corev1.NodeSelectorRequirement{ + Key: common.K8sZoneLabelKey, + Operator: corev1.NodeSelectorOpIn, + Values: []string{zone}, + }) } // customized labels if pod.Spec.Affinity != nil && pod.Spec.Affinity.NodeAffinity != nil { - fillCustomizedNodeLabels(pod.Spec.Affinity.NodeAffinity, result, &node) + fillCustomizedNodeAffinity(pod.Spec.Affinity.NodeAffinity, nodeAffinity, &node) } - return result, nil + return nodeAffinity, nil } -func fillCustomizedNodeLabels(nodeAffinity *corev1.NodeAffinity, result map[string]string, node *corev1.Node) { +func fillCustomizedNodeAffinity(podNodeAffinity *corev1.NodeAffinity, dstNodeAffinity *corev1.NodeAffinity, node *corev1.Node) { // prefer - for _, term := range nodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution { + for _, term := range podNodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution { for _, expression := range term.Preference.MatchExpressions { - // use the actually value in the node. + // use the actually value in the node. Transform In, NotIn, Exists, DoesNotExist. Gt, and Lt to In. value, exist := node.Labels[expression.Key] if exist { - result[expression.Key] = value + dstNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions = + append(dstNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions, + corev1.NodeSelectorRequirement{ + Key: expression.Key, + Operator: corev1.NodeSelectorOpIn, + Values: []string{value}, + }) } } } - if nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { + if podNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { return } // require - for _, term := range nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + for _, term := range podNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { for _, expression := range term.MatchExpressions { - // use the actually value in the node. + // use the actually value in the node. Transform In, NotIn, Exists, DoesNotExist. Gt, and Lt to In. value, exist := node.Labels[expression.Key] if exist { - result[expression.Key] = value + dstNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions = + append(dstNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions, + corev1.NodeSelectorRequirement{ + Key: expression.Key, + Operator: corev1.NodeSelectorOpIn, + Values: []string{value}, + }) } } } diff --git a/pkg/dataflow/helper_test.go b/pkg/dataflow/helper_test.go index 0125d51231e..733864855a9 100644 --- a/pkg/dataflow/helper_test.go +++ b/pkg/dataflow/helper_test.go @@ -19,7 +19,7 @@ func TestGenerateNodeLabels(t *testing.T) { tests := []struct { name string args args - want map[string]string + want *v1.NodeAffinity wantErr bool }{ { @@ -41,10 +41,30 @@ func TestGenerateNodeLabels(t *testing.T) { }, }, }, - want: map[string]string{ - common.K8sNodeNameLabelKey: "node01", - common.K8sRegionLabelKey: "region01", - common.K8sZoneLabelKey: "zone01", + want: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: common.K8sNodeNameLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node01"}, + }, + { + Key: common.K8sRegionLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"region01"}, + }, + { + Key: common.K8sZoneLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"zone01"}, + }, + }, + }, + }, + }, }, wantErr: false, }, @@ -63,7 +83,7 @@ func TestGenerateNodeLabels(t *testing.T) { }, }, }, - want: map[string]string{}, + want: nil, wantErr: false, }, { @@ -112,16 +132,40 @@ func TestGenerateNodeLabels(t *testing.T) { common.K8sNodeNameLabelKey: "node01", common.K8sZoneLabelKey: "zone01", "k8s.rack": "rack01", - "k8s.gpu": "true", + "k8s.gpu": "false", }, }, }, }, - want: map[string]string{ - common.K8sNodeNameLabelKey: "node01", - common.K8sZoneLabelKey: "zone01", - "k8s.rack": "rack01", - "k8s.gpu": "true", + want: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: common.K8sNodeNameLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node01"}, + }, + { + Key: common.K8sZoneLabelKey, + Operator: v1.NodeSelectorOpIn, + Values: []string{"zone01"}, + }, + { + Key: "k8s.gpu", + Operator: v1.NodeSelectorOpIn, + Values: []string{"false"}, + }, + { + Key: "k8s.rack", + Operator: v1.NodeSelectorOpIn, + Values: []string{"rack01"}, + }, + }, + }, + }, + }, }, wantErr: false, }, diff --git a/pkg/utils/affinity.go b/pkg/utils/affinity.go index e6a71f561a5..8890b013ac8 100644 --- a/pkg/utils/affinity.go +++ b/pkg/utils/affinity.go @@ -18,7 +18,8 @@ package utils import v1 "k8s.io/api/core/v1" -func InjectNodeSelectorTermsToAffinity(terms []v1.NodeSelectorTerm, affinity *v1.Affinity) *v1.Affinity { +// InjectNodeSelectorRequirements injects(not append) a node selector term to affinity‘s nodeAffinity. +func InjectNodeSelectorRequirements(matchExpressions []v1.NodeSelectorRequirement, affinity *v1.Affinity) *v1.Affinity { result := affinity if affinity == nil { result = &v1.Affinity{} @@ -30,8 +31,19 @@ func InjectNodeSelectorTermsToAffinity(terms []v1.NodeSelectorTerm, affinity *v1 if result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = &v1.NodeSelector{} } - result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = - append(result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, terms...) + // no element + if result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms == nil { + result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = []v1.NodeSelectorTerm{ + { + MatchExpressions: matchExpressions, + }, + } + return result + } + // has element, inject term's match expressions to each element + for _, nodeSelectorTerm := range result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + nodeSelectorTerm.MatchExpressions = append(nodeSelectorTerm.MatchExpressions, matchExpressions...) + } return result } diff --git a/pkg/utils/affinity_test.go b/pkg/utils/affinity_test.go index 98d06b107ee..b6b120cdfed 100644 --- a/pkg/utils/affinity_test.go +++ b/pkg/utils/affinity_test.go @@ -24,20 +24,49 @@ import ( func TestInjectNodeSelectorTermsToAffinity(t *testing.T) { type args struct { - terms []v1.NodeSelectorTerm - affinity *v1.Affinity + expressions []v1.NodeSelectorRequirement + affinity *v1.Affinity } tests := []struct { name string args args want *v1.Affinity }{ - // TODO: Add test cases. + { + name: "test1", + args: args{ + expressions: []v1.NodeSelectorRequirement{ + { + Key: "test", + Operator: v1.NodeSelectorOpIn, + Values: []string{"test"}, + }, + }, + affinity: &v1.Affinity{}, + }, + want: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "test", + Operator: v1.NodeSelectorOpIn, + Values: []string{"test"}, + }, + }, + }, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := InjectNodeSelectorTermsToAffinity(tt.args.terms, tt.args.affinity); !reflect.DeepEqual(got, tt.want) { - t.Errorf("InjectNodeSelectorTermsToAffinity() = %v, want %v", got, tt.want) + if got := InjectNodeSelectorRequirements(tt.args.expressions, tt.args.affinity); !reflect.DeepEqual(got, tt.want) { + t.Errorf("InjectNodeSelectorRequirements() = %v, want %v", got, tt.want) } }) }