Skip to content

Commit

Permalink
feat: support additional services for blue-green
Browse files Browse the repository at this point in the history
Add support for additional preview and active services for the BlueGreen
strategy.

Signed-off-by: d3adb5 <me@d3adb5.net>
  • Loading branch information
d3adb5 committed Feb 7, 2025
1 parent 44eee2e commit 01b48af
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 0 deletions.
8 changes: 8 additions & 0 deletions manifests/crds/rollout-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ spec:
type: object
activeService:
type: string
additionalActiveServices:
items:
type: string
type: array
additionalPreviewServices:
items:
type: string
type: array
antiAffinity:
properties:
preferredDuringSchedulingIgnoredDuringExecution:
Expand Down
14 changes: 14 additions & 0 deletions pkg/apiclient/rollout/rollout.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,20 @@
"type": "integer",
"format": "int32",
"title": "AbortScaleDownDelaySeconds adds a delay in second before scaling down the preview replicaset\nif update is aborted. 0 means not to scale down.\nDefault is 30 second\n+optional"
},
"additionalActiveServices": {
"type": "array",
"items": {
"type": "string"
},
"title": "AdditionalActiveServices is a list of additional Services that the\nrollout modifies during reconciliation. These will always be updated\nafter the primary active Service.\n+optional"
},
"additionalPreviewServices": {
"type": "array",
"items": {
"type": "string"
},
"title": "AdditionalPreviewServices is a list of additional Services that the\nrollout modifies during reconciliation. These will always be updated\nafter the primary one.\n+optional"
}
},
"title": "BlueGreenStrategy defines parameters for Blue Green deployment"
Expand Down
12 changes: 12 additions & 0 deletions pkg/apis/rollouts/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,18 @@ type BlueGreenStrategy struct {
// Default is 30 second
// +optional
AbortScaleDownDelaySeconds *int32 `json:"abortScaleDownDelaySeconds,omitempty" protobuf:"varint,14,opt,name=abortScaleDownDelaySeconds"`

// AdditionalActiveServices is a list of additional Services that the
// rollout modifies during reconciliation. These will always be updated
// after the primary active Service.
// +optional
AdditionalActiveServices []string `json:"additionalActiveServices,omitempty" protobuf:"bytes,15,opt,name=additionalActiveServices"`

// AdditionalPreviewServices is a list of additional Services that the
// rollout modifies during reconciliation. These will always be updated
// after the primary one.
// +optional
AdditionalPreviewServices []string `json:"additionalPreviewServices,omitempty" protobuf:"bytes,16,opt,name=additionalPreviewServices"`
}

