Skip to content

Commit ee6a61a

Browse files
author
Sergey Dudoladov
committed
Improve reporting about rolling updates
1 parent 688d252 commit ee6a61a

File tree

5 files changed

+26
-18
lines changed

5 files changed

+26
-18
lines changed

docs/administrator.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,8 @@ The operator is capable of maintaining roles of multiple kinds within a Postgres
219219

220220
3. **Per-cluster robot users** are also roles for processes originating from external systems but defined for an individual Postgres cluster in its manifest. A typical example is a role for connections from an application that uses the database.
221221

222-
4. **Human users** originate from the Teams API that returns list of the team members given a team id. Operator differentiates between (a) product teams that own a particular Postgres cluster and are granted admin rights to maintain it, and (b) Postgres superuser teams that get the superuser access to all PG databases running in a k8s cluster for the purposes of maintaining and troubleshooting.
222+
4. **Human users** originate from the Teams API that returns list of the team members given a team id. Operator differentiates between (a) product teams that own a particular Postgres cluster and are granted admin rights to maintain it, and (b) Postgres superuser teams that get the superuser access to all PG databases running in a k8s cluster for the purposes of maintaining and troubleshooting.
223+
224+
## Understanding rolling update of Spilo pods
225+
226+
The operator logs reasons for a rolling update with the `info` level and a diff between the old and new StatefulSet specs with the `debug` level. To benefit from numerous escape characters in the latter log entry, view it in CLI with `echo -e`. Note that the resultant message will contain some noise because the `PodTemplate` used by the operator is yet to be updated with the default values used internally in Kubernetes.

