Skip to content

Commit 198cac5

Browse files
authored
[Bugfix] Prevent LifeCycle restarts (#1127)
1 parent 87ea1ee commit 198cac5

File tree

13 files changed

+953
-55
lines changed

13 files changed

+953
-55
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- (Feature) Add Member Update helpers
66
- (Feature) Active Member condition
77
- (Bugfix) Accept Initial Spec
8+
- (Bugfix) Prevent LifeCycle restarts
89

910
## [1.2.17](https://github.com/arangodb/kube-arangodb/tree/1.2.17) (2022-09-22)
1011
- (Feature) Add new field to DeploymentReplicationStatus with details on DC2DC sync status=

go.mod

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ require (
5555
k8s.io/apimachinery v0.21.10
5656
k8s.io/client-go v12.0.0+incompatible
5757
k8s.io/klog v1.0.0
58-
)
59-
60-
require (
6158
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect
6259
github.com/beorn7/perks v1.0.1 // indirect
6360
github.com/cespare/xxhash/v2 v2.1.1 // indirect
@@ -106,6 +103,10 @@ require (
106103
k8s.io/utils v0.0.0-20210521133846-da695404a2bc // indirect
107104
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
108105
sigs.k8s.io/yaml v1.2.0
106+
github.com/josephburnett/jd v1.6.1
107+
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
108+
github.com/go-openapi/jsonpointer v0.19.5 // indirect
109+
github.com/go-openapi/swag v0.21.1 // indirect
110+
github.com/josharian/intern v1.0.0 // indirect
111+
github.com/mailru/easyjson v0.7.7 // indirect
109112
)
110-
111-
require github.com/cenkalti/backoff/v4 v4.1.3 // indirect

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,16 @@ github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
164164
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
165165
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
166166
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
167+
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
168+
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
167169
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
168170
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
169171
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
170172
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
171173
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
172174
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
175+
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
176+
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
173177
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
174178
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
175179
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -305,6 +309,10 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
305309
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 h1:cW/amwGEJK5MSKntPXRjX4dxs/nGxGT8gXKIsKFmHGc=
306310
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15/go.mod h1:Fdm/oWRW+CH8PRbLntksCNtmcCBximKPkVQYvmMl80k=
307311
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
312+
github.com/josephburnett/jd v1.6.1 h1:Uzqhcje4WqvVyp85F3Oj0ezISPTlnhnr/KaLZIy8qh0=
313+
github.com/josephburnett/jd v1.6.1/go.mod h1:R8ZnZnLt2D4rhW4NvBc/USTo6mzyNT6fYNIIWOJA9GY=
314+
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
315+
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
308316
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
309317
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
310318
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -339,6 +347,9 @@ github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK
339347
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
340348
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
341349
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
350+
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
351+
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
352+
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
342353
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
343354
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
344355
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@@ -900,6 +911,7 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
900911
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
901912
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
902913
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
914+
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
903915
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
904916
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
905917
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=

pkg/deployment/resources/internal_exporter.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,10 @@
1919
package resources
2020

2121
import (
22-
"os"
23-
"path/filepath"
24-
2522
core "k8s.io/api/core/v1"
2623

2724
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
2825
"github.com/arangodb/kube-arangodb/pkg/apis/shared"
29-
"github.com/arangodb/kube-arangodb/pkg/util/errors"
3026
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3127
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/probes"
3228
)
@@ -36,11 +32,7 @@ func ArangodbInternalExporterContainer(image string, args []string, livenessProb
3632
resources core.ResourceRequirements, securityContext *core.SecurityContext,
3733
spec api.DeploymentSpec) (core.Container, error) {
3834

39-
binaryPath, err := os.Executable()
40-
if err != nil {
41-
return core.Container{}, errors.WithStack(err)
42-
}
43-
exePath := filepath.Join(k8sutil.LifecycleVolumeMountDir, filepath.Base(binaryPath))
35+
exePath := k8sutil.LifecycleBinary()
4436

4537
c := core.Container{
4638
Name: shared.ExporterContainerName,

pkg/deployment/resources/pod_creator_probes.go

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

2323
import (
2424
"math"
25-
"os"
26-
"path/filepath"
2725
"time"
2826

2927
core "k8s.io/api/core/v1"
@@ -223,18 +221,13 @@ func (r *Resources) probeBuilders(imageInfo api.ImageInfo) map[api.ServerGroup]p
223221
}
224222
}
225223

226-
func (r *Resources) probeCommand(spec api.DeploymentSpec, probeType api.ProbeType) ([]string, error) {
227-
binaryPath, err := os.Executable()
228-
if err != nil {
229-
return nil, err
230-
}
231-
exePath := filepath.Join(k8sutil.LifecycleVolumeMountDir, filepath.Base(binaryPath))
224+
func (r *Resources) probeCommand(spec api.DeploymentSpec, probeType api.ProbeType) []string {
225+
exePath := k8sutil.LifecycleBinary()
232226
args := []string{
233227
exePath,
234228
"lifecycle",
235229
"probe",
236230
string(probeType),
237-
// TODO test rotation required when changed
238231
}
239232

240233
if spec.IsSecure() {
@@ -245,7 +238,7 @@ func (r *Resources) probeCommand(spec api.DeploymentSpec, probeType api.ProbeTyp
245238
args = append(args, "--auth")
246239
}
247240

248-
return args, nil
241+
return args
249242
}
250243

251244
func (r *Resources) probeBuilderLivenessCoreSelect(group api.ServerGroup, imageInfo api.ImageInfo) probeBuilder {
@@ -266,10 +259,7 @@ func (r *Resources) probeBuilderStartupCoreSelect(group api.ServerGroup, imageIn
266259

267260
func (r *Resources) probeBuilderLivenessCoreOperator(spec api.DeploymentSpec, group api.ServerGroup,
268261
image api.ImageInfo) (Probe, error) {
269-
args, err := r.probeCommand(spec, api.ProbeTypeLiveness)
270-
if err != nil {
271-
return nil, err
272-
}
262+
args := r.probeCommand(spec, api.ProbeTypeLiveness)
273263

274264
cmdProbeConfig := &probes.CMDProbeConfig{
275265
Command: args,
@@ -283,10 +273,7 @@ func (r *Resources) probeBuilderLivenessCoreOperator(spec api.DeploymentSpec, gr
283273

284274
func (r *Resources) probeBuilderStartupCoreOperator(spec api.DeploymentSpec, group api.ServerGroup,
285275
image api.ImageInfo) (Probe, error) {
286-
args, err := r.probeCommand(spec, api.ProbeTypeStartUp)
287-
if err != nil {
288-
return nil, err
289-
}
276+
args := r.probeCommand(spec, api.ProbeTypeStartUp)
290277

291278
retries, periodSeconds := getProbeRetries(group)
292279
if IsServerProgressAvailable(group, image) {
@@ -399,10 +386,7 @@ func (r *Resources) probeBuilderReadinessCoreSelect() probeBuilder {
399386
}
400387

401388
func (r *Resources) probeBuilderReadinessCoreOperator(spec api.DeploymentSpec, _ api.ServerGroup, _ api.ImageInfo) (Probe, error) {
402-
args, err := r.probeCommand(spec, api.ProbeTypeReadiness)
403-
if err != nil {
404-
return nil, err
405-
}
389+
args := r.probeCommand(spec, api.ProbeTypeReadiness)
406390

407391
return &probes.CMDProbeConfig{
408392
Command: args,

pkg/deployment/rotation/arangod_containers.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
3333
"github.com/arangodb/kube-arangodb/pkg/deployment/topology"
3434
"github.com/arangodb/kube-arangodb/pkg/util"
35+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3536
)
3637

3738
const (
@@ -61,7 +62,7 @@ func containersCompare(ds api.DeploymentSpec, g api.ServerGroup, spec, status *c
6162

6263
g := podContainerFuncGenerator(ds, g, ac, bc)
6364

64-
if m, p, err := comparePodContainer(builder, g(compareServerContainerVolumeMounts)); err != nil {
65+
if m, p, err := comparePodContainer(builder, g(compareServerContainerVolumeMounts), g(compareServerContainerProbes)); err != nil {
6566
log.Err(err).Msg("Error while getting pod diff")
6667
return SkippedRotation, nil, err
6768
} else {
@@ -104,11 +105,6 @@ func containersCompare(ds api.DeploymentSpec, g api.ServerGroup, spec, status *c
104105
bc.Ports = ac.Ports
105106
mode = mode.And(SilentRotation)
106107
}
107-
108-
if !areProbesEqual(ac.StartupProbe, bc.StartupProbe) {
109-
bc.StartupProbe = ac.StartupProbe
110-
mode = mode.And(SilentRotation)
111-
}
112108
} else {
113109
if ac.Image != bc.Image {
114110
// Image changed
@@ -252,6 +248,18 @@ func areProbesEqual(a, b *core.Probe) bool {
252248
return equality.Semantic.DeepEqual(a, b)
253249
}
254250

251+
func isManagedProbe(a, b *core.Probe) bool {
252+
if a.Exec == nil || b.Exec == nil {
253+
return false
254+
}
255+
256+
if len(a.Exec.Command) == 0 || len(b.Exec.Command) == 0 {
257+
return false
258+
}
259+
260+
return a.Exec.Command[0] == k8sutil.LifecycleBinary() && b.Exec.Command[0] == k8sutil.LifecycleBinary()
261+
}
262+
255263
// areEnvsFromEqual returns true when environment variables from source are the same after filtering.
256264
func areEnvsFromEqual(a, b []core.EnvFromSource, rules ...func(a, b map[string]core.EnvFromSource) (map[string]core.EnvFromSource, map[string]core.EnvFromSource)) bool {
257265
am := createEnvsFromMap(a)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2016-2022 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+
package rotation
22+
23+
import (
24+
core "k8s.io/api/core/v1"
25+
"k8s.io/apimachinery/pkg/api/equality"
26+
27+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
28+
)
29+
30+
func compareServerContainerProbes(ds api.DeploymentSpec, g api.ServerGroup, spec, status *core.Container) comparePodContainerFunc {
31+
return func(builder api.ActionBuilder) (mode Mode, plan api.Plan, err error) {
32+
if !areProbesEqual(spec.StartupProbe, status.StartupProbe) {
33+
status.StartupProbe = spec.StartupProbe
34+
mode = mode.And(SilentRotation)
35+
}
36+
37+
if !areProbesEqual(spec.ReadinessProbe, status.ReadinessProbe) {
38+
if isManagedProbe(spec.ReadinessProbe, status.ReadinessProbe) {
39+
q := status.ReadinessProbe.DeepCopy()
40+
41+
q.Exec = spec.ReadinessProbe.Exec.DeepCopy()
42+
43+
if equality.Semantic.DeepDerivative(spec.ReadinessProbe, q) {
44+
status.ReadinessProbe = spec.ReadinessProbe
45+
mode = mode.And(SilentRotation)
46+
}
47+
}
48+
}
49+
50+
if !areProbesEqual(spec.LivenessProbe, status.LivenessProbe) {
51+
if isManagedProbe(spec.LivenessProbe, status.LivenessProbe) {
52+
q := status.LivenessProbe.DeepCopy()
53+
54+
q.Exec = spec.LivenessProbe.Exec.DeepCopy()
55+
56+
if equality.Semantic.DeepDerivative(spec.LivenessProbe, q) {
57+
status.LivenessProbe = spec.LivenessProbe
58+
mode = mode.And(SilentRotation)
59+
}
60+
}
61+
}
62+
63+
return
64+
}
65+
}

pkg/deployment/rotation/compare.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ package rotation
2323
import (
2424
"encoding/json"
2525

26+
jd "github.com/josephburnett/jd/lib"
2627
"github.com/rs/zerolog/log"
2728
core "k8s.io/api/core/v1"
2829

@@ -114,14 +115,27 @@ func compare(deploymentSpec api.DeploymentSpec, member api.MemberStatus, group a
114115
}
115116

116117
if spec.RotationNeeded(newStatus) {
117-
specData, _ := json.Marshal(spec)
118-
statusData, _ := json.Marshal(newStatus)
119-
120-
log.Info().Str("before", spec.PodSpecChecksum).
121-
Str("id", member.ID).
122-
Str("spec", string(specData)).
123-
Str("status", string(statusData)).
124-
Msg("Pod needs rotation - templates does not match")
118+
line := logger.Str("id", member.ID)
119+
120+
specBytes, errA := json.Marshal(spec.PodSpec)
121+
if errA == nil {
122+
line = line.Str("spec", string(specBytes))
123+
}
124+
125+
statusBytes, errB := json.Marshal(newStatus.PodSpec)
126+
if errB == nil {
127+
line = line.Str("status", string(statusBytes))
128+
}
129+
130+
if errA == nil && errB == nil {
131+
if specData, err := jd.ReadJsonString(string(specBytes)); err == nil && specData != nil {
132+
if statusData, err := jd.ReadJsonString(string(statusBytes)); err == nil && statusData != nil {
133+
line = line.Str("diff", specData.Diff(statusData).Render())
134+
}
135+
}
136+
}
137+
138+
line.Info("Pod needs rotation - templates does not match")
125139

126140
return GracefulRotation, nil, nil
127141
}

pkg/deployment/rotation/logger.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2016-2022 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+
package rotation
22+
23+
import "github.com/arangodb/kube-arangodb/pkg/logging"
24+
25+
var (
26+
logger = logging.Global().RegisterAndGetLogger("pod_compare", logging.Info)
27+
)

0 commit comments

Comments
 (0)