Skip to content

Commit

Permalink
K8SPSMDB-227: Add topologySpreadConstraints (#1280)
Browse files Browse the repository at this point in the history
* K8SPSMDB-227: Add `topologySpreadConstraints`

https://jira.percona.com/browse/K8SPSMDB-227

* fix tests

* fix defaults

* fix `upgrade-consistency` test

* update `cr.yaml`

* Revert "fix tests"

This reverts commit 6796ce7.

* don't add topologySpreadConstraints by default

* fix `TestSetSafeDefault`

---------

Co-authored-by: Inel Pandzic <[email protected]>
  • Loading branch information
pooknull and inelpandzic authored Sep 1, 2023
1 parent 06ffb2d commit ef110e3
Show file tree
Hide file tree
Showing 12 changed files with 1,903 additions and 17 deletions.
364 changes: 364 additions & 0 deletions config/crd/bases/psmdb.percona.com_perconaservermongodbs.yaml

Large diffs are not rendered by default.

364 changes: 364 additions & 0 deletions deploy/bundle.yaml

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions deploy/cr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ spec:
- name: rs0
size: 3
# terminationGracePeriodSeconds: 300
# topologySpreadConstraints:
# - labelSelector:
# matchLabels:
# app.kubernetes.io/name: percona-server-mongodb
# maxSkew: 1
# topologyKey: kubernetes.io/hostname
# whenUnsatisfiable: DoNotSchedule
# externalNodes:
# - host: 34.124.76.90
# - host: 34.124.76.91
Expand Down Expand Up @@ -310,6 +317,13 @@ spec:
configsvrReplSet:
size: 3
# terminationGracePeriodSeconds: 300
# topologySpreadConstraints:
# - labelSelector:
# matchLabels:
# app.kubernetes.io/name: percona-server-mongodb
# maxSkew: 1
# topologyKey: kubernetes.io/hostname
# whenUnsatisfiable: DoNotSchedule
# externalNodes:
# - host: 34.124.76.93
# - host: 34.124.76.94
Expand Down Expand Up @@ -407,6 +421,13 @@ spec:
mongos:
size: 3
# terminationGracePeriodSeconds: 300
# topologySpreadConstraints:
# - labelSelector:
# matchLabels:
# app.kubernetes.io/name: percona-server-mongodb
# maxSkew: 1
# topologyKey: kubernetes.io/hostname
# whenUnsatisfiable: DoNotSchedule
# # for more configuration fields refer to https://docs.mongodb.com/manual/reference/configuration-options/
# configuration: |
# systemLog:
Expand Down
364 changes: 364 additions & 0 deletions deploy/crd.yaml

Large diffs are not rendered by default.

364 changes: 364 additions & 0 deletions deploy/cw-bundle.yaml

Large diffs are not rendered by default.

364 changes: 364 additions & 0 deletions e2e-tests/version-service/conf/crd.yaml

Large diffs are not rendered by default.

29 changes: 24 additions & 5 deletions pkg/apis/psmdb/v1/psmdb_defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func (cr *PerconaServerMongoDB) CheckNSetDefaults(platform version.Platform, log
cr.Spec.Sharding.Mongos.ReadinessProbe.FailureThreshold = 3
}

cr.Spec.Sharding.Mongos.reconcileOpts()
cr.Spec.Sharding.Mongos.reconcileOpts(cr)

if err := cr.Spec.Sharding.Mongos.Configuration.SetDefaults(); err != nil {
return errors.Wrap(err, "failed to set configuration defaults")
Expand Down Expand Up @@ -558,10 +558,10 @@ func (rs *ReplsetSpec) SetDefaults(platform version.Platform, cr *PerconaServerM
rs.Expose.ExposeType = corev1.ServiceTypeClusterIP
}

rs.MultiAZ.reconcileOpts()
rs.MultiAZ.reconcileOpts(cr)

if rs.Arbiter.Enabled {
rs.Arbiter.MultiAZ.reconcileOpts()
rs.Arbiter.MultiAZ.reconcileOpts(cr)
}

if !cr.Spec.UnsafeConf && cr.DeletionTimestamp == nil {
Expand Down Expand Up @@ -694,7 +694,7 @@ func (nv *NonVotingSpec) SetDefaults(cr *PerconaServerMongoDB, rs *ReplsetSpec)
nv.ServiceAccountName = WorkloadSA
}

nv.MultiAZ.reconcileOpts()
nv.MultiAZ.reconcileOpts(cr)

if nv.ContainerSecurityContext == nil {
nv.ContainerSecurityContext = rs.ContainerSecurityContext
Expand Down Expand Up @@ -741,8 +741,9 @@ func (rs *ReplsetSpec) setSafeDefaults(log logr.Logger) {
}
}

func (m *MultiAZ) reconcileOpts() {
func (m *MultiAZ) reconcileOpts(cr *PerconaServerMongoDB) {
m.reconcileAffinityOpts()
m.reconcileTopologySpreadConstraints(cr)

if m.PodDisruptionBudget == nil {
defaultMaxUnavailable := intstr.FromInt(1)
Expand Down Expand Up @@ -786,6 +787,24 @@ func (m *MultiAZ) reconcileAffinityOpts() {
}
}

func (m *MultiAZ) reconcileTopologySpreadConstraints(cr *PerconaServerMongoDB) {
if cr.CompareVersion("1.15.0") < 0 {
return
}

for i := range m.TopologySpreadConstraints {
if m.TopologySpreadConstraints[i].MaxSkew == 0 {
m.TopologySpreadConstraints[i].MaxSkew = 1
}
if m.TopologySpreadConstraints[i].TopologyKey == "" {
m.TopologySpreadConstraints[i].TopologyKey = defaultAffinityTopologyKey
}
if m.TopologySpreadConstraints[i].WhenUnsatisfiable == "" {
m.TopologySpreadConstraints[i].WhenUnsatisfiable = corev1.DoNotSchedule
}
}
}

func (v *VolumeSpec) reconcileOpts() error {
if v.EmptyDir == nil && v.HostPath == nil && v.PersistentVolumeClaim.PersistentVolumeClaimSpec == nil {
v.PersistentVolumeClaim.PersistentVolumeClaimSpec = &corev1.PersistentVolumeClaimSpec{}
Expand Down
5 changes: 3 additions & 2 deletions pkg/apis/psmdb/v1/psmdb_defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,9 @@ func TestSetSafeDefault(t *testing.T) {
cr := &api.PerconaServerMongoDB{
ObjectMeta: metav1.ObjectMeta{Name: "psmdb-mock", Namespace: "psmdb"},
Spec: api.PerconaServerMongoDBSpec{
Replsets: []*api.ReplsetSpec{{Name: "rs0", Size: 3}, {Name: "rs1", Size: 3}},
Sharding: api.Sharding{Enabled: true, Mongos: &api.MongosSpec{Size: 3}},
CRVersion: version.Version,
Replsets: []*api.ReplsetSpec{{Name: "rs0", Size: 3}, {Name: "rs1", Size: 3}},
Sharding: api.Sharding{Enabled: true, Mongos: &api.MongosSpec{Size: 3}},
},
}

Expand Down
21 changes: 11 additions & 10 deletions pkg/apis/psmdb/v1/psmdb_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,17 @@ func (spec *PMMSpec) ShouldUseAPIKeyAuth(secret *corev1.Secret) bool {
}

type MultiAZ struct {
Affinity *PodAffinity `json:"affinity,omitempty"`
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
PriorityClassName string `json:"priorityClassName,omitempty"`
ServiceAccountName string `json:"serviceAccountName,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
PodDisruptionBudget *PodDisruptionBudgetSpec `json:"podDisruptionBudget,omitempty"`
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
RuntimeClassName *string `json:"runtimeClassName,omitempty"`
Affinity *PodAffinity `json:"affinity,omitempty"`
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
PriorityClassName string `json:"priorityClassName,omitempty"`
ServiceAccountName string `json:"serviceAccountName,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
PodDisruptionBudget *PodDisruptionBudgetSpec `json:"podDisruptionBudget,omitempty"`
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
RuntimeClassName *string `json:"runtimeClassName,omitempty"`

Resources corev1.ResourceRequirements `json:"resources,omitempty"`

Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/psmdb/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/psmdb/mongos.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func MongosTemplateSpec(cr *api.PerconaServerMongoDB, initImage string, log logr
HostAliases: cr.Spec.Sharding.Mongos.HostAliases,
SecurityContext: cr.Spec.Sharding.Mongos.PodSecurityContext,
Affinity: PodAffinity(cr, cr.Spec.Sharding.Mongos.MultiAZ.Affinity, ls),
TopologySpreadConstraints: PodTopologySpreadConstraints(cr, cr.Spec.Sharding.Mongos.MultiAZ.TopologySpreadConstraints, ls),
NodeSelector: cr.Spec.Sharding.Mongos.MultiAZ.NodeSelector,
Tolerations: cr.Spec.Sharding.Mongos.MultiAZ.Tolerations,
TerminationGracePeriodSeconds: cr.Spec.Sharding.Mongos.MultiAZ.TerminationGracePeriodSeconds,
Expand Down
16 changes: 16 additions & 0 deletions pkg/psmdb/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ func StatefulSpec(ctx context.Context, cr *api.PerconaServerMongoDB, replset *ap
HostAliases: replset.HostAliases,
SecurityContext: podSecurityContext,
Affinity: PodAffinity(cr, multiAZ.Affinity, customLabels),
TopologySpreadConstraints: PodTopologySpreadConstraints(cr, multiAZ.TopologySpreadConstraints, customLabels),
NodeSelector: multiAZ.NodeSelector,
Tolerations: multiAZ.Tolerations,
TerminationGracePeriodSeconds: multiAZ.TerminationGracePeriodSeconds,
Expand Down Expand Up @@ -228,6 +229,21 @@ func PodAffinity(cr *api.PerconaServerMongoDB, af *api.PodAffinity, labels map[s
return nil
}

func PodTopologySpreadConstraints(cr *api.PerconaServerMongoDB, tscs []corev1.TopologySpreadConstraint, ls map[string]string) []corev1.TopologySpreadConstraint {
result := make([]corev1.TopologySpreadConstraint, 0, len(tscs))

for _, tsc := range tscs {
if tsc.LabelSelector == nil && tsc.MatchLabelKeys == nil {
tsc.LabelSelector = &metav1.LabelSelector{
MatchLabels: ls,
}
}

result = append(result, tsc)
}
return result
}

func isEncryptionEnabled(cr *api.PerconaServerMongoDB, replset *api.ReplsetSpec) (bool, error) {
enabled, err := replset.Configuration.IsEncryptionEnabled()
if err != nil {
Expand Down

0 comments on commit ef110e3

Please sign in to comment.