Skip to content

Commit 8076745

Browse files
authored
Add topologySpreadConstraints to PodSpec (#522)
* Add topologySpreadConstraints Add `topologySpreadConstraints` support to pod specification. Signed-off-by: Nick Huanca <[email protected]> * Add crd changes to helm chart for ZK instance Signed-off-by: Nick Huanca <[email protected]> * Test to make sure we have topospreadconst Signed-off-by: Nick Huanca <[email protected]> * Add coverage in deepcopy_test.go Signed-off-by: Nick Huanca <[email protected]> * Add test for deepcopy Signed-off-by: Nick Huanca <[email protected]> Signed-off-by: Nick Huanca <[email protected]>
1 parent adcf3bf commit 8076745

File tree

9 files changed

+310
-3
lines changed

9 files changed

+310
-3
lines changed

api/v1beta1/deepcopy_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ var _ = Describe("ZookeeperCluster DeepCopy", func() {
173173
It("value of Tol should be example", func() {
174174
Ω(z2.Spec.Pod.Tolerations[0].Key).To(Equal("tol"))
175175
})
176+
It("have empty topologySpreadConstraints", func() {
177+
Ω(z2.Spec.Pod.TopologySpreadConstraints).To(HaveLen(0))
178+
})
176179
It("checking status conditions", func() {
177180
Ω(z2.Status.Conditions[0].Reason).To(Equal(z1.Status.Conditions[0].Reason))
178181
})
@@ -242,6 +245,14 @@ var _ = Describe("ZookeeperCluster DeepCopy", func() {
242245
podpolicy2 := podpolicy.DeepCopy()
243246
Ω(podpolicy2).To(BeNil())
244247
})
248+
It("checking for deepcopy podpolicy.topologyspreadconstraints", func() {
249+
t := v1.TopologySpreadConstraint{}
250+
podpolicy := v1beta1.PodPolicy{
251+
TopologySpreadConstraints: []v1.TopologySpreadConstraint{t},
252+
}
253+
podpolicy2 := podpolicy.DeepCopy()
254+
Ω(podpolicy2.TopologySpreadConstraints).To(HaveLen(1))
255+
})
245256
It("checking for nil zookeepercluster", func() {
246257
var zk *v1beta1.ZookeeperCluster
247258
zk2 := zk.DeepCopy()

api/v1beta1/zookeepercluster_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ type PodPolicy struct {
445445
// The scheduling constraints on pods.
446446
Affinity *v1.Affinity `json:"affinity,omitempty"`
447447

448+
// TopologySpreadConstraints to apply to the pods
449+
TopologySpreadConstraints []v1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
450+
448451
// Resources is the resource requirements for the container.
449452
// This field cannot be updated once the cluster is created.
450453
Resources v1.ResourceRequirements `json:"resources,omitempty"`

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4133,6 +4133,144 @@ spec:
41334133
type: string
41344134
type: object
41354135
type: array
4136+
topologySpreadConstraints:
4137+
description: TopologySpreadConstraints to apply to the pods
4138+
items:
4139+
description: TopologySpreadConstraint specifies how to spread
4140+
matching pods among the given topology.
4141+
properties:
4142+
labelSelector:
4143+
description: LabelSelector is used to find matching pods.
4144+
Pods that match this label selector are counted to determine
4145+
the number of pods in their corresponding topology domain.
4146+
properties:
4147+
matchExpressions:
4148+
description: matchExpressions is a list of label selector
4149+
requirements. The requirements are ANDed.
4150+
items:
4151+
description: A label selector requirement is a selector
4152+
that contains values, a key, and an operator that
4153+
relates the key and values.
4154+
properties:
4155+
key:
4156+
description: key is the label key that the selector
4157+
applies to.
4158+
type: string
4159+
operator:
4160+
description: operator represents a key's relationship
4161+
to a set of values. Valid operators are In,
4162+
NotIn, Exists and DoesNotExist.
4163+
type: string
4164+
values:
4165+
description: values is an array of string values.
4166+
If the operator is In or NotIn, the values array
4167+
must be non-empty. If the operator is Exists
4168+
or DoesNotExist, the values array must be empty.
4169+
This array is replaced during a strategic merge
4170+
patch.
4171+
items:
4172+
type: string
4173+
type: array
4174+
required:
4175+
- key
4176+
- operator
4177+
type: object
4178+
type: array
4179+
matchLabels:
4180+
additionalProperties:
4181+
type: string
4182+
description: matchLabels is a map of {key,value} pairs.
4183+
A single {key,value} in the matchLabels map is equivalent
4184+
to an element of matchExpressions, whose key field
4185+
is "key", the operator is "In", and the values array
4186+
contains only "value". The requirements are ANDed.
4187+
type: object
4188+
type: object
4189+
maxSkew:
4190+
description: 'MaxSkew describes the degree to which pods
4191+
may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`,
4192+
it is the maximum permitted difference between the number
4193+
of matching pods in the target topology and the global
4194+
minimum. The global minimum is the minimum number of matching
4195+
pods in an eligible domain or zero if the number of eligible
4196+
domains is less than MinDomains. For example, in a 3-zone
4197+
cluster, MaxSkew is set to 1, and pods with the same labelSelector
4198+
spread as 2/2/1: In this case, the global minimum is 1.
4199+
| zone1 | zone2 | zone3 | | P P | P P | P | -
4200+
if MaxSkew is 1, incoming pod can only be scheduled to
4201+
zone3 to become 2/2/2; scheduling it onto zone1(zone2)
4202+
would make the ActualSkew(3-1) on zone1(zone2) violate
4203+
MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled
4204+
onto any zone. When `whenUnsatisfiable=ScheduleAnyway`,
4205+
it is used to give higher precedence to topologies that
4206+
satisfy it. It''s a required field. Default value is 1
4207+
and 0 is not allowed.'
4208+
format: int32
4209+
type: integer
4210+
minDomains:
4211+
description: "MinDomains indicates a minimum number of eligible
4212+
domains. When the number of eligible domains with matching
4213+
topology keys is less than minDomains, Pod Topology Spread
4214+
treats \"global minimum\" as 0, and then the calculation
4215+
of Skew is performed. And when the number of eligible
4216+
domains with matching topology keys equals or greater
4217+
than minDomains, this value has no effect on scheduling.
4218+
As a result, when the number of eligible domains is less
4219+
than minDomains, scheduler won't schedule more than maxSkew
4220+
Pods to those domains. If value is nil, the constraint
4221+
behaves as if MinDomains is equal to 1. Valid values are
4222+
integers greater than 0. When value is not nil, WhenUnsatisfiable
4223+
must be DoNotSchedule. \n For example, in a 3-zone cluster,
4224+
MaxSkew is set to 2, MinDomains is set to 5 and pods with
4225+
the same labelSelector spread as 2/2/2: | zone1 | zone2
4226+
| zone3 | | P P | P P | P P | The number of domains
4227+
is less than 5(MinDomains), so \"global minimum\" is treated
4228+
as 0. In this situation, new pod with the same labelSelector
4229+
cannot be scheduled, because computed skew will be 3(3
4230+
- 0) if new Pod is scheduled to any of the three zones,
4231+
it will violate MaxSkew. \n This is an alpha field and
4232+
requires enabling MinDomainsInPodTopologySpread feature
4233+
gate."
4234+
format: int32
4235+
type: integer
4236+
topologyKey:
4237+
description: TopologyKey is the key of node labels. Nodes
4238+
that have a label with this key and identical values are
4239+
considered to be in the same topology. We consider each
4240+
<key, value> as a "bucket", and try to put balanced number
4241+
of pods into each bucket. We define a domain as a particular
4242+
instance of a topology. Also, we define an eligible domain
4243+
as a domain whose nodes match the node selector. e.g.
4244+
If TopologyKey is "kubernetes.io/hostname", each Node
4245+
is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone",
4246+
each zone is a domain of that topology. It's a required
4247+
field.
4248+
type: string
4249+
whenUnsatisfiable:
4250+
description: 'WhenUnsatisfiable indicates how to deal with
4251+
a pod if it doesn''t satisfy the spread constraint. -
4252+
DoNotSchedule (default) tells the scheduler not to schedule
4253+
it. - ScheduleAnyway tells the scheduler to schedule the
4254+
pod in any location, but giving higher precedence to topologies
4255+
that would help reduce the skew. A constraint is considered
4256+
"Unsatisfiable" for an incoming pod if and only if every
4257+
possible node assignment for that pod would violate "MaxSkew"
4258+
on some topology. For example, in a 3-zone cluster, MaxSkew
4259+
is set to 1, and pods with the same labelSelector spread
4260+
as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P |
4261+
If WhenUnsatisfiable is set to DoNotSchedule, incoming
4262+
pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2)
4263+
as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1).
4264+
In other words, the cluster can still be imbalanced, but
4265+
scheduler won''t make it *more* imbalanced. It''s a required
4266+
field.'
4267+
type: string
4268+
required:
4269+
- maxSkew
4270+
- topologyKey
4271+
- whenUnsatisfiable
4272+
type: object
4273+
type: array
41364274
type: object
41374275
ports:
41384276
items:

charts/zookeeper/templates/zookeeper.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ spec:
7676
{{- if .Values.pod.affinity }}
7777
affinity:
7878
{{ toYaml .Values.pod.affinity | indent 6 }}
79+
{{- end }}
80+
{{- if .Values.pod.topologySpreadConstraints }}
81+
topologySpreadConstraints:
82+
{{ toYaml .Values.pod.topologySpreadConstraints | indent 6 }}
7983
{{- end }}
8084
{{- if .Values.pod.resources }}
8185
resources:

charts/zookeeper/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pod:
3636
# labels: {}
3737
# nodeSelector: {}
3838
# affinity: {}
39+
# topologySpreadConstraints: {}
3940
# resources: {}
4041
# tolerations: []
4142
# env: []

0 commit comments

Comments
 (0)