Skip to content

Commit 08ecc44

Browse files
kvahedneunhoef
authored andcommitted
Feature/restart pods on sidecar changes (#420)
* added side car changes to pod rotation * change log * go fmt * sidecar test
1 parent b192e7b commit 08ecc44

File tree

11 files changed

+569
-7
lines changed

11 files changed

+569
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Change Log
22

33
## [0.3.13]() (XXXX-XX-XX)
4+
- Added side car changed to pod rotation criterium
45
- Added ArangoDB version and image id to member status
56

67
## [0.3.12](https://github.com/arangodb/kube-arangodb/tree/0.3.12) (2019-07-04)

docs/Manual/Tutorials/Kubernetes/bare-metal.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ kubectl get all --all-namespaces
220220
- Attach `tiller` to proper role
221221

222222
```
223-
kubectl create clusterrolebinding tiller-cluster-rule \
223+
kubectl create clusterrolebinding tiller-cluster-rule \
224224
--clusterrole=cluster-admin --serviceaccount=kube-system:tiller
225225
```
226226
```

pkg/apis/deployment/v1alpha/deployment_status.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222

2323
package v1alpha
2424

25-
import "github.com/arangodb/kube-arangodb/pkg/util"
25+
import (
26+
"github.com/arangodb/kube-arangodb/pkg/util"
27+
)
2628

2729
// DeploymentStatus contains the status part of a Cluster resource.
2830
type DeploymentStatus struct {

pkg/apis/deployment/v1alpha/member_status.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package v1alpha
2424

2525
import (
26+
"reflect"
2627
"time"
2728

2829
driver "github.com/arangodb/go-driver"
@@ -54,6 +55,8 @@ type MemberStatus struct {
5455
IsInitialized bool `json:"initialized"`
5556
// CleanoutJobID holds the ID of the agency job for cleaning out this server
5657
CleanoutJobID string `json:"cleanout-job-id,omitempty"`
58+
// SideCarSpecs contains list of specifications specified for side cars
59+
SideCarSpecs map[string]v1.Container
5760
// ArangoVersion holds the ArangoDB version in member
5861
ArangoVersion driver.Version `json:"arango-version,omitempty"`
5962
//ImageId holds the members ArangoDB image ID
@@ -70,6 +73,7 @@ func (s MemberStatus) Equal(other MemberStatus) bool {
7073
s.Conditions.Equal(other.Conditions) &&
7174
s.IsInitialized == other.IsInitialized &&
7275
s.CleanoutJobID == other.CleanoutJobID &&
76+
reflect.DeepEqual(s.SideCarSpecs, other.SideCarSpecs) &&
7377
s.ArangoVersion == other.ArangoVersion &&
7478
s.ImageID == other.ImageID
7579
}

pkg/deployment/reconcile/action_context.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ type ActionContext interface {
8888
GetDeploymentHealth() (driver.ClusterHealth, error)
8989
// InvalidateSyncStatus resets the sync state to false and triggers an inspection
9090
InvalidateSyncStatus()
91+
// GetSpec returns a copy of the spec
92+
GetSpec() api.DeploymentSpec
93+
9194
}
9295

9396
// newActionContext creates a new ActionContext implementation.
@@ -109,6 +112,10 @@ func (ac *actionContext) GetMode() api.DeploymentMode {
109112
return ac.context.GetSpec().GetMode()
110113
}
111114

115+
func (ac *actionContext) GetSpec() api.DeploymentSpec {
116+
return ac.context.GetSpec()
117+
}
118+
112119
// GetDeploymentHealth returns a copy of the latest known state of cluster health
113120
func (ac *actionContext) GetDeploymentHealth() (driver.ClusterHealth, error) {
114121
return ac.context.GetDeploymentHealth()

pkg/deployment/reconcile/action_rotate_member.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"context"
2727
"time"
2828

29+
"k8s.io/api/core/v1"
2930
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
3031
"github.com/rs/zerolog"
3132
)
@@ -89,6 +90,7 @@ func (a *actionRotateMember) Start(ctx context.Context) (bool, error) {
8990
}
9091
// Update status
9192
m.Phase = api.MemberPhaseRotating
93+
9294
if err := a.actionCtx.UpdateMember(m); err != nil {
9395
return false, maskAny(err)
9496
}
@@ -117,6 +119,15 @@ func (a *actionRotateMember) CheckProgress(ctx context.Context) (bool, bool, err
117119
m.Phase = api.MemberPhaseNone
118120
m.RecentTerminations = nil // Since we're rotating, we do not care about old terminations.
119121
m.CleanoutJobID = ""
122+
123+
group := a.action.Group
124+
var groupSpec = a.actionCtx.GetSpec().GetServerGroupSpec(group)
125+
// Check for missing side cars in
126+
m.SideCarSpecs = make(map[string]v1.Container)
127+
for _, specSidecar := range groupSpec.GetSidecars() {
128+
m.SideCarSpecs[specSidecar.Name] = *specSidecar.DeepCopy()
129+
}
130+
120131
if err := a.actionCtx.UpdateMember(m); err != nil {
121132
return false, false, maskAny(err)
122133
}

pkg/deployment/reconcile/plan_builder.go

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,18 @@
2323
package reconcile
2424

2525
import (
26+
"reflect"
2627
"strings"
2728

2829
driver "github.com/arangodb/go-driver"
2930
upgraderules "github.com/arangodb/go-upgrade-rules"
3031
"github.com/rs/zerolog"
3132
"github.com/rs/zerolog/log"
32-
"k8s.io/api/core/v1"
3333
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3434

3535
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
3636
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
37+
v1 "k8s.io/api/core/v1"
3738
)
3839

3940
// upgradeDecision is the result of an upgrade check.
@@ -394,9 +395,106 @@ func podNeedsRotation(log zerolog.Logger, p v1.Pod, apiObject metav1.Object, spe
394395
return true, "Resource Requirements changed"
395396
}
396397

398+
var memberStatus, _, _ = status.Members.MemberStatusByPodName(p.GetName())
399+
if memberStatus.SideCarSpecs == nil {
400+
memberStatus.SideCarSpecs = make(map[string]v1.Container)
401+
}
402+
403+
// Check for missing side cars in
404+
for _, specSidecar := range groupSpec.GetSidecars() {
405+
var stateSidecar v1.Container
406+
if stateSidecar, found = memberStatus.SideCarSpecs[specSidecar.Name]; !found {
407+
return true, "Sidecar " + specSidecar.Name + " not found in running pod " + p.GetName()
408+
}
409+
if sideCarRequireRotation(specSidecar.DeepCopy(), &stateSidecar) {
410+
return true, "Sidecar " + specSidecar.Name + " requires rotation"
411+
}
412+
}
413+
414+
for name := range memberStatus.SideCarSpecs {
415+
var found = false
416+
for _, specSidecar := range groupSpec.GetSidecars() {
417+
if name == specSidecar.Name {
418+
found = true
419+
break
420+
}
421+
}
422+
if !found {
423+
return true, "Sidecar " + name + " no longer in specification"
424+
}
425+
}
426+
397427
return false, ""
398428
}
399429

430+
// sideCarRequireRotation checks if side car requires rotation including default parameters
431+
func sideCarRequireRotation(wanted, given *v1.Container) bool {
432+
if !reflect.DeepEqual(wanted.Args, given.Args) {
433+
return true
434+
}
435+
if !reflect.DeepEqual(wanted.Command, given.Command) {
436+
return true
437+
}
438+
if !reflect.DeepEqual(wanted.Env, given.Env) {
439+
return true
440+
}
441+
if !reflect.DeepEqual(wanted.EnvFrom, given.EnvFrom) {
442+
return true
443+
}
444+
if wanted.Image != given.Image {
445+
return true
446+
}
447+
if wanted.ImagePullPolicy != given.ImagePullPolicy {
448+
if wanted.ImagePullPolicy != "Always" || !strings.HasSuffix(given.Image, ":latest") {
449+
return true
450+
}
451+
}
452+
if wanted.Lifecycle != given.Lifecycle {
453+
return true
454+
}
455+
if wanted.LivenessProbe != given.LivenessProbe {
456+
return true
457+
}
458+
if !reflect.DeepEqual(wanted.Ports, given.Ports) {
459+
return true
460+
}
461+
if wanted.ReadinessProbe != given.ReadinessProbe {
462+
return true
463+
}
464+
if !reflect.DeepEqual(wanted.Resources, given.Resources) {
465+
return true
466+
}
467+
if wanted.SecurityContext != given.SecurityContext {
468+
return true
469+
}
470+
if wanted.Stdin != given.Stdin {
471+
return true
472+
}
473+
if wanted.StdinOnce != given.StdinOnce {
474+
return true
475+
}
476+
if wanted.TerminationMessagePath != given.TerminationMessagePath {
477+
return true
478+
}
479+
if wanted.TerminationMessagePolicy != given.TerminationMessagePolicy {
480+
return true
481+
}
482+
if wanted.TTY != given.TTY {
483+
return true
484+
}
485+
if !reflect.DeepEqual(wanted.VolumeDevices, given.VolumeDevices) {
486+
return true
487+
}
488+
if !reflect.DeepEqual(wanted.VolumeMounts, given.VolumeMounts) {
489+
return true
490+
}
491+
if wanted.WorkingDir != given.WorkingDir {
492+
return true
493+
}
494+
495+
return false
496+
}
497+
400498
// resourcesRequireRotation returns true if the resource requirements have changed such that a rotation is required
401499
func resourcesRequireRotation(wanted, given v1.ResourceRequirements) bool {
402500
checkList := func(wanted, given v1.ResourceList) bool {

pkg/deployment/resources/member_cleanup.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func (r *Resources) cleanupRemovedClusterMembers() error {
7171
r.health.mutex.Unlock()
7272

7373
// Only accept recent cluster health values
74+
7475
healthAge := time.Since(ts)
7576
if healthAge > maxClusterHealthAge {
7677
log.Info().Dur("age", healthAge).Msg("Cleanup longer than max cluster health. Exiting")

tests/load_balancer_source_ranges_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func TestLoadBalancingSourceRanges(t *testing.T) {
108108
}
109109
t.Logf("Service %s cannot be found, waiting for some time...", eaServiceName)
110110
time.Sleep(time.Second)
111-
counter += 1
111+
counter++
112112
if counter >= 60 {
113113
t.Fatalf("Could not find service %s within 60 seconds, giving up.", eaServiceName)
114114
}
@@ -149,7 +149,7 @@ func TestLoadBalancingSourceRanges(t *testing.T) {
149149
}
150150
}
151151
t.Logf("Service %s cannot be found, waiting for some more time...", eaServiceName)
152-
counter += 1
152+
counter++
153153
if counter >= 60 {
154154
t.Fatalf("Could not find changed service %s within 60 seconds, giving up.", eaServiceName)
155155
}

0 commit comments

Comments
 (0)