Skip to content

Commit 9c81eb2

Browse files
committed
coordinate its update process
1 parent 863da7e commit 9c81eb2

File tree

9 files changed

+95
-16
lines changed

9 files changed

+95
-16
lines changed

apis/workloads/v1/instanceset_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,11 @@ type InstanceSetStatus struct {
352352
// +optional
353353
UpdateRevisions map[string]string `json:"updateRevisions,omitempty"`
354354

355+
// revisions that will be applied during next pod update process
356+
//
357+
// +optional
358+
ProposedRevisions map[string]string `json:"proposedRevisions,omitempty"`
359+
355360
// TemplatesStatus represents status of each instance generated by InstanceTemplates.
356361
//
357362
// +optional

config/crd/bases/workloads.kubeblocks.io_instancesets.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11794,6 +11794,12 @@ spec:
1179411794
InstanceSet's generation, which is updated on mutation by the API Server.
1179511795
format: int64
1179611796
type: integer
11797+
proposedRevisions:
11798+
additionalProperties:
11799+
type: string
11800+
description: revisions that will be applied during next pod update
11801+
process
11802+
type: object
1179711803
readyInitReplicas:
1179811804
description: |-
1179911805
Represents the number of instances that have already reached the InstanceStatus during the cluster initialization stage.

deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11794,6 +11794,12 @@ spec:
1179411794
InstanceSet's generation, which is updated on mutation by the API Server.
1179511795
format: int64
1179611796
type: integer
11797+
proposedRevisions:
11798+
additionalProperties:
11799+
type: string
11800+
description: revisions that will be applied during next pod update
11801+
process
11802+
type: object
1179711803
readyInitReplicas:
1179811804
description: |-
1179911805
Represents the number of instances that have already reached the InstanceStatus during the cluster initialization stage.

docs/developer_docs/api-reference/cluster.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33632,6 +33632,18 @@ key is the pod name, value is the revision.</p>
3363233632
</tr>
3363333633
<tr>
3363433634
<td>
33635+
<code>proposedRevisions</code><br/>
33636+
<em>
33637+
map[string]string
33638+
</em>
33639+
</td>
33640+
<td>
33641+
<em>(Optional)</em>
33642+
<p>revisions that will be applied during next pod update process</p>
33643+
</td>
33644+
</tr>
33645+
<tr>
33646+
<td>
3363533647
<code>templatesStatus</code><br/>
3363633648
<em>
3363733649
<a href="#workloads.kubeblocks.io/v1.InstanceTemplateStatus">

pkg/controller/instanceset/in_place_update_util.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ func getPodUpdatePolicy(its *workloads.InstanceSet, pod *corev1.Pod) (podUpdateP
296296
if err != nil {
297297
return noOpsPolicy, "", err
298298
}
299+
proposedRevisions, err := GetRevisions(its.Status.ProposedRevisions)
300+
if err != nil {
301+
return noOpsPolicy, "", err
302+
}
299303

300304
// In case of the ITS is stopping and replicas is 0, we can't compose the instance template and instance
301305
// to choose the update policy, so we use the pod update policy directly.
@@ -327,7 +331,7 @@ func getPodUpdatePolicy(its *workloads.InstanceSet, pod *corev1.Pod) (podUpdateP
327331
}
328332

329333
specUpdatePolicy := getPodUpdatePolicyInSpec(its, pod, newPod)
330-
if getPodRevision(pod) != updateRevisions[pod.Name] {
334+
if getPodRevision(pod) != updateRevisions[pod.Name] && getPodRevision(pod) != proposedRevisions[pod.Name] {
331335
return recreatePolicy, specUpdatePolicy, nil
332336
}
333337

pkg/controller/instanceset/instance_util.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,14 +425,23 @@ func MergeNodeSelectorOnceAnnotation(its *workloads.InstanceSet, podToNodeMappin
425425
}
426426

427427
func buildInstancePodByTemplate(name string, template *instancetemplate.InstanceTemplateExt, parent *workloads.InstanceSet, revision string) (*corev1.Pod, error) {
428+
injectNewServiceAccount := func(template *corev1.PodTemplateSpec) {
429+
newSAName, ok := parent.Annotations[constant.ProposedServiceAccountNameAnnotationKey]
430+
if ok {
431+
template.Spec.ServiceAccountName = newSAName
432+
}
433+
}
434+
428435
// 1. build a pod from template
429436
var err error
430437
if len(revision) == 0 {
431-
revision, err = buildInstanceTemplateRevision(&template.PodTemplateSpec, parent)
438+
revision, err = buildInstanceTemplateRevision(&template.PodTemplateSpec, parent, injectNewServiceAccount)
432439
if err != nil {
433440
return nil, err
434441
}
435442
}
443+
podTemplate := template.PodTemplateSpec.DeepCopy()
444+
injectNewServiceAccount(podTemplate)
436445
labels := getMatchLabels(parent.Name)
437446
pod := builder.NewPodBuilder(parent.Namespace, name).
438447
AddAnnotationsInMap(template.Annotations).
@@ -442,7 +451,7 @@ func buildInstancePodByTemplate(name string, template *instancetemplate.Instance
442451
AddLabels(instancetemplate.TemplateNameLabelKey, template.Name). // TODO: remove this label later
443452
AddLabels(constant.KBAppInstanceTemplateLabelKey, template.Name).
444453
AddControllerRevisionHashLabel(revision).
445-
SetPodSpec(*template.Spec.DeepCopy()).
454+
SetPodSpec(podTemplate.Spec).
446455
GetObject()
447456
// Set these immutable fields only on initial Pod creation, not updates.
448457
pod.Spec.Hostname = pod.Name
@@ -612,8 +621,12 @@ func copyAndMerge(oldObj, newObj client.Object) client.Object {
612621
}
613622
}
614623

615-
func buildInstanceTemplateRevision(template *corev1.PodTemplateSpec, parent *workloads.InstanceSet) (string, error) {
616-
podTemplate := filterInPlaceFields(template)
624+
func buildInstanceTemplateRevision(template *corev1.PodTemplateSpec, parent *workloads.InstanceSet, mutateTemplateFn func(template *corev1.PodTemplateSpec)) (string, error) {
625+
templateCopy := template.DeepCopy()
626+
if mutateTemplateFn != nil {
627+
mutateTemplateFn(templateCopy)
628+
}
629+
podTemplate := filterInPlaceFields(templateCopy)
617630
its := builder.NewInstanceSetBuilder(parent.Namespace, parent.Name).
618631
SetUID(parent.UID).
619632
AddAnnotationsInMap(parent.Annotations).

pkg/controller/instanceset/reconciler_instance_alignment.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,6 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (
143143
return kubebuilderx.Continue, err
144144
}
145145

146-
// HACK: inject new serviceaccount name if possible
147-
if its.Annotations != nil {
148-
newName, ok := its.Annotations[constant.ProposedServiceAccountNameAnnotationKey]
149-
if ok {
150-
its.Annotations[constant.ServiceAccountInUseAnnotationKey] = newName
151-
newPod.Spec.ServiceAccountName = newName
152-
}
153-
}
154-
155146
if err := tree.Add(newPod); err != nil {
156147
return kubebuilderx.Continue, err
157148
}

pkg/controller/instanceset/reconciler_revision_update.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"sigs.k8s.io/controller-runtime/pkg/client"
2828

2929
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1"
30+
"github.com/apecloud/kubeblocks/pkg/constant"
3031
"github.com/apecloud/kubeblocks/pkg/controller/instancetemplate"
3132
"github.com/apecloud/kubeblocks/pkg/controller/kubebuilderx"
3233
"github.com/apecloud/kubeblocks/pkg/controller/model"
@@ -74,12 +75,26 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kub
7475

7576
// build instance revision list from instance templates
7677
var instanceRevisionList []instanceRevision
78+
proposedRevisions := make(map[string]string)
7779
for instanceName, templateExt := range nameMap {
78-
revision, err := buildInstanceTemplateRevision(&templateExt.PodTemplateSpec, its)
80+
updatedRevision, err := buildInstanceTemplateRevision(&templateExt.PodTemplateSpec, its, nil)
7981
if err != nil {
8082
return kubebuilderx.Continue, err
8183
}
82-
instanceRevisionList = append(instanceRevisionList, instanceRevision{name: instanceName, revision: revision})
84+
85+
proposedRevision, err := buildInstanceTemplateRevision(&templateExt.PodTemplateSpec, its, func(template *corev1.PodTemplateSpec) {
86+
newSAName, ok := its.Annotations[constant.ProposedServiceAccountNameAnnotationKey]
87+
if ok {
88+
template.Spec.ServiceAccountName = newSAName
89+
}
90+
})
91+
if err != nil {
92+
return kubebuilderx.Continue, err
93+
}
94+
if proposedRevision != updatedRevision {
95+
proposedRevisions[instanceName] = proposedRevision
96+
}
97+
instanceRevisionList = append(instanceRevisionList, instanceRevision{name: instanceName, revision: updatedRevision})
8398
}
8499
updatedRevisions := make(map[string]string, len(instanceRevisionList))
85100
for _, r := range instanceRevisionList {
@@ -92,6 +107,11 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kub
92107
return kubebuilderx.Continue, err
93108
}
94109
its.Status.UpdateRevisions = revisions
110+
proposedRevisions, err = buildRevisions(proposedRevisions)
111+
if err != nil {
112+
return kubebuilderx.Continue, err
113+
}
114+
its.Status.ProposedRevisions = proposedRevisions
95115
updateRevision := ""
96116
if len(instanceRevisionList) > 0 {
97117
updateRevision = instanceRevisionList[len(instanceRevisionList)-1].revision

pkg/controller/instanceset/reconciler_status.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,28 @@ func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilder
191191
if its.Spec.MinReadySeconds > 0 && availableReplicas != readyReplicas {
192192
return kubebuilderx.RetryAfter(time.Second), nil
193193
}
194+
195+
// serviceaccount name migration process
196+
proposedRevisions, err := GetRevisions(its.Status.ProposedRevisions)
197+
if err != nil {
198+
return kubebuilderx.Continue, err
199+
}
200+
201+
updateDone := true
202+
for podName, revision := range proposedRevisions {
203+
if currentRevisions[podName] != revision {
204+
updateDone = false
205+
break
206+
}
207+
}
208+
if updateDone {
209+
_, ok1 := its.Annotations[constant.ServiceAccountInUseAnnotationKey]
210+
proposedSA, ok2 := its.Annotations[constant.ProposedServiceAccountNameAnnotationKey]
211+
if !ok1 && ok2 {
212+
its.Annotations[constant.ServiceAccountInUseAnnotationKey] = proposedSA
213+
}
214+
}
215+
194216
return kubebuilderx.Continue, nil
195217
}
196218

0 commit comments

Comments
 (0)