Skip to content

Commit

Permalink
K8SPSMDB-1002: add crd preferer primary node
Browse files Browse the repository at this point in the history
Add crd parameter to prefer primary node in cluster.
  • Loading branch information
sergelogvinov committed Aug 27, 2024
1 parent c2b95d9 commit 46d7983
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 20 deletions.
8 changes: 8 additions & 0 deletions config/crd/bases/psmdb.percona.com_perconaservermongodbs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6206,6 +6206,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down Expand Up @@ -13792,6 +13796,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down
8 changes: 8 additions & 0 deletions deploy/bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,10 @@ spec:
- type: string
x-kubernetes-int-or-string: true
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
resources:
Expand Down Expand Up @@ -4868,6 +4872,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down
8 changes: 8 additions & 0 deletions deploy/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6879,6 +6879,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down Expand Up @@ -14465,6 +14469,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down
8 changes: 8 additions & 0 deletions deploy/cw-bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,10 @@ spec:
- type: string
x-kubernetes-int-or-string: true
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
resources:
Expand Down Expand Up @@ -4868,6 +4872,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down
8 changes: 8 additions & 0 deletions e2e-tests/version-service/conf/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6879,6 +6879,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down Expand Up @@ -14465,6 +14469,10 @@ spec:
type: string
type: object
type: object
primaryPreferTagSelector:
additionalProperties:
type: string
type: object
priorityClassName:
type: string
readinessProbe:
Expand Down
35 changes: 19 additions & 16 deletions pkg/apis/psmdb/v1/psmdb_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,25 +581,28 @@ func (conf *MongoConfiguration) SetDefaults() error {

type HorizonsSpec map[string]map[string]string

type PrimaryPreferTagSelectorSpec map[string]string

type ReplsetSpec struct {
MultiAZ `json:",inline"`

Name string `json:"name,omitempty"`
Size int32 `json:"size"`
ClusterRole ClusterRole `json:"clusterRole,omitempty"`
Arbiter Arbiter `json:"arbiter,omitempty"`
Expose ExposeTogglable `json:"expose,omitempty"`
VolumeSpec *VolumeSpec `json:"volumeSpec,omitempty"`
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`
LivenessProbe *LivenessProbeExtended `json:"livenessProbe,omitempty"`
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"`
Storage *MongodSpecStorage `json:"storage,omitempty"`
Configuration MongoConfiguration `json:"configuration,omitempty"`
ExternalNodes []*ExternalNode `json:"externalNodes,omitempty"`
NonVoting NonVotingSpec `json:"nonvoting,omitempty"`
HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"`
Horizons HorizonsSpec `json:"splitHorizons,omitempty"`
Name string `json:"name,omitempty"`
Size int32 `json:"size"`
ClusterRole ClusterRole `json:"clusterRole,omitempty"`
Arbiter Arbiter `json:"arbiter,omitempty"`
Expose ExposeTogglable `json:"expose,omitempty"`
VolumeSpec *VolumeSpec `json:"volumeSpec,omitempty"`
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`
LivenessProbe *LivenessProbeExtended `json:"livenessProbe,omitempty"`
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"`
Storage *MongodSpecStorage `json:"storage,omitempty"`
Configuration MongoConfiguration `json:"configuration,omitempty"`
ExternalNodes []*ExternalNode `json:"externalNodes,omitempty"`
NonVoting NonVotingSpec `json:"nonvoting,omitempty"`
HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"`
Horizons HorizonsSpec `json:"splitHorizons,omitempty"`
PrimaryPreferTagSelector PrimaryPreferTagSelectorSpec `json:"primaryPreferTagSelector,omitempty"`
}

func (r *ReplsetSpec) PodName(cr *PerconaServerMongoDB, idx int) string {
Expand Down
28 changes: 28 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.

19 changes: 18 additions & 1 deletion pkg/controller/perconaservermongodb/mgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ func (r *ReconcilePerconaServerMongoDB) updateConfigMembers(ctx context.Context,
Votes: mongo.DefaultVotes,
}

if compareTags(nodeLabels, rs.PrimaryPreferTagSelector) {
member.Priority = mongo.DefaultPriority + 1
}

if len(rs.Horizons) > 0 {
horizons := make(map[string]string)
for h, domain := range rs.Horizons[pod.Name] {
Expand Down Expand Up @@ -411,7 +415,7 @@ func (r *ReconcilePerconaServerMongoDB) updateConfigMembers(ctx context.Context,
}

currMembers := append(mongo.ConfigMembers(nil), cnf.Members...)
cnf.Members.SetVotes(unsafePSA)
cnf.Members.SetVotes(members, unsafePSA)
if !reflect.DeepEqual(currMembers, cnf.Members) {
cnf.Version++

Expand Down Expand Up @@ -726,6 +730,19 @@ func comparePrivileges(x []mongo.RolePrivilege, y []mongo.RolePrivilege) bool {
return true
}

func compareTags(tags mongo.ReplsetTags, selector api.PrimaryPreferTagSelectorSpec) bool {
if len(selector) == 0 {
return false
}
for tag, v := range selector {
if val, ok := tags[tag]; ok && val == v {
continue
}
return false
}
return true
}

func (r *ReconcilePerconaServerMongoDB) createOrUpdateSystemRoles(ctx context.Context, cli mongo.Client, role string, privileges []mongo.RolePrivilege) error {
roleInfo, err := cli.GetRole(ctx, role)
if err != nil {
Expand Down
58 changes: 58 additions & 0 deletions pkg/controller/perconaservermongodb/mgo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package perconaservermongodb

import (
"testing"

api "github.com/percona/percona-server-mongodb-operator/pkg/apis/psmdb/v1"
"github.com/percona/percona-server-mongodb-operator/pkg/psmdb/mongo"
)

func TestCompareTags(t *testing.T) {
t.Parallel()

tests := []struct {
name string
mongoTags mongo.ReplsetTags
selectorTags api.PrimaryPreferTagSelectorSpec
expected bool
}{
{
name: "empty tags",
mongoTags: mongo.ReplsetTags{},
selectorTags: api.PrimaryPreferTagSelectorSpec{},
expected: false,
},
{
name: "selector with podName",
mongoTags: mongo.ReplsetTags{},
selectorTags: api.PrimaryPreferTagSelectorSpec{"podName": "test"},
expected: false,
},
{
name: "match selector with podName",
mongoTags: mongo.ReplsetTags{"podName": "test"},
selectorTags: api.PrimaryPreferTagSelectorSpec{"podName": "test"},
expected: true,
},
{
name: "match selector with podName and other tags",
mongoTags: mongo.ReplsetTags{"podName": "test", "other": "tag"},
selectorTags: api.PrimaryPreferTagSelectorSpec{"podName": "test"},
expected: true,
},
{
name: "match two selectors with podName and other tags",
mongoTags: mongo.ReplsetTags{"podName": "test", "other": "tag"},
selectorTags: api.PrimaryPreferTagSelectorSpec{"podName": "test", "other": "tag"},
expected: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := compareTags(tt.mongoTags, tt.selectorTags); got != tt.expected {
t.Errorf("compareTags() = %v, want %v", got, tt.expected)
}
})
}
}
20 changes: 18 additions & 2 deletions pkg/psmdb/mongo/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,9 +791,20 @@ func (m *ConfigMembers) AddNew(from ConfigMembers) bool {
}

// SetVotes sets voting parameters for members list
func (m *ConfigMembers) SetVotes(unsafePSA bool) {
func (m *ConfigMembers) SetVotes(compareWith ConfigMembers, unsafePSA bool) {
votes := 0
lastVoteIdx := -1

cm := make(map[string]int, len(compareWith))

for _, member := range compareWith {
if member.ArbiterOnly {
continue
}

cm[member.Host] = member.Priority
}

for i, member := range *m {
if member.Hidden {
continue
Expand Down Expand Up @@ -834,7 +845,12 @@ func (m *ConfigMembers) SetVotes(unsafePSA bool) {
// In unsafe PSA (Primary with a Secondary and an Arbiter),
// we are unable to set the votes and the priority simultaneously.
// Therefore, setting only the votes.
[]ConfigMember(*m)[i].Priority = DefaultPriority
priority := DefaultPriority
if c, ok := cm[member.Host]; ok && c > 0 {
priority = c
}

[]ConfigMember(*m)[i].Priority = priority
}
}
} else if member.ArbiterOnly {
Expand Down
2 changes: 1 addition & 1 deletion pkg/psmdb/mongo/mongo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ func TestVoting(t *testing.T) {
}

for _, c := range cases {
c.mset.SetVotes(false)
c.mset.SetVotes(*c.mset, false)
if len(*c.mset) != len(*c.desiered) {
t.Errorf("%s: missmatched members size", c.name)
continue
Expand Down

0 comments on commit 46d7983

Please sign in to comment.