Skip to content

Commit

Permalink
adding snow and cluster api upgrade rollout strategy (#7317)
Browse files Browse the repository at this point in the history
  • Loading branch information
raymond-zhang00 authored Jan 19, 2024
1 parent 003a554 commit 01c65c0
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 188 deletions.
4 changes: 4 additions & 0 deletions pkg/clusterapi/apibuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ func KubeadmControlPlane(clusterSpec *cluster.Spec, infrastructureObject APIObje
setStackedEtcdConfigInKubeadmControlPlane(kcp, bundle.KubeDistro.Etcd)
}

SetUpgradeRolloutStrategyInKubeadmControlPlane(kcp, clusterSpec.Cluster.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy)

return kcp, nil
}

Expand Down Expand Up @@ -291,6 +293,8 @@ func MachineDeployment(clusterSpec *cluster.Spec, workerNodeGroupConfig anywhere
},
}

SetUpgradeRolloutStrategyInMachineDeployment(md, workerNodeGroupConfig.UpgradeRolloutStrategy)

ConfigureAutoscalingInMachineDeployment(md, workerNodeGroupConfig.AutoScalingConfiguration)

return md
Expand Down
24 changes: 20 additions & 4 deletions pkg/clusterapi/apibuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,11 @@ func TestCluster(t *testing.T) {
tt.Expect(got).To(Equal(want))
}

