Skip to content

Commit 0e79a30

Browse files
authored
[Feature] ArangoMember Removal Priority (#1409)
1 parent 5bdd168 commit 0e79a30

15 files changed

+429
-82
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- (Bugfix) Use ArangoMember as owner reference for syncmaster secrets instead of Deployment
2020
- (Improvement) Remove PodSchedulingFailure condition instead of setting to false, restart pod if it could not be scheduled
2121
- (Feature) Add ArangoMember overrides
22+
- (Feature) ArangoMember Removal Priority
2223

2324
## [1.2.32](https://github.com/arangodb/kube-arangodb/tree/1.2.32) (2023-08-07)
2425
- (Feature) Backup lifetime - remove Backup once its lifetime has been reached

pkg/apis/deployment/v1/arango_member_spec.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ package v1
2222

2323
import (
2424
"k8s.io/apimachinery/pkg/types"
25+
26+
"github.com/arangodb/kube-arangodb/pkg/util"
2527
)
2628

2729
type ArangoMemberSpec struct {
@@ -38,4 +40,14 @@ type ArangoMemberSpec struct {
3840

3941
// Template keeps template which is gonna be applied on the Pod.
4042
Template *ArangoMemberPodTemplate `json:"template,omitempty"`
43+
44+
DeletionPriority *int `json:"deletion_priority,omitempty"`
45+
}
46+
47+
func (a *ArangoMemberSpec) GetDeletionPriority() int {
48+
if a == nil {
49+
return 0
50+
}
51+
52+
return util.TypeOrDefault[int](a.DeletionPriority, 0)
4153
}

pkg/apis/deployment/v1/topology_status.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -140,6 +140,14 @@ func (t *TopologyStatus) IsTopologyEvenlyDistributed(group ServerGroup) bool {
140140
return min+1 >= max
141141
}
142142

143+
func (t *TopologyStatus) GetID() types.UID {
144+
if t == nil {
145+
return ""
146+
}
147+
148+
return t.ID
149+
}
150+
143151
func (t *TopologyStatus) Enabled() bool {
144152
return t != nil
145153
}

pkg/apis/deployment/v1/zz_generated.deepcopy.go

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

pkg/apis/deployment/v2alpha1/actions.generated.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ const (
374374
// ActionTypeJWTStatusUpdate in scopes Normal. Update status of JWT propagation
375375
ActionTypeJWTStatusUpdate ActionType = "JWTStatusUpdate"
376376

377-
// ActionTypeKillMemberPod in scopes Normal. Execute Delete on Pod (put pod in Terminating state)
377+
// ActionTypeKillMemberPod in scopes High and Normal. Execute Delete on Pod (put pod in Terminating state)
378378
ActionTypeKillMemberPod ActionType = "KillMemberPod"
379379

380380
// ActionTypeLicenseSet in scopes Normal. Update Cluster license (3.9+)
@@ -776,7 +776,7 @@ func (a ActionType) Priority() ActionPriority {
776776
case ActionTypeJWTStatusUpdate:
777777
return ActionPriorityNormal
778778
case ActionTypeKillMemberPod:
779-
return ActionPriorityNormal
779+
return ActionPriorityHigh
780780
case ActionTypeLicenseSet:
781781
return ActionPriorityNormal
782782
case ActionTypeMarkToRemoveMember:

pkg/apis/deployment/v2alpha1/arango_member_spec.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ package v2alpha1
2222

2323
import (
2424
"k8s.io/apimachinery/pkg/types"
25+
26+
"github.com/arangodb/kube-arangodb/pkg/util"
2527
)
2628

2729
type ArangoMemberSpec struct {
@@ -38,4 +40,14 @@ type ArangoMemberSpec struct {
3840

3941
// Template keeps template which is gonna be applied on the Pod.
4042
Template *ArangoMemberPodTemplate `json:"template,omitempty"`
43+
44+
DeletionPriority *int `json:"deletion_priority,omitempty"`
45+
}
46+
47+
func (a *ArangoMemberSpec) GetDeletionPriority() int {
48+
if a == nil {
49+
return 0
50+
}
51+
52+
return util.TypeOrDefault[int](a.DeletionPriority, 0)
4153
}

pkg/apis/deployment/v2alpha1/topology_status.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -140,6 +140,14 @@ func (t *TopologyStatus) IsTopologyEvenlyDistributed(group ServerGroup) bool {
140140
return min+1 >= max
141141
}
142142

143+
func (t *TopologyStatus) GetID() types.UID {
144+
if t == nil {
145+
return ""
146+
}
147+
148+
return t.ID
149+
}
150+
143151
func (t *TopologyStatus) Enabled() bool {
144152
return t != nil
145153
}

pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go

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

pkg/deployment/reconcile/plan_builder_scale.go

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ import (
2626
"github.com/arangodb/kube-arangodb/pkg/apis/deployment"
2727
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
2828
"github.com/arangodb/kube-arangodb/pkg/deployment/actions"
29-
"github.com/arangodb/kube-arangodb/pkg/deployment/agency/state"
3029
"github.com/arangodb/kube-arangodb/pkg/deployment/reconcile/shared"
31-
"github.com/arangodb/kube-arangodb/pkg/deployment/reconciler"
3230
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3331
)
3432

@@ -94,12 +92,7 @@ func (r *Reconciler) createScalePlan(status api.DeploymentStatus, members api.Me
9492
} else if len(members) > count {
9593
// Note, we scale down 1 member at a time
9694

97-
if m, err := members.SelectMemberToRemove(
98-
getCleanedServer(context),
99-
getToBeCleanedServer(context),
100-
topologyMissingMemberToRemoveSelector(status.Topology),
101-
topologyAwarenessMemberToRemoveSelector(group, status.Topology),
102-
getDbServerWithLowestShards(context, group)); err != nil {
95+
if m, err := planBuilderScaleDownFilter(context, status, group, members); err != nil {
10396
r.planLogger.Err(err).Str("role", group.AsRole()).Warn("Failed to select member to remove")
10497
} else {
10598
ready, message := groupReadyForRestart(context, status, m, group)
@@ -174,68 +167,6 @@ func filterScaleUP(a api.Action) bool {
174167
return a.Type == api.ActionTypeAddMember
175168
}
176169

177-
func getCleanedServer(ctx reconciler.ArangoAgencyGet) api.MemberToRemoveSelector {
178-
return func(m api.MemberStatusList) (string, error) {
179-
if a, ok := ctx.GetAgencyCache(); ok {
180-
for _, member := range m {
181-
if a.Target.CleanedServers.Contains(state.Server(member.ID)) {
182-
return member.ID, nil
183-
}
184-
}
185-
}
186-
return "", nil
187-
}
188-
}
189-
190-
func getToBeCleanedServer(ctx reconciler.ArangoAgencyGet) api.MemberToRemoveSelector {
191-
return func(m api.MemberStatusList) (string, error) {
192-
if a, ok := ctx.GetAgencyCache(); ok {
193-
for _, member := range m {
194-
if a.Target.ToBeCleanedServers.Contains(state.Server(member.ID)) {
195-
return member.ID, nil
196-
}
197-
}
198-
}
199-
return "", nil
200-
}
201-
}
202-
203-
func getDbServerWithLowestShards(ctx reconciler.ArangoAgencyGet, g api.ServerGroup) api.MemberToRemoveSelector {
204-
return func(m api.MemberStatusList) (string, error) {
205-
if g != api.ServerGroupDBServers {
206-
return "", nil
207-
}
208-
209-
a, ok := ctx.GetAgencyCache()
210-
if !ok {
211-
return "", nil
212-
}
213-
214-
dbServersShards := a.ShardsByDBServers()
215-
for _, member := range m {
216-
if _, ok := dbServersShards[state.Server(member.ID)]; !ok {
217-
// member is not in agency cache, so it has no shards
218-
return member.ID, nil
219-
}
220-
}
221-
222-
var resultServer state.Server = ""
223-
var resultShards int
224-
225-
for server, shards := range dbServersShards {
226-
// init first server as result
227-
if resultServer == "" {
228-
resultServer = server
229-
resultShards = shards
230-
} else if shards < resultShards {
231-
resultServer = server
232-
resultShards = shards
233-
}
234-
}
235-
return string(resultServer), nil
236-
}
237-
}
238-
239170
func (r *Reconciler) scaleDownCandidate(ctx context.Context, apiObject k8sutil.APIObject,
240171
spec api.DeploymentSpec, status api.DeploymentStatus,
241172
context PlanBuilderContext) api.Plan {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
//go:build !enterprise
22+
23+
package reconcile
24+
25+
import api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
26+
27+
func planBuilderScaleDownTopologyMissing(context PlanBuilderContext, status api.DeploymentStatus, group api.ServerGroup, in api.MemberStatusList) (api.MemberStatus, bool, error) {
28+
return api.MemberStatus{}, false, nil
29+
}
30+
31+
func planBuilderScaleDownTopologyAwarenessMember(context PlanBuilderContext, status api.DeploymentStatus, group api.ServerGroup, in api.MemberStatusList) (api.MemberStatus, bool, error) {
32+
return api.MemberStatus{}, false, nil
33+
}

0 commit comments

Comments
 (0)