Skip to content

Commit bf7bf43

Browse files
authored
233 do not upgrade statefulset when only replicas differ (#236)
* scale only when only the replicas have changed #233 * extract image tag correct #233 * extend triggers logging to quorum up/down-grades #233 * bump charts, manifests and versions #233
1 parent c469bb4 commit bf7bf43

8 files changed

Lines changed: 66 additions & 22 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ OPERATOR_SDK_VERSION ?= v1.38.0
5252
# Image URL to use all building/pushing image targets
5353
DOCKER_HUB_NAME ?= $(shell docker info | sed '/Username:/!d;s/.* //')
5454
IMG_NAME ?= typesense-operator
55-
IMG_TAG ?= 0.3.8-rc.2
55+
IMG_TAG ?= 0.3.8-rc.3
5656
IMG ?= $(DOCKER_HUB_NAME)/$(IMG_NAME):$(IMG_TAG)
5757

5858
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ Join the conversation:
228228
## 📦 Project Status
229229
230230
TyKO is an **independently maintained** project (not affiliated with Typesense, Inc.).
231-
- Latest version: **0.3.8-rc.2**
231+
- Latest version: **0.3.8-rc.3**
232232
- Tested on: Kubernetes 1.35 (earliest 1.26), Typesense 30.0 (earliest 26.0)
233233
- Contributions welcome! See [FAQ](https://akyriako.github.io/typesense-operator-docs/docs/faq) and [Development](https://akyriako.github.io/typesense-operator-docs/docs/development)
234234

charts/typesense-operator/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ type: application
1414
# This is the chart version. This version number should be incremented each time you make changes
1515
# to the chart and its templates, including the app version.
1616
# Versions are expected to follow Semantic Versioning (https://semver.org/)
17-
version: 0.3.8-rc.2
17+
version: 0.3.8-rc.3
1818
# This is the version number of the application being deployed. This version number should be
1919
# incremented each time you make changes to the application. Versions are not expected to
2020
# follow Semantic Versioning. They should reflect the version the application is using.
2121
# It is recommended to use it with quotes.
22-
appVersion: "0.3.8-rc.2"
22+
appVersion: "0.3.8-rc.3"
2323

2424
maintainers:
2525
- name: Kyriakos Akriotis

charts/typesense-operator/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ controllerManager:
1212
- ALL
1313
image:
1414
repository: akyriako78/typesense-operator
15-
tag: 0.3.8-rc.2
15+
tag: 0.3.8-rc.3
1616
imagePullPolicy: IfNotPresent
1717
resources:
1818
limits:

config/manager/kustomization.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ kind: Kustomization
55
images:
66
- name: controller
77
newName: akyriako78/typesense-operator
8-
newTag: 0.3.8-rc.2
8+
newTag: 0.3.8-rc.3

internal/controller/typesensecluster_quorum.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,20 @@ func (r *TypesenseClusterReconciler) ReconcileQuorum(ctx context.Context, ts *ts
216216
return ConditionReasonQuorumReady, 0, nil
217217
}
218218

219+
var (
220+
QuorumDowngraded UpdateStatefulSetTrigger = "QuorumDowngraded"
221+
QuorumUpgraded UpdateStatefulSetTrigger = "QuorumUpgraded"
222+
)
223+
219224
func (r *TypesenseClusterReconciler) downgradeQuorum(
220225
ctx context.Context,
221226
ts *tsv1alpha1.TypesenseCluster,
222227
cm *v1.ConfigMap,
223228
stsObjectKey client.ObjectKey,
224229
healthyNodes, minRequiredNodes int32,
225230
) (ConditionQuorum, int, error) {
226-
r.logger.Info("downgrading quorum")
231+
//r.logger.Info("downgrading quorum")
232+
r.logger.V(debugLevel).Info("scaling statefulset", "sts", stsObjectKey.Name, "triggers", QuorumDowngraded)
227233

228234
sts, err := r.GetFreshStatefulSet(ctx, stsObjectKey)
229235
if err != nil {
@@ -264,7 +270,8 @@ func (r *TypesenseClusterReconciler) upgradeQuorum(
264270
cm *v1.ConfigMap,
265271
stsObjectKey client.ObjectKey,
266272
) (ConditionQuorum, int, error) {
267-
r.logger.Info("upgrading quorum", "incremental", ts.Spec.IncrementalQuorumRecovery)
273+
//r.logger.Info("upgrading quorum", "incremental", ts.Spec.IncrementalQuorumRecovery)
274+
r.logger.V(debugLevel).Info("scaling statefulset", "sts", stsObjectKey.Name, "triggers", QuorumUpgraded, "incremental", ts.Spec.IncrementalQuorumRecovery)
268275

269276
sts, err := r.GetFreshStatefulSet(ctx, stsObjectKey)
270277
if err != nil {

internal/controller/typesensecluster_statefulset.go

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,17 @@ func (r *TypesenseClusterReconciler) ReconcileStatefulSet(ctx context.Context, t
9090
r.logger.Error(err, "building statefulset failed", "sts", stsObjectKey.Name)
9191
}
9292

93-
update, triggers := r.shouldUpdateStatefulSet(sts, desiredSts, ts)
93+
update, scaleOnly, triggers := r.shouldUpdateStatefulSet(sts, desiredSts, ts)
9494
if update {
95-
r.logger.V(debugLevel).Info("updating statefulset", "sts", sts.Name, "triggers", triggers)
96-
97-
oldImage := strings.Replace(sts.Spec.Template.Spec.Containers[0].Image, "typesense/typesense:", "", -1)
98-
newImage := strings.Replace(desiredSts.Spec.Template.Spec.Containers[0].Image, "typesense/typesense:", "", -1)
95+
oldImage := getImageTag(sts.Spec.Template.Spec.Containers[0].Image)
96+
newImage := getImageTag(desiredSts.Spec.Template.Spec.Containers[0].Image)
9997
if oldImage != newImage {
100-
r.logger.V(debugLevel).Info("scheduling typesense update", "current", oldImage, "target", newImage)
98+
triggers = append(triggers, SpecTypesenseVersionChanged)
10199
r.Recorder.Eventf(ts, "Normal", "TypesenseVersionUpdate", "Scheduled update from %s to %s", oldImage, newImage)
102100
}
103101

102+
r.logger.V(debugLevel).Info("updating statefulset", "sts", sts.Name, "triggers", triggers)
103+
104104
updatedSts, err := r.updateStatefulSet(ctx, sts, desiredSts)
105105
if err != nil {
106106
r.logger.Error(err, "updating statefulset failed", "sts", stsObjectKey.Name)
@@ -126,6 +126,33 @@ func (r *TypesenseClusterReconciler) ReconcileStatefulSet(ctx context.Context, t
126126

127127
r.logLagThresholds(updatedSts)
128128
return updatedSts, nil
129+
} else if !update && scaleOnly {
130+
r.logger.V(debugLevel).Info("scaling statefulset", "sts", sts.Name, "triggers", triggers)
131+
132+
size := ts.Spec.Replicas
133+
err = r.ScaleStatefulSet(ctx, stsObjectKey, size)
134+
if err != nil {
135+
return desiredSts, nil
136+
}
137+
138+
configMapName := fmt.Sprintf(ClusterNodesConfigMap, ts.Name)
139+
configMapObjectKey := client.ObjectKey{Namespace: ts.Namespace, Name: configMapName}
140+
141+
var cm = &corev1.ConfigMap{}
142+
if err := r.Get(ctx, configMapObjectKey, cm); err != nil {
143+
r.logger.V(debugLevel).Error(err, fmt.Sprintf("unable to fetch config map: %s", configMapName))
144+
}
145+
_, _, updated, err := r.updateConfigMap(ctx, ts, cm, &size, true)
146+
if err != nil {
147+
return desiredSts, nil
148+
}
149+
150+
if updated && ts.Spec.ForceResetPeersConfigOnUpdate {
151+
_ = r.forcePodsConfigMapUpdate(ctx, ts)
152+
}
153+
154+
r.logLagThresholds(desiredSts)
155+
return desiredSts, nil
129156
}
130157
}
131158
}
@@ -520,33 +547,35 @@ func (r *TypesenseClusterReconciler) buildStatefulSet(ctx context.Context, key c
520547
type UpdateStatefulSetTrigger string
521548

522549
var (
523-
BelowSpecReplicas UpdateStatefulSetTrigger = "BelowSpecReplicas"
550+
SpecReplicasChanged UpdateStatefulSetTrigger = "SpecReplicasChanged"
524551
HashAnnotationChanged UpdateStatefulSetTrigger = "HashAnnotationChanged"
525552
PodAnnotationsChanged UpdateStatefulSetTrigger = "PodAnnotationsChanged"
526553
StatefulSetAnnotationsChanged UpdateStatefulSetTrigger = "StatefulSetAnnotationsChanged"
527554
SpecResourcesChanged UpdateStatefulSetTrigger = "SpecResourcesChanged"
528555
PodSecurityContextChanged UpdateStatefulSetTrigger = "PodSecurityContextChanged"
529556
InvalidContainerCount UpdateStatefulSetTrigger = "InvalidContainerCount"
530557
ContainerSecurityContextChanged UpdateStatefulSetTrigger = "ContainerSecurityContextChanged"
558+
SpecTypesenseVersionChanged UpdateStatefulSetTrigger = "SpecTypesenseVersionChanged"
531559
)
532560

533-
func (r *TypesenseClusterReconciler) shouldUpdateStatefulSet(sts *appsv1.StatefulSet, desired *appsv1.StatefulSet, ts *tsv1alpha1.TypesenseCluster) (update bool, triggers []UpdateStatefulSetTrigger) {
561+
func (r *TypesenseClusterReconciler) shouldUpdateStatefulSet(sts *appsv1.StatefulSet, desired *appsv1.StatefulSet, ts *tsv1alpha1.TypesenseCluster) (update bool, scaleOnly bool, triggers []UpdateStatefulSetTrigger) {
534562
update = false
563+
scaleOnly = false
535564

536565
if sts == nil || ts == nil {
537-
return false, nil
566+
return false, false, nil
538567
}
539568

540569
condition := r.getConditionReady(ts)
541570
if condition == nil {
542-
return false, nil
571+
return false, false, nil
543572
}
544573

545-
// BelowSpecReplicas
574+
// SpecReplicasChanged
546575
if *sts.Spec.Replicas != ts.Spec.Replicas &&
547576
(condition.Reason != string(ConditionReasonQuorumDowngraded) || condition.Reason != string(ConditionReasonQuorumQueuedWrites)) {
548-
triggers = append(triggers, BelowSpecReplicas)
549-
update = true
577+
triggers = append(triggers, SpecReplicasChanged)
578+
scaleOnly = true
550579
}
551580

552581
// HashAnnotationChanged
@@ -606,7 +635,7 @@ func (r *TypesenseClusterReconciler) shouldUpdateStatefulSet(sts *appsv1.Statefu
606635
update = true
607636
}
608637

609-
return update, triggers
638+
return update, scaleOnly, triggers
610639
}
611640

612641
func (r *TypesenseClusterReconciler) shouldEmergencyUpdateStatefulSet(sts *appsv1.StatefulSet, ts *tsv1alpha1.TypesenseCluster) bool {

internal/controller/utils.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,11 @@ func filterAnnotations(annotations map[string]string, filters ...string) map[str
211211

212212
return filtered
213213
}
214+
215+
func getImageTag(image string) string {
216+
pos := strings.LastIndex(image, ":")
217+
if pos == -1 {
218+
return image
219+
}
220+
return image[pos+1:]
221+
}

0 commit comments

Comments
 (0)