// AntiAffinity defines which inter-pod scheduling rule to use for anti-affinity injection
Expand Down
18 changes: 18 additions & 0 deletions rollout/bluegreen.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func (c *rolloutContext) rolloutBlueGreen() error {
if err != nil {
return err
}
additionalPreviewSvcs, additionalActiveSvcs, err := c.getAdditionalPreviewAndActiveServices()
if err != nil {
return err
}
c.newRS, err = c.getAllReplicaSetsAndSyncRevision()
if err != nil {
return fmt.Errorf("failed to getAllReplicaSetsAndSyncRevision in rolloutBlueGreen create true: %w", err)
Expand All @@ -32,6 +36,13 @@ func (c *rolloutContext) rolloutBlueGreen() error {
return err
}

for _, svc := range additionalPreviewSvcs {
err = c.reconcilePreviewService(svc)
if err != nil {
return err
}
}

if replicasetutil.CheckPodSpecChange(c.rollout, c.newRS) {
return c.syncRolloutStatusBlueGreen(previewSvc, activeSvc)
}
Expand All @@ -53,6 +64,13 @@ func (c *rolloutContext) rolloutBlueGreen() error {
return err
}

for _, svc := range additionalActiveSvcs {
err = c.reconcileActiveService(svc)
if err != nil {
return err
}
}

err = c.awsVerifyTargetGroups(activeSvc)
if err != nil {
return err
Expand Down
41 changes: 41 additions & 0 deletions rollout/bluegreen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,47 @@ func TestBlueGreenSetPreviewService(t *testing.T) {
f.verifyPatchedService(servicePatch, rsPodHash, "")
}

// TestBlueGreenSetAdditionalPreviewServices ensures all preview services are set to the desired ReplicaSet
func TestBlueGreenSetAdditionalPreviewServices(t *testing.T) {
previewServiceNames := []string{"preview", "additional1", "additional2", "additional3"}
previewServices := make([]*corev1.Service, len(previewServiceNames))
f := newFixture(t)
defer f.Close()

r := newBlueGreenRollout("foo", 1, nil, "active", previewServiceNames[0])
r.Spec.Strategy.BlueGreen.AdditionalPreviewServices = previewServiceNames[1:]
f.rolloutLister = append(f.rolloutLister, r)
f.objects = append(f.objects, r)

rs := newReplicaSetWithStatus(r, 1, 1)
rsPodHash := rs.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]
f.kubeobjects = append(f.kubeobjects, rs)
f.replicaSetLister = append(f.replicaSetLister, rs)

selector := map[string]string{v1alpha1.DefaultRolloutUniqueLabelKey: rsPodHash}
activeSvc := newService("active", 80, selector, r)
f.kubeobjects = append(f.kubeobjects, activeSvc)
for i, svcName := range previewServiceNames {
previewServices[i] = newService(svcName, 80, nil, r)
f.kubeobjects = append(f.kubeobjects, previewServices[i])
}

f.serviceLister = append(f.serviceLister, previewServices[0], activeSvc)
f.serviceLister = append(f.serviceLister, previewServices[1:]...)

servicePatches := make([]int, len(previewServices))
for i, svc := range previewServices {
servicePatches[i] = f.expectPatchServiceAction(svc, rsPodHash)
}

f.expectPatchRolloutAction(r)
f.run(getKey(r, t))

for _, patch := range servicePatches {
f.verifyPatchedService(patch, rsPodHash, "")
}
}

// TestBlueGreenProgressDeadlineAbort tests aborting an update if it is timeout
func TestBlueGreenProgressDeadlineAbort(t *testing.T) {
// Two cases to be tested:
Expand Down
26 changes: 26 additions & 0 deletions rollout/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,32 @@ func (c *rolloutContext) getPreviewAndActiveServices() (*corev1.Service, *corev1
return previewSvc, activeSvc, nil
}

func (c *rolloutContext) makeServicesList(svcNames []string) ([]*corev1.Service, error) {
svcs := make([]*corev1.Service, len(svcNames))
for i, svcName := range svcNames {
svc, err := c.servicesLister.Services(c.rollout.Namespace).Get(svcName)
if err != nil {
return nil, err
}
svcs[i] = svc
}
return svcs, nil
}

func (c *rolloutContext) getAdditionalPreviewAndActiveServices() ([]*corev1.Service, []*corev1.Service, error) {
previewSvcs, err := c.makeServicesList(c.rollout.Spec.Strategy.BlueGreen.AdditionalPreviewServices)
if err != nil {
return nil, nil, err
}

activeSvcs, err := c.makeServicesList(c.rollout.Spec.Strategy.BlueGreen.AdditionalActiveServices)
if err != nil {
return nil, nil, err
}

return previewSvcs, activeSvcs, nil
}

func (c *rolloutContext) reconcilePingAndPongService() error {
if trafficrouting.IsPingPongEnabled(c.rollout) && !rolloututils.IsFullyPromoted(c.rollout) {
_, canaryService := trafficrouting.GetStableAndCanaryServices(c.rollout, true)
Expand Down
12 changes: 12 additions & 0 deletions ui/src/models/rollout/generated/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,18 @@ export interface GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1BlueGreenSt
* @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1BlueGreenStrategy
*/
abortScaleDownDelaySeconds?: number;
/**
*
* @type {Array<string>}
* @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1BlueGreenStrategy
*/
additionalActiveServices?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1BlueGreenStrategy
*/
additionalPreviewServices?: Array<string>;
}
/**
*
Expand Down

0 comments on commit 01b48af

Please sign in to comment.