func wantKubeadmControlPlane() *controlplanev1.KubeadmControlPlane {
type kubeadmControlPlaneOpt func(k *controlplanev1.KubeadmControlPlane)

func wantKubeadmControlPlane(opts ...kubeadmControlPlaneOpt) *controlplanev1.KubeadmControlPlane {
replicas := int32(3)
return &controlplanev1.KubeadmControlPlane{
kcp := &controlplanev1.KubeadmControlPlane{
TypeMeta: metav1.TypeMeta{
APIVersion: "controlplane.cluster.x-k8s.io/v1beta1",
Kind: "KubeadmControlPlane",
Expand Down Expand Up @@ -363,6 +365,12 @@ func wantKubeadmControlPlane() *controlplanev1.KubeadmControlPlane {
Version: "v1.21.5-eks-1-21-9",
},
}

for _, opt := range opts {
opt(kcp)
}

return kcp
}

func TestKubeadmControlPlane(t *testing.T) {
Expand Down Expand Up @@ -429,10 +437,12 @@ func TestKubeadmConfigTemplate(t *testing.T) {
tt.Expect(got).To(Equal(want))
}

func wantMachineDeployment() *clusterv1.MachineDeployment {
type machineDeploymentOpt func(m *clusterv1.MachineDeployment)

func wantMachineDeployment(opts ...machineDeploymentOpt) *clusterv1.MachineDeployment {
replicas := int32(3)
version := "v1.21.5-eks-1-21-9"
return &clusterv1.MachineDeployment{
md := &clusterv1.MachineDeployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "cluster.x-k8s.io/v1beta1",
Kind: "MachineDeployment",
Expand Down Expand Up @@ -478,6 +488,12 @@ func wantMachineDeployment() *clusterv1.MachineDeployment {
Replicas: &replicas,
},
}

for _, opt := range opts {
opt(md)
}

return md
}

func TestMachineDeployment(t *testing.T) {
Expand Down
37 changes: 37 additions & 0 deletions pkg/clusterapi/rollout_strategy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package clusterapi

import (
"k8s.io/apimachinery/pkg/util/intstr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"

anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
)

// SetUpgradeRolloutStrategyInKubeadmControlPlane updates the kubeadm control plane with the upgrade rollout strategy defined in an eksa cluster.
func SetUpgradeRolloutStrategyInKubeadmControlPlane(kcp *controlplanev1.KubeadmControlPlane, rolloutStrategy *anywherev1.ControlPlaneUpgradeRolloutStrategy) {
if rolloutStrategy != nil {
maxSurge := intstr.FromInt(rolloutStrategy.RollingUpdate.MaxSurge)
kcp.Spec.RolloutStrategy = &controlplanev1.RolloutStrategy{
Type: controlplanev1.RollingUpdateStrategyType,
RollingUpdate: &controlplanev1.RollingUpdate{
MaxSurge: &maxSurge,
},
}
}
}

// SetUpgradeRolloutStrategyInMachineDeployment updates the machine deployment with the upgrade rollout strategy defined in an eksa cluster.
func SetUpgradeRolloutStrategyInMachineDeployment(md *clusterv1.MachineDeployment, rolloutStrategy *anywherev1.WorkerNodesUpgradeRolloutStrategy) {
if rolloutStrategy != nil {
maxSurge := intstr.FromInt(rolloutStrategy.RollingUpdate.MaxSurge)
maxUnavailable := intstr.FromInt(rolloutStrategy.RollingUpdate.MaxUnavailable)
md.Spec.Strategy = &clusterv1.MachineDeploymentStrategy{
Type: clusterv1.RollingUpdateMachineDeploymentStrategyType,
RollingUpdate: &clusterv1.MachineRollingUpdateDeployment{
MaxSurge: &maxSurge,
MaxUnavailable: &maxUnavailable,
},
}
}
}
92 changes: 92 additions & 0 deletions pkg/clusterapi/rollout_strategy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package clusterapi_test

import (
"testing"

"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/util/intstr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"

anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
"github.com/aws/eks-anywhere/pkg/clusterapi"
)

func TestSetUpgradeRolloutStrategyInKubeadmControlPlane(t *testing.T) {
tests := []struct {
name string
rolloutStrategy *anywherev1.ControlPlaneUpgradeRolloutStrategy
want *controlplanev1.KubeadmControlPlane
}{
{
name: "no upgrade rollout strategy",
rolloutStrategy: nil,
want: wantKubeadmControlPlane(),
},
{
name: "with maxSurge",
rolloutStrategy: &anywherev1.ControlPlaneUpgradeRolloutStrategy{
RollingUpdate: anywherev1.ControlPlaneRollingUpdateParams{
MaxSurge: 1,
},
},
want: wantKubeadmControlPlane(func(k *controlplanev1.KubeadmControlPlane) {
maxSurge := intstr.FromInt(1)
k.Spec.RolloutStrategy = &controlplanev1.RolloutStrategy{
Type: controlplanev1.RollingUpdateStrategyType,
RollingUpdate: &controlplanev1.RollingUpdate{
MaxSurge: &maxSurge,
},
}
}),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
kcp := wantKubeadmControlPlane()
clusterapi.SetUpgradeRolloutStrategyInKubeadmControlPlane(kcp, tt.rolloutStrategy)
assert.Equal(t, tt.want, kcp)
})
}
}

func TestSetUpgradeRolloutStrategyInMachineDeployment(t *testing.T) {
tests := []struct {
name string
rolloutStrategy *anywherev1.WorkerNodesUpgradeRolloutStrategy
want *clusterv1.MachineDeployment
}{
{
name: "no upgrade rollout strategy",
rolloutStrategy: nil,
want: wantMachineDeployment(),
},
{
name: "with maxSurge and maxUnavailable",
rolloutStrategy: &anywherev1.WorkerNodesUpgradeRolloutStrategy{
RollingUpdate: anywherev1.WorkerNodesRollingUpdateParams{
MaxSurge: 1,
MaxUnavailable: 0,
},
},
want: wantMachineDeployment(func(m *clusterv1.MachineDeployment) {
maxSurge := intstr.FromInt(1)
maxUnavailable := intstr.FromInt(0)
m.Spec.Strategy = &clusterv1.MachineDeploymentStrategy{
Type: clusterv1.RollingUpdateMachineDeploymentStrategyType,
RollingUpdate: &clusterv1.MachineRollingUpdateDeployment{
MaxSurge: &maxSurge,
MaxUnavailable: &maxUnavailable,
},
}
}),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
md := wantMachineDeployment()
clusterapi.SetUpgradeRolloutStrategyInMachineDeployment(md, tt.rolloutStrategy)
assert.Equal(t, tt.want, md)
})
}
}
17 changes: 17 additions & 0 deletions pkg/providers/snow/apibuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
. "github.com/onsi/gomega"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
Expand Down Expand Up @@ -105,6 +106,7 @@ func TestCAPICluster(t *testing.T) {

func wantKubeadmControlPlane() *controlplanev1.KubeadmControlPlane {
wantReplicas := int32(3)
wantMaxSurge := intstr.FromInt(1)
return &controlplanev1.KubeadmControlPlane{
TypeMeta: metav1.TypeMeta{
APIVersion: "controlplane.cluster.x-k8s.io/v1beta1",
Expand Down Expand Up @@ -187,6 +189,12 @@ func wantKubeadmControlPlane() *controlplanev1.KubeadmControlPlane {
},
},
},
RolloutStrategy: &controlplanev1.RolloutStrategy{
Type: controlplanev1.RollingUpdateStrategyType,
RollingUpdate: &controlplanev1.RollingUpdate{
MaxSurge: &wantMaxSurge,
},
},
Replicas: &wantReplicas,
Version: "v1.21.5-eks-1-21-9",
},
Expand Down Expand Up @@ -765,6 +773,8 @@ func TestKubeadmConfigTemplate(t *testing.T) {
func wantMachineDeployment() *clusterv1.MachineDeployment {
wantVersion := "v1.21.5-eks-1-21-9"
wantReplicas := int32(3)
wantMaxUnavailable := intstr.FromInt(0)
wantMaxSurge := intstr.FromInt(1)
return &clusterv1.MachineDeployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "cluster.x-k8s.io/v1beta1",
Expand Down Expand Up @@ -809,6 +819,13 @@ func wantMachineDeployment() *clusterv1.MachineDeployment {
},
},
Replicas: &wantReplicas,
Strategy: &clusterv1.MachineDeploymentStrategy{
RollingUpdate: &clusterv1.MachineRollingUpdateDeployment{
MaxUnavailable: &wantMaxUnavailable,
MaxSurge: &wantMaxSurge,
},
Type: clusterv1.RollingUpdateMachineDeploymentStrategyType,
},
},
}
}
Expand Down
21 changes: 0 additions & 21 deletions pkg/providers/snow/snow.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ func (p *SnowProvider) Name() string {
}

func (p *SnowProvider) SetupAndValidateCreateCluster(ctx context.Context, clusterSpec *cluster.Spec) error {
if err := p.validateUpgradeRolloutStrategy(clusterSpec); err != nil {
return fmt.Errorf("failed setup and validations: %v", err)
}
if err := p.configManager.SetDefaultsAndValidate(ctx, clusterSpec.Config); err != nil {
return fmt.Errorf("setting defaults and validate snow config: %v", err)
}
Expand All @@ -87,19 +84,13 @@ func (p *SnowProvider) SetupAndValidateCreateCluster(ctx context.Context, cluste
}

func (p *SnowProvider) SetupAndValidateUpgradeCluster(ctx context.Context, cluster *types.Cluster, clusterSpec *cluster.Spec, _ *cluster.Spec) error {
if err := p.validateUpgradeRolloutStrategy(clusterSpec); err != nil {
return fmt.Errorf("failed setup and validations: %v", err)
}
if err := p.configManager.SetDefaultsAndValidate(ctx, clusterSpec.Config); err != nil {
return fmt.Errorf("setting defaults and validate snow config: %v", err)
}
return nil
}

func (p *SnowProvider) SetupAndValidateDeleteCluster(ctx context.Context, _ *types.Cluster, clusterSpec *cluster.Spec) error {
if err := p.validateUpgradeRolloutStrategy(clusterSpec); err != nil {
return fmt.Errorf("failed setup and validations: %v", err)
}
if err := SetupEksaCredentialsSecret(clusterSpec.Config); err != nil {
return fmt.Errorf("setting up credentials: %v", err)
}
Expand Down Expand Up @@ -318,18 +309,6 @@ func namespaceOrDefault(obj client.Object) string {
return ns
}

func (p *SnowProvider) validateUpgradeRolloutStrategy(clusterSpec *cluster.Spec) error {
if clusterSpec.Cluster.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy != nil {
return fmt.Errorf("Upgrade rollout strategy customization is not supported for snow provider")
}
for _, workerNodeGroupConfiguration := range clusterSpec.Cluster.Spec.WorkerNodeGroupConfigurations {
if workerNodeGroupConfiguration.UpgradeRolloutStrategy != nil {
return fmt.Errorf("Upgrade rollout strategy customization is not supported for snow provider")
}
}
return nil
}

// UpgradeNeeded compares the new snow version bundle and objects with the existing ones in the cluster and decides whether
// to trigger a cluster upgrade or not.
// TODO: revert the change once cluster.BuildSpec is used in cluster_manager to replace the deprecated cluster.BuildSpecForCluster
Expand Down
Loading

0 comments on commit 01c65c0

Please sign in to comment.