pkg/cluster/cluster.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -321,15 +321,16 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *v1beta1.StatefulSet) *comp
321321
needsRollUpdate = true
322322
reasons = append(reasons, "new statefulset's container specification doesn't match the current one")
323323
} else {
324-
needsRollUpdate, reasons = c.compareContainers(c.Statefulset, statefulSet)
324+
var containerReasons []string
325+
needsRollUpdate, containerReasons = c.compareContainers(c.Statefulset, statefulSet)
326+
reasons = append(reasons, containerReasons...)
325327
}
326328
if len(c.Statefulset.Spec.Template.Spec.Containers) == 0 {
327329
c.logger.Warningf("statefulset %q has no container", util.NameFromMeta(c.Statefulset.ObjectMeta))
328330
return &compareStatefulsetResult{}
329331
}
330332
// In the comparisons below, the needsReplace and needsRollUpdate flags are never reset, since checks fall through
331333
// and the combined effect of all the changes should be applied.
332-
// TODO: log all reasons for changing the statefulset, not just the last one.
333334
// TODO: make sure this is in sync with generatePodTemplate, ideally by using the same list of fields to generate
334335
// the template and the diff
335336
if c.Statefulset.Spec.Template.Spec.ServiceAccountName != statefulSet.Spec.Template.Spec.ServiceAccountName {
@@ -340,7 +341,7 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *v1beta1.StatefulSet) *comp
340341
if *c.Statefulset.Spec.Template.Spec.TerminationGracePeriodSeconds != *statefulSet.Spec.Template.Spec.TerminationGracePeriodSeconds {
341342
needsReplace = true
342343
needsRollUpdate = true
343-
reasons = append(reasons, "new statefulset's terminationGracePeriodSeconds doesn't match the current one")
344+
reasons = append(reasons, "new statefulset's terminationGracePeriodSeconds doesn't match the current one")
344345
}
345346
if !reflect.DeepEqual(c.Statefulset.Spec.Template.Spec.Affinity, statefulSet.Spec.Template.Spec.Affinity) {
346347
needsReplace = true
@@ -416,23 +417,23 @@ func newCheck(msg string, cond containerCondition) containerCheck {
416417

417418
// compareContainers: compare containers from two stateful sets
418419
// and return:
419-
// * whether or not roll update is needed
420+
// * whether or not a rolling update is needed
420421
// * a list of reasons in a human readable format
421422
func (c *Cluster) compareContainers(setA, setB *v1beta1.StatefulSet) (bool, []string) {
422423
reasons := make([]string, 0)
423424
needsRollUpdate := false
424425
checks := []containerCheck{
425-
newCheck("new statefulset's container %d name doesn't match the current one",
426+
newCheck("new statefulset's container %s (index %d) name doesn't match the current one",
426427
func(a, b v1.Container) bool { return a.Name != b.Name }),
427-
newCheck("new statefulset's container %d image doesn't match the current one",
428+
newCheck("new statefulset's container %s (index %d) image doesn't match the current one",
428429
func(a, b v1.Container) bool { return a.Image != b.Image }),
429-
newCheck("new statefulset's container %d ports don't match the current one",
430+
newCheck("new statefulset's container %s (index %d) ports don't match the current one",
430431
func(a, b v1.Container) bool { return !reflect.DeepEqual(a.Ports, b.Ports) }),
431-
newCheck("new statefulset's container %d resources don't match the current ones",
432+
newCheck("new statefulset's container %s (index %d) resources don't match the current ones",
432433
func(a, b v1.Container) bool { return !compareResources(&a.Resources, &b.Resources) }),
433-
newCheck("new statefulset's container %d environment doesn't match the current one",
434+
newCheck("new statefulset's container %s (index %d) environment doesn't match the current one",
434435
func(a, b v1.Container) bool { return !reflect.DeepEqual(a.Env, b.Env) }),
435-
newCheck("new statefulset's container %d environment sources don't match the current one",
436+
newCheck("new statefulset's container %s (index %d) environment sources don't match the current one",
436437
func(a, b v1.Container) bool { return !reflect.DeepEqual(a.EnvFrom, b.EnvFrom) }),
437438
}
438439

@@ -441,7 +442,7 @@ func (c *Cluster) compareContainers(setA, setB *v1beta1.StatefulSet) (bool, []st
441442
for _, check := range checks {
442443
if check.condition(containerA, containerB) {
443444
needsRollUpdate = true
444-
reasons = append(reasons, fmt.Sprintf(check.reason, index))
445+
reasons = append(reasons, fmt.Sprintf(check.reason, containerA.Name, index))
445446
}
446447
}
447448
}

pkg/cluster/resources.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,17 @@ func (c *Cluster) preScaleDown(newStatefulSet *v1beta1.StatefulSet) error {
132132
return nil
133133
}
134134

135-
// setRollingUpdateFlagForStatefulSet sets the indicator or the rolling upgrade requirement
135+
// setRollingUpdateFlagForStatefulSet sets the indicator or the rolling update requirement
136136
// in the StatefulSet annotation.
137137
func (c *Cluster) setRollingUpdateFlagForStatefulSet(sset *v1beta1.StatefulSet, val bool) {
138138
anno := sset.GetAnnotations()
139-
c.logger.Debugf("rolling upgrade flag has been set to %t", val)
140139
if anno == nil {
141140
anno = make(map[string]string)
142141
}
142+
143143
anno[rollingUpdateStatefulsetAnnotationKey] = strconv.FormatBool(val)
144144
sset.SetAnnotations(anno)
145+
c.logger.Debugf("statefulset's rolling update annotation has been set to %t", val)
145146
}
146147

147148
// applyRollingUpdateFlagforStatefulSet sets the rolling update flag for the cluster's StatefulSet
@@ -176,9 +177,9 @@ func (c *Cluster) getRollingUpdateFlagFromStatefulSet(sset *v1beta1.StatefulSet,
176177
return flag
177178
}
178179

179-
// mergeRollingUpdateFlagUsingCache return the value of the rollingUpdate flag from the passed
180+
// mergeRollingUpdateFlagUsingCache returns the value of the rollingUpdate flag from the passed
180181
// statefulset, however, the value can be cleared if there is a cached flag in the cluster that
181-
// is set to false (the disrepancy could be a result of a failed StatefulSet update).s
182+
// is set to false (the discrepancy could be a result of a failed StatefulSet update)
182183
func (c *Cluster) mergeRollingUpdateFlagUsingCache(runningStatefulSet *v1beta1.StatefulSet) bool {
183184
var (
184185
cachedStatefulsetExists, clearRollingUpdateFromCache, podsRollingUpdateRequired bool
@@ -198,7 +199,7 @@ func (c *Cluster) mergeRollingUpdateFlagUsingCache(runningStatefulSet *v1beta1.S
198199
c.logger.Infof("clearing the rolling update flag based on the cached information")
199200
podsRollingUpdateRequired = false
200201
} else {
201-
c.logger.Infof("found a statefulset with an unfinished pods rolling update")
202+
c.logger.Infof("found a statefulset with an unfinished rolling update of the pods")
202203

203204
}
204205
}

pkg/cluster/sync.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cluster
22

33
import (
44
"fmt"
5+
56
"k8s.io/api/core/v1"
67
policybeta1 "k8s.io/api/policy/v1beta1"
78
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -280,6 +281,7 @@ func (c *Cluster) syncStatefulSet() error {
280281
podsRollingUpdateRequired = true
281282
c.setRollingUpdateFlagForStatefulSet(desiredSS, podsRollingUpdateRequired)
282283
}
284+
283285
c.logStatefulSetChanges(c.Statefulset, desiredSS, false, cmp.reasons)
284286

285287
if !cmp.replace {

pkg/cluster/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func (c *Cluster) logStatefulSetChanges(old, new *v1beta1.StatefulSet, isUpdate
179179
if !reflect.DeepEqual(old.Annotations, new.Annotations) {
180180
c.logger.Debugf("metadata.annotation diff\n%s\n", util.PrettyDiff(old.Annotations, new.Annotations))
181181
}
182-
c.logger.Debugf("spec diff\n%s\n", util.PrettyDiff(old.Spec, new.Spec))
182+
c.logger.Debugf("spec diff between old and new statefulsets: \n%s\n", util.PrettyDiff(old.Spec, new.Spec))
183183

184184
if len(reasons) > 0 {
185185
for _, reason := range reasons {

0 commit comments

Comments
 (0)