Skip to content

Commit c829a71

Browse files
authored
Feature/new resize mode (#524)
1 parent 43135df commit c829a71

19 files changed

+681
-69
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
4+
- Add new VolumeResize mode to be compatible with Azure flow
5+
- Allow to customize probe configuration options
6+
- Add new upgrade flag for ArangoDB 3.6.0<=
7+
38
## [0.4.3](https://github.com/arangodb/kube-arangodb/tree/0.4.3) (2020-01-31)
49
- Prevent DBServer deletion if there are any shards active on it
510
- Add Maintenance mode annotation for ArangoDeployment

Dockerfile.ubi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ARG IMAGE=registry.access.redhat.com/ubi8/ubi-minimal:8.0
2+
FROM ${IMAGE}
3+
4+
RUN microdnf update && microdnf clean all

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,15 @@ $(BIN): $(SOURCES) dashboard/assets.go VERSION
221221

222222
.PHONY: docker
223223
docker: check-vars $(BIN)
224-
docker build -f $(DOCKERFILE) --build-arg "VERSION=${VERSION_MAJOR_MINOR_PATCH}" -t $(OPERATORIMAGE) .
224+
docker build --no-cache -f $(DOCKERFILE) --build-arg "VERSION=${VERSION_MAJOR_MINOR_PATCH}" -t $(OPERATORIMAGE) .
225225
ifdef PUSHIMAGES
226226
docker push $(OPERATORIMAGE)
227227
endif
228228

229229
.PHONY: docker-ubi
230230
docker-ubi: check-vars $(BIN)
231-
docker build -f $(DOCKERFILE) --build-arg "VERSION=${VERSION_MAJOR_MINOR_PATCH}" --build-arg "IMAGE=$(BASEUBIIMAGE)" -t $(OPERATORUBIIMAGE) .
231+
docker build --no-cache -f "$(DOCKERFILE).ubi" --build-arg "VERSION=${VERSION_MAJOR_MINOR_PATCH}" --build-arg "IMAGE=$(BASEUBIIMAGE)" -t $(OPERATORUBIIMAGE)-local-only-build .
232+
docker build --no-cache -f $(DOCKERFILE) --build-arg "VERSION=${VERSION_MAJOR_MINOR_PATCH}" --build-arg "IMAGE=$(OPERATORUBIIMAGE)-local-only-build" -t $(OPERATORUBIIMAGE) .
232233
ifdef PUSHIMAGES
233234
docker push $(OPERATORUBIIMAGE)
234235
endif

chart/kube-arangodb/templates/deployment-operator/cluster-role.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rules:
1717
resources: ["customresourcedefinitions"]
1818
verbs: ["get", "list", "watch"]
1919
- apiGroups: [""]
20-
resources: ["namespaces", "nodes"]
20+
resources: ["namespaces", "nodes", "persistentvolumes"]
2121
verbs: ["get", "list"]
2222
- apiGroups: ["storage.k8s.io"]
2323
resources: ["storageclasses"]

pkg/apis/deployment/v1/plan.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ const (
4444
ActionTypeShutdownMember ActionType = "ShutdownMember"
4545
// ActionTypeRotateMember causes a member to be shutdown and have it's pod removed.
4646
ActionTypeRotateMember ActionType = "RotateMember"
47+
// ActionTypeRotateStartMember causes a member to be shutdown and have it's pod removed. Do not wait to pod recover.
48+
ActionTypeRotateStartMember ActionType = "RotateStartMember"
49+
// ActionTypeRotateMember causes a member to be restored.
50+
ActionTypeRotateStopMember ActionType = "RotateStopMember"
4751
// ActionTypeUpgradeMember causes a member to be shutdown and have it's pod removed, restarted with AutoUpgrade option, waited until termination and the restarted again.
4852
ActionTypeUpgradeMember ActionType = "UpgradeMember"
4953
// ActionTypeWaitForMemberUp causes the plan to wait until the member is considered "up".
@@ -58,6 +62,10 @@ const (
5862
ActionTypeDisableClusterScaling ActionType = "ScalingDisabled"
5963
// ActionTypeEnableClusterScaling turns on scaling DBservers and coordinators
6064
ActionTypeEnableClusterScaling ActionType = "ScalingEnabled"
65+
// ActionTypePVCResize resize event for PVC
66+
ActionTypePVCResize ActionType = "PVCResize"
67+
// ActionTypePVCResized waits for PVC to resize for defined time
68+
ActionTypePVCResized ActionType = "PVCResized"
6169
)
6270

6371
const (

pkg/apis/deployment/v1/pvc.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 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+
// Author Adam Janikowski
21+
//
22+
23+
package v1
24+
25+
type PVCResizeMode string
26+
27+
const (
28+
PVCResizeModeRuntime PVCResizeMode = "runtime"
29+
PVCResizeModeRotate PVCResizeMode = "rotate"
30+
)
31+
32+
func (p *PVCResizeMode) Get() PVCResizeMode {
33+
if p == nil {
34+
return PVCResizeModeRuntime
35+
}
36+
37+
return *p
38+
}
39+
40+
func (p PVCResizeMode) String() string {
41+
return string(p)
42+
}

pkg/apis/deployment/v1/server_group_spec.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ type ServerGroupSpec struct {
6464
PriorityClassName string `json:"priorityClassName,omitempty"`
6565
// VolumeClaimTemplate specifies a template for volume claims
6666
VolumeClaimTemplate *v1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"`
67+
// VolumeResizeMode specified resize mode for pvc
68+
VolumeResizeMode *PVCResizeMode `json:"pvcResizeMode,omitempty"`
6769
// Sidecars specifies a list of additional containers to be started
6870
Sidecars []v1.Container `json:"sidecars,omitempty"`
6971
}

pkg/deployment/context_impl.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ package deployment
2525
import (
2626
"context"
2727
"fmt"
28+
"k8s.io/apimachinery/pkg/api/errors"
2829
"net"
2930
"strconv"
3031

@@ -309,6 +310,31 @@ func (d *Deployment) DeletePvc(pvcName string) error {
309310
return nil
310311
}
311312

313+
// UpdatePvc updated a persistent volume claim in the namespace
314+
// of the deployment. If the pvc does not exist, the error is ignored.
315+
func (d *Deployment) UpdatePvc(pvc *v1.PersistentVolumeClaim) error {
316+
_, err := d.GetKubeCli().CoreV1().PersistentVolumeClaims(d.GetNamespace()).Update(pvc)
317+
if err == nil {
318+
return nil
319+
}
320+
321+
if errors.IsNotFound(err) {
322+
return nil
323+
}
324+
325+
return maskAny(err)
326+
}
327+
328+
// GetPv returns PV info about PV with given name.
329+
func (d *Deployment) GetPv(pvName string) (*v1.PersistentVolume, error) {
330+
pv, err := d.GetKubeCli().CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{})
331+
if err == nil {
332+
return pv, nil
333+
}
334+
335+
return nil, maskAny(err)
336+
}
337+
312338
// GetOwnedPods returns a list of all pods owned by the deployment.
313339
func (d *Deployment) GetOwnedPods() ([]v1.Pod, error) {
314340
// Get all current pods

pkg/deployment/reconcile/action_context.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ package reconcile
2525
import (
2626
"context"
2727
"fmt"
28-
v1 "k8s.io/api/core/v1"
29-
3028
"github.com/arangodb/go-driver/agency"
29+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
30+
v1 "k8s.io/api/core/v1"
3131

3232
"github.com/arangodb/arangosync-client/client"
3333
driver "github.com/arangodb/go-driver"
@@ -40,6 +40,8 @@ import (
4040
// ActionContext provides methods to the Action implementations
4141
// to control their context.
4242
type ActionContext interface {
43+
// GetAPIObject returns the deployment as k8s object.
44+
GetAPIObject() k8sutil.APIObject
4345
// Gets the specified mode of deployment
4446
GetMode() api.DeploymentMode
4547
// GetDatabaseClient returns a cached client for the entire database (cluster coordinators or single server),
@@ -53,6 +55,9 @@ type ActionContext interface {
5355
GetAgency(ctx context.Context) (agency.Agency, error)
5456
// GetSyncServerClient returns a cached client for a specific arangosync server.
5557
GetSyncServerClient(ctx context.Context, group api.ServerGroup, id string) (client.API, error)
58+
// CreateEvent creates a given event.
59+
// On error, the error is logged.
60+
CreateEvent(evt *k8sutil.Event)
5661
// GetMemberStatusByID returns the current member status
5762
// for the member with given id.
5863
// Returns member status, true when found, or false
@@ -74,6 +79,11 @@ type ActionContext interface {
7479
// GetPvc returns PVC info about PVC with given name in the namespace
7580
// of the deployment.
7681
GetPvc(pvcName string) (*v1.PersistentVolumeClaim, error)
82+
// GetPv returns PV info about PV with given name.
83+
GetPv(pvName string) (*v1.PersistentVolume, error)
84+
// UpdatePvc update PVC with given name in the namespace
85+
// of the deployment.
86+
UpdatePvc(pvc *v1.PersistentVolumeClaim) error
7787
// RemovePodFinalizers removes all the finalizers from the Pod with given name in the namespace
7888
// of the deployment. If the pod does not exist, the error is ignored.
7989
RemovePodFinalizers(podName string) error
@@ -103,7 +113,7 @@ type ActionContext interface {
103113
// newActionContext creates a new ActionContext implementation.
104114
func newActionContext(log zerolog.Logger, context Context) ActionContext {
105115
return &actionContext{
106-
log: log,
116+
log: log,
107117
context: context,
108118
}
109119
}
@@ -114,6 +124,22 @@ type actionContext struct {
114124
context Context
115125
}
116126

127+
func (ac *actionContext) GetPv(pvName string) (*v1.PersistentVolume, error) {
128+
return ac.context.GetPv(pvName)
129+
}
130+
131+
func (ac *actionContext) GetAPIObject() k8sutil.APIObject {
132+
return ac.context.GetAPIObject()
133+
}
134+
135+
func (ac *actionContext) UpdatePvc(pvc *v1.PersistentVolumeClaim) error {
136+
return ac.context.UpdatePvc(pvc)
137+
}
138+
139+
func (ac *actionContext) CreateEvent(evt *k8sutil.Event) {
140+
ac.context.CreateEvent(evt)
141+
}
142+
117143
func (ac *actionContext) GetPvc(pvcName string) (*v1.PersistentVolumeClaim, error) {
118144
return ac.context.GetPvc(pvcName)
119145
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 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+
// Author Ewout Prangsma
21+
//
22+
23+
package reconcile
24+
25+
import (
26+
"context"
27+
"time"
28+
29+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
30+
core "k8s.io/api/core/v1"
31+
"k8s.io/apimachinery/pkg/api/errors"
32+
33+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
34+
"github.com/rs/zerolog"
35+
)
36+
37+
// NewRotateMemberAction creates a new Action that implements the given
38+
// planned RotateMember action.
39+
func NewPVCResizeAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
40+
return &actionPVCResize{
41+
log: log,
42+
action: action,
43+
actionCtx: actionCtx,
44+
}
45+
}
46+
47+
// actionRotateMember implements an RotateMember.
48+
type actionPVCResize struct {
49+
log zerolog.Logger
50+
action api.Action
51+
actionCtx ActionContext
52+
}
53+
54+
// Start performs the start of the action.
55+
// Returns true if the action is completely finished, false in case
56+
// the start time needs to be recorded and a ready condition needs to be checked.
57+
func (a *actionPVCResize) Start(ctx context.Context) (bool, error) {
58+
log := a.log
59+
group := a.action.Group
60+
groupSpec := a.actionCtx.GetSpec().GetServerGroupSpec(group)
61+
m, ok := a.actionCtx.GetMemberStatusByID(a.action.MemberID)
62+
if !ok {
63+
log.Error().Msg("No such member")
64+
return true, nil
65+
}
66+
67+
if m.PersistentVolumeClaimName == "" {
68+
// Nothing to do, PVC is empty
69+
return true, nil
70+
}
71+
72+
pvc, err := a.actionCtx.GetPvc(m.PersistentVolumeClaimName)
73+
if err != nil {
74+
if errors.IsNotFound(err) {
75+
return true, nil
76+
}
77+
78+
return false, err
79+
}
80+
81+
var res core.ResourceList
82+
if groupSpec.HasVolumeClaimTemplate() {
83+
res = groupSpec.GetVolumeClaimTemplate().Spec.Resources.Requests
84+
} else {
85+
res = groupSpec.Resources.Requests
86+
}
87+
88+
if requestedSize, ok := res[core.ResourceStorage]; ok {
89+
if volumeSize, ok := pvc.Spec.Resources.Requests[core.ResourceStorage]; ok {
90+
cmp := volumeSize.Cmp(requestedSize)
91+
if cmp < 0 {
92+
pvc.Spec.Resources.Requests[core.ResourceStorage] = requestedSize
93+
if err := a.actionCtx.UpdatePvc(pvc); err != nil {
94+
return false, err
95+
}
96+
97+
return false, nil
98+
} else if cmp > 0 {
99+
log.Error().Str("server-group", group.AsRole()).Str("pvc-storage-size", volumeSize.String()).Str("requested-size", requestedSize.String()).
100+
Msg("Volume size should not shrink")
101+
a.actionCtx.CreateEvent(k8sutil.NewCannotShrinkVolumeEvent(a.actionCtx.GetAPIObject(), pvc.Name))
102+
return false, nil
103+
}
104+
}
105+
}
106+
107+
return true, nil
108+
}
109+
110+
// CheckProgress checks the progress of the action.
111+
// Returns: ready, abort, error.
112+
func (a *actionPVCResize) CheckProgress(ctx context.Context) (bool, bool, error) {
113+
// Check that pod is removed
114+
log := a.log
115+
m, found := a.actionCtx.GetMemberStatusByID(a.action.MemberID)
116+
if !found {
117+
log.Error().Msg("No such member")
118+
return true, false, nil
119+
}
120+
121+
pvc, err := a.actionCtx.GetPvc(m.PersistentVolumeClaimName)
122+
if err != nil {
123+
if errors.IsNotFound(err) {
124+
return true, false, nil
125+
}
126+
127+
return false, true, err
128+
}
129+
130+
pv, err := a.actionCtx.GetPv(pvc.Spec.VolumeName)
131+
if err != nil {
132+
if errors.IsNotFound(err) {
133+
return true, false, nil
134+
}
135+
136+
return false, true, err
137+
}
138+
139+
if requestedSize, ok := pvc.Spec.Resources.Requests[core.ResourceStorage]; ok {
140+
if volumeSize, ok := pv.Spec.Capacity[core.ResourceStorage]; ok {
141+
cmp := volumeSize.Cmp(requestedSize)
142+
if cmp >= 0 {
143+
return true, false, nil
144+
}
145+
}
146+
}
147+
148+
return false, false, nil
149+
}
150+
151+
// Timeout returns the amount of time after which this action will timeout.
152+
func (a *actionPVCResize) Timeout() time.Duration {
153+
return pvcResizeTimeout
154+
}
155+
156+
// Return the MemberID used / created in this action
157+
func (a *actionPVCResize) MemberID() string {
158+
return a.action.MemberID
159+
}

0 commit comments

Comments
 (0)