Skip to content

Commit

Permalink
support for auto upgrade channel
Browse files Browse the repository at this point in the history
  • Loading branch information
LochanRn committed Oct 13, 2023
1 parent 30d08b2 commit fa76c24
Show file tree
Hide file tree
Showing 17 changed files with 900 additions and 13 deletions.
66 changes: 66 additions & 0 deletions api/v1beta1/azuremanagedcontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,50 @@ const (
PrivateDNSZoneModeNone string = "None"
)

// UpgradeChannel - For more information see setting the AKS cluster auto-upgrade channel [https://docs.microsoft.com/azure/aks/upgrade-cluster#set-auto-upgrade-channel].
type UpgradeChannel string

const (
// UpgradeChannelNodeImage - Automatically upgrade the node image to the latest version available. Consider using nodeOSUpgradeChannel
// instead as that allows you to configure node OS patching separate from Kubernetes version patching

Check failure on line 42 in api/v1beta1/azuremanagedcontrolplane_types.go

View workflow job for this annotation

GitHub Actions / coverage

Comment should end in a period (godot)
UpgradeChannelNodeImage UpgradeChannel = "node-image"
// UpgradeChannelNone - Disables auto-upgrades and keeps the cluster at its current version of Kubernetes.
UpgradeChannelNone UpgradeChannel = "none"
// UpgradeChannelPatch - Automatically upgrade the cluster to the latest supported patch version when it becomes available
// while keeping the minor version the same. For example, if a cluster is running version 1.17.7 and versions 1.17.9, 1.18.4,
// 1.18.6, and 1.19.1 are available, your cluster is upgraded to 1.17.9.
UpgradeChannelPatch UpgradeChannel = "patch"
// UpgradeChannelRapid - Automatically upgrade the cluster to the latest supported patch release on the latest supported minor
// version. In cases where the cluster is at a version of Kubernetes that is at an N-2 minor version where N is the latest
// supported minor version, the cluster first upgrades to the latest supported patch version on N-1 minor version. For example,
// if a cluster is running version 1.17.7 and versions 1.17.9, 1.18.4, 1.18.6, and 1.19.1 are available, your cluster first
// is upgraded to 1.18.6, then is upgraded to 1.19.1.
UpgradeChannelRapid UpgradeChannel = "rapid"
// UpgradeChannelStable - Automatically upgrade the cluster to the latest supported patch release on minor version N-1, where
// N is the latest supported minor version. For example, if a cluster is running version 1.17.7 and versions 1.17.9, 1.18.4,
// 1.18.6, and 1.19.1 are available, your cluster is upgraded to 1.18.6.
UpgradeChannelStable UpgradeChannel = "stable"
)

// NodeOSUpgradeChannel - Manner in which the OS on your nodes is updated. The default is NodeImage.
type NodeOSUpgradeChannel string

const (
// NodeOSUpgradeChannelNodeImage - AKS will update the nodes with a newly patched VHD containing security fixes and bugfixes
// on a weekly cadence. With the VHD update machines will be rolling reimaged to that VHD following maintenance windows and
// surge settings. No extra VHD cost is incurred when choosing this option as AKS hosts the images.
NodeOSUpgradeChannelNodeImage NodeOSUpgradeChannel = "NodeImage"
// NodeOSUpgradeChannelNone - No attempt to update your machines OS will be made either by OS or by rolling VHDs. This means
// you are responsible for your security updates

Check failure on line 71 in api/v1beta1/azuremanagedcontrolplane_types.go

View workflow job for this annotation

GitHub Actions / coverage

Comment should end in a period (godot)
NodeOSUpgradeChannelNone NodeOSUpgradeChannel = "None"
// NodeOSUpgradeChannelUnmanaged - OS updates will be applied automatically through the OS built-in patching infrastructure.
// Newly scaled in machines will be unpatched initially and will be patched at some point by the OS's infrastructure. Behavior
// of this option depends on the OS in question. Ubuntu and Mariner apply security patches through unattended upgrade roughly
// once a day around 06:00 UTC. Windows does not apply security patches automatically and so for them this option is equivalent
// to None till further notice

Check failure on line 77 in api/v1beta1/azuremanagedcontrolplane_types.go

View workflow job for this annotation

GitHub Actions / coverage

Comment should end in a period (godot)
NodeOSUpgradeChannelUnmanaged NodeOSUpgradeChannel = "Unmanaged"
)

// ManagedControlPlaneOutboundType enumerates the values for the managed control plane OutboundType.
type ManagedControlPlaneOutboundType string

Expand Down Expand Up @@ -221,6 +265,23 @@ type AzureManagedControlPlaneSpec struct {
// DisableLocalAccounts disables getting static credentials for this cluster when set. Expected to only be used for AAD clusters.
// +optional
DisableLocalAccounts *bool `json:"disableLocalAccounts,omitempty"`

// AutoUpgradeProfile - Profile of auto upgrade configuration.
// +optional
AutoUpgradeProfile *ManagedClusterAutoUpgradeProfile `json:"autoUpgradeProfile,omitempty"`
}

// ManagedClusterAutoUpgradeProfile - Auto upgrade profile for a managed cluster.
type ManagedClusterAutoUpgradeProfile struct {
// NodeOSUpgradeChannel is a manner in which the OS on your nodes is updated. The default is NodeImage. Possible values include: NodeImage,Unmanaged,None
// +kubebuilder:validation:Enum=NodeImage;Unmanaged;None
// +optional
NodeOSUpgradeChannel *NodeOSUpgradeChannel `json:"nodeOSUpgradeChannel,omitempty"`

// UpgradeChannel - upgrade channel for auto upgrade. Possible values include: "node-image","none","patch","rapid","stable"
// +kubebuilder:validation:Enum=node-image;none;patch;rapid;stable
// +optional
UpgradeChannel *UpgradeChannel `json:"upgradeChannel,omitempty"`
}

// HTTPProxyConfig is the HTTP proxy configuration for the cluster.
Expand Down Expand Up @@ -364,6 +425,11 @@ type ManagedControlPlaneSubnet struct {

// AzureManagedControlPlaneStatus defines the observed state of AzureManagedControlPlane.
type AzureManagedControlPlaneStatus struct {
// AutoUpgradeVersion is the Kubernetes version populated after autoupgrade based on the upgrade channel.
// +kubebuilder:validation:MinLength:=2
// +optional
AutoUpgradeVersion string `json:"autoUpgradeVersion,omitempty"`

// Ready is true when the provider resource is ready.
// +optional
Ready bool `json:"ready,omitempty"`
Expand Down
34 changes: 34 additions & 0 deletions api/v1beta1/azuremanagedcontrolplane_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/utils/ptr"
"sigs.k8s.io/cluster-api-provider-azure/feature"
"sigs.k8s.io/cluster-api-provider-azure/util/versions"
webhookutils "sigs.k8s.io/cluster-api-provider-azure/util/webhook"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
capifeature "sigs.k8s.io/cluster-api/feature"
Expand Down Expand Up @@ -256,6 +257,10 @@ func (mw *azureManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, o
allErrs = append(allErrs, errs...)
}

if errs := m.validateAutoUpgradeProfile(old); len(errs) > 0 {
allErrs = append(allErrs, errs...)
}

if errs := m.validateOIDCIssuerProfileUpdate(old); len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
Expand Down Expand Up @@ -492,6 +497,35 @@ func (m *AzureManagedControlPlane) validateManagedClusterNetwork(cli client.Clie
return nil
}

// validateAutoUpgradeProfile validates auto upgrade profile

Check failure on line 500 in api/v1beta1/azuremanagedcontrolplane_webhook.go

View workflow job for this annotation

GitHub Actions / coverage

Comment should end in a period (godot)
func (m *AzureManagedControlPlane) validateAutoUpgradeProfile(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
if old.Spec.AutoUpgradeProfile != nil && m.Spec.AutoUpgradeProfile == nil {
// Prevent AutoUpgradeProfile to be set to nil.
// unsetting the field is not allowed
allErrs = append(allErrs,
field.Invalid(
field.NewPath("Spec", "AutoUpgradeProfile"),
m.Spec.AutoUpgradeProfile,
"field cannot be set to nil, to disable auto upgrades set the channel to none."))
}

if hv, _ := versions.GetHigherK8sVersion(m.Spec.Version, old.Spec.Version); hv != m.Spec.Version {
allErrs = append(allErrs, field.Invalid(field.NewPath("Spec", "Version"),
m.Spec.Version, "field version cannot be downgraded"),
)
}

if old.Status.AutoUpgradeVersion != "" && m.Spec.Version != old.Spec.Version {
if hv, _ := versions.GetHigherK8sVersion(m.Spec.Version, old.Status.AutoUpgradeVersion); hv != m.Spec.Version {
allErrs = append(allErrs, field.Invalid(field.NewPath("Spec", "Version"),
m.Spec.Version, "version is auto-upgraded to "+old.Status.AutoUpgradeVersion+",cannot be downgraded"),
)
}
}
return allErrs
}

// validateAPIServerAccessProfileUpdate validates update to APIServerAccessProfile.
func (m *AzureManagedControlPlane) validateAPIServerAccessProfileUpdate(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
Expand Down
111 changes: 111 additions & 0 deletions api/v1beta1/azuremanagedcontrolplane_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,117 @@ func TestAzureManagedControlPlane_ValidateUpdate(t *testing.T) {
amcp: createAzureManagedControlPlane("192.168.0.10", "1.999.9", generateSSHPublicKey(true)),
wantErr: true,
},
{
name: "AzureManagedControlPlane invalid version downgrade change",
oldAMCP: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
},
amcp: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.17.0",
},
},
wantErr: true,
},
{
name: "AzureManagedControlPlane invalid version downgrade change",
oldAMCP: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
Status: AzureManagedControlPlaneStatus{
AutoUpgradeVersion: "v1.18.3",
},
},
amcp: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.1",
},
},
wantErr: true,
},
{
name: "AzureManagedControlPlane invalid version downgrade change",
oldAMCP: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
Status: AzureManagedControlPlaneStatus{
AutoUpgradeVersion: "1.19.3",
},
},
amcp: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.6",
},
},
wantErr: true,
},
{
name: "AzureManagedControlPlane no version change",
oldAMCP: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
Status: AzureManagedControlPlaneStatus{
AutoUpgradeVersion: "1.19.3",
},
},
amcp: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
},
wantErr: false,
},
{
name: "AzureManagedControlPlane valid version upgrade change",
oldAMCP: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
Status: AzureManagedControlPlaneStatus{
AutoUpgradeVersion: "1.19.3",
},
},
amcp: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.19.5",
},
},
wantErr: false,
},
{
name: "AzureManagedControlPlane valid version change",
oldAMCP: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.18.0",
},
Status: AzureManagedControlPlaneStatus{
AutoUpgradeVersion: "1.19.3",
},
},
amcp: &AzureManagedControlPlane{
Spec: AzureManagedControlPlaneSpec{
DNSServiceIP: ptr.To("192.168.0.0"),
Version: "v1.19.3",
},
},
wantErr: false,
},
{
name: "AzureManagedControlPlane SubscriptionID is immutable",
oldAMCP: &AzureManagedControlPlane{
Expand Down
30 changes: 30 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions azure/scope/managedcontrolplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,26 @@ func (s *ManagedControlPlaneScope) IsAADEnabled() bool {
return false
}

// SetAutoUpgradeVersionStatus sets the auto upgrade version in status

Check failure on line 481 in azure/scope/managedcontrolplane.go

View workflow job for this annotation

GitHub Actions / coverage

Comment should end in a period (godot)
func (s *ManagedControlPlaneScope) SetAutoUpgradeVersionStatus(version string) {
s.ControlPlane.Status.AutoUpgradeVersion = version
}

// IsManagedVersionUpgrade checks if version is auto managed by AKS.
func (s *ManagedControlPlaneScope) IsManagedVersionUpgrade() bool {
return isManagedVersionUpgrade(s.ControlPlane)
}

func isManagedVersionUpgrade(managedControlPlane *infrav1.AzureManagedControlPlane) bool {
if managedControlPlane.Spec.AutoUpgradeProfile != nil &&
managedControlPlane.Spec.AutoUpgradeProfile.UpgradeChannel != nil &&
(*managedControlPlane.Spec.AutoUpgradeProfile.UpgradeChannel != infrav1.UpgradeChannelNone &&
*managedControlPlane.Spec.AutoUpgradeProfile.UpgradeChannel != infrav1.UpgradeChannelNodeImage) {
return true
}
return false
}

// ManagedClusterSpec returns the managed cluster spec.
func (s *ManagedControlPlaneScope) ManagedClusterSpec() azure.ResourceSpecGetter {
managedClusterSpec := managedclusters.ManagedClusterSpec{
Expand Down Expand Up @@ -609,6 +629,16 @@ func (s *ManagedControlPlaneScope) ManagedClusterSpec() azure.ResourceSpecGetter
}
}

if s.ControlPlane.Spec.AutoUpgradeProfile != nil {
managedClusterSpec.AutoUpgradeProfile = &managedclusters.ManagedClusterAutoUpgradeProfile{}
if s.ControlPlane.Spec.AutoUpgradeProfile.UpgradeChannel != nil {
managedClusterSpec.AutoUpgradeProfile.UpgradeChannel = s.ControlPlane.Spec.AutoUpgradeProfile.UpgradeChannel
}
if s.ControlPlane.Spec.AutoUpgradeProfile.NodeOSUpgradeChannel != nil {
managedClusterSpec.AutoUpgradeProfile.NodeOSUpgradeChannel = s.ControlPlane.Spec.AutoUpgradeProfile.NodeOSUpgradeChannel
}
}

return &managedClusterSpec
}

Expand Down
Loading

0 comments on commit fa76c24

Please sign in to comment.