Skip to content

Commit e55bae9

Browse files
committed
feat: add deployment mode switching for QueryNode (#298)
- Added DeployMode field to MilvusQueryNode struct to support OneDeployMode and TwoDeployMode - Modified DeployControllerImpl to reconcile QueryNode deployment mode based on configuration - Implemented ChangeToOneDeployMode and ChangeToTwoDeployMode in DeployControllerBizImpl - Updated test cases in deploy_ctrl_test.go to cover deployment mode switching
1 parent 5c622a5 commit e55bae9

File tree

5 files changed

+736
-27
lines changed

5 files changed

+736
-27
lines changed

apis/milvus.io/v1beta1/components_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ type Component struct {
264264

265265
type MilvusQueryNode struct {
266266
Component `json:",inline"`
267+
// +kubebuilder:validation:Enum=OneDeployMode;TwoDeployMode
268+
// +kubebuilder:default:=TwoDeployMode
269+
// +kubebuilder:validation:Optional
270+
DeployMode string `json:"deployMode,omitempty"`
267271
}
268272

269273
type MilvusDataNode struct {

pkg/controllers/deploy_ctrl.go

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,48 @@ func (c *DeployControllerImpl) Reconcile(ctx context.Context, mc v1beta1.Milvus,
5050
return errors.Wrap(err, "update milvus rolling mode status")
5151
}
5252
biz := c.bizFactory.GetBiz(component)
53+
// Reconcile QueryNode deploy mode
54+
if component == QueryNode {
55+
// Parse and compare deploy mode
56+
configuredDeployMode, err := parseDeployMode(mc.Spec.Com.QueryNode)
57+
if err != nil {
58+
return errors.Wrap(err, "parse deploy mode")
59+
}
60+
currentDeployMode, err := biz.CheckDeployMode(ctx, mc)
61+
if err != nil {
62+
return errors.Wrap(err, "check deploy mode")
63+
}
64+
if configuredDeployMode != currentDeployMode {
65+
logger.Info("deploy mode mismatch detected", "configured", configuredDeployMode, "current", currentDeployMode)
66+
if configuredDeployMode == v1beta1.OneDeployMode {
67+
err = biz.ChangeToOneDeployMode(ctx, mc)
68+
if err != nil {
69+
return errors.Wrap(err, "change to OneDeployMode")
70+
}
71+
} else if configuredDeployMode == v1beta1.TwoDeployMode {
72+
err = biz.ChangeToTwoDeployMode(ctx, mc)
73+
if err != nil {
74+
return errors.Wrap(err, "change to TwoDeployMode")
75+
}
76+
}
77+
err = biz.MarkDeployModeChanging(ctx, mc, true)
78+
if err != nil {
79+
return err
80+
}
81+
return errors.New("requeue after deploy mode change")
82+
}
83+
err = biz.MarkDeployModeChanging(ctx, mc, false)
84+
if err != nil {
85+
return err
86+
}
87+
return c.handleTwoDeployMode(ctx, mc, biz)
88+
}
89+
90+
err = c.rollingModeStatusUpdater.Update(ctx, &mc)
91+
if err != nil {
92+
return errors.Wrap(err, "update milvus rolling mode status")
93+
}
94+
biz = c.bizFactory.GetBiz(component)
5395
deployMode, err := biz.CheckDeployMode(ctx, mc)
5496
if err != nil {
5597
return errors.Wrap(err, "check deploy mode")
@@ -137,6 +179,7 @@ type DeployControllerBiz interface {
137179
type DeployModeChanger interface {
138180
MarkDeployModeChanging(ctx context.Context, mc v1beta1.Milvus, changing bool) error
139181
ChangeToTwoDeployMode(ctx context.Context, mc v1beta1.Milvus) error
182+
ChangeToOneDeployMode(ctx context.Context, mc v1beta1.Milvus) error
140183
}
141184

142185
var _ DeployControllerBiz = &DeployControllerBizImpl{}
@@ -168,7 +211,28 @@ func (c *DeployControllerBizImpl) CheckDeployMode(ctx context.Context, mc v1beta
168211
}
169212
fallthrough
170213
default:
171-
// check in cluster
214+
// continue
215+
}
216+
// Check QueryNode cluster state
217+
if c.component == QueryNode {
218+
mode, err := c.checkDeployModeInCluster(ctx, mc)
219+
if err == nil {
220+
return mode, nil
221+
}
222+
if kerrors.IsNotFound(err) {
223+
return v1beta1.TwoDeployMode, nil
224+
}
225+
if err != nil {
226+
return v1beta1.DeployModeUnknown, errors.Wrap(err, "check deploy mode in cluster")
227+
}
228+
}
229+
// Prioritize configured QueryNode mode
230+
if c.component == QueryNode && mc.Spec.Com.QueryNode != nil && mc.Spec.Com.QueryNode.DeployMode != "" {
231+
configuredDeployMode, err := parseDeployMode(mc.Spec.Com.QueryNode)
232+
if err != nil {
233+
return v1beta1.DeployModeUnknown, errors.Wrap(err, "parse deploy mode in CheckDeployMode")
234+
}
235+
return configuredDeployMode, nil
172236
}
173237
if v1beta1.Labels().IsChangingMode(mc, c.component.Name) {
174238
return v1beta1.OneDeployMode, nil
@@ -335,3 +399,98 @@ func (c *DeployControllerBizImpl) HandleManualMode(ctx context.Context, mc v1bet
335399
}
336400
return nil
337401
}
402+
403+
// ParseDeployMode converts QueryNode DeployMode to ComponentDeployMode
404+
func parseDeployMode(queryNode *v1beta1.MilvusQueryNode) (v1beta1.ComponentDeployMode, error) {
405+
if queryNode == nil || queryNode.DeployMode == "" {
406+
return v1beta1.TwoDeployMode, nil
407+
}
408+
switch queryNode.DeployMode {
409+
case "OneDeployMode":
410+
return v1beta1.OneDeployMode, nil
411+
case "TwoDeployMode":
412+
return v1beta1.TwoDeployMode, nil
413+
default:
414+
return v1beta1.DeployModeUnknown, errors.Errorf("invalid DeployMode: %s, must be OneDeployMode or TwoDeployMode", queryNode.DeployMode)
415+
}
416+
}
417+
418+
// ChangeToOneDeployMode switches QueryNode to single deployment mode
419+
func (c *DeployControllerBizImpl) ChangeToOneDeployMode(ctx context.Context, mc v1beta1.Milvus) error {
420+
if c.component != QueryNode {
421+
return nil
422+
}
423+
currentDeploy, lastDeploy, err := c.util.GetDeploys(ctx, mc)
424+
if err != nil {
425+
return errors.Wrap(err, "get querynode deploys for ChangeToOneDeployMode")
426+
}
427+
if currentDeploy != nil && lastDeploy != nil {
428+
lastDeploy.Spec.Replicas = int32Ptr(0)
429+
err = c.cli.Update(ctx, lastDeploy)
430+
if err != nil {
431+
return errors.Wrap(err, "scale down last deployment")
432+
}
433+
err = c.cli.Delete(ctx, lastDeploy)
434+
if err != nil && !kerrors.IsNotFound(err) {
435+
return errors.Wrap(err, "delete last deployment")
436+
}
437+
}
438+
if currentDeploy != nil {
439+
err = c.util.MarkMilvusComponentGroupId(ctx, mc, c.component, 0)
440+
if err != nil {
441+
return errors.Wrap(err, "mark group id to 0")
442+
}
443+
}
444+
return nil
445+
}
446+
447+
// ChangeToTwoDeployMode switches QueryNode to dual deployment mode
448+
func (c *DeployControllerBizImpl) ChangeToTwoDeployMode(ctx context.Context, mc v1beta1.Milvus) error {
449+
if c.component != QueryNode {
450+
return nil
451+
}
452+
currentDeploy, lastDeploy, err := c.util.GetDeploys(ctx, mc)
453+
if err != nil {
454+
return errors.Wrap(err, "get querynode deploys for ChangeToTwoDeployMode")
455+
}
456+
if currentDeploy != nil && lastDeploy != nil {
457+
return nil
458+
}
459+
if currentDeploy != nil && lastDeploy == nil {
460+
err = c.util.CreateDeploy(ctx, mc, nil, 1)
461+
if err != nil {
462+
return errors.Wrap(err, "create second deployment")
463+
}
464+
currentDeploy.Spec.Replicas = int32Ptr(0)
465+
err = c.cli.Update(ctx, currentDeploy)
466+
if err != nil {
467+
return errors.Wrap(err, "scale down current deployment")
468+
}
469+
}
470+
return nil
471+
}
472+
473+
// handleTwoDeployMode manages QueryNode in dual deployment mode
474+
func (c *DeployControllerImpl) handleTwoDeployMode(ctx context.Context, mc v1beta1.Milvus, biz DeployControllerBiz) error {
475+
if err := biz.HandleCreate(ctx, mc); err != nil {
476+
return errors.Wrap(err, "handle create")
477+
}
478+
if biz.IsPaused(ctx, mc) {
479+
return nil
480+
}
481+
if mc.Spec.Com.EnableManualMode {
482+
return biz.HandleManualMode(ctx, mc)
483+
}
484+
if ReplicasValue(QueryNode.GetReplicas(mc.Spec)) == 0 {
485+
return biz.HandleStop(ctx, mc)
486+
}
487+
err := biz.HandleRolling(ctx, mc)
488+
if err != nil {
489+
return errors.Wrap(err, "handle rolling")
490+
}
491+
err = biz.HandleScaling(ctx, mc)
492+
if err != nil {
493+
return errors.Wrap(err, "handle scaling")
494+
}
495+
return nil
496+
}

0 commit comments

Comments
 (0)