From 8b5fb2d8503e1c9ffff8d6b8fc54bc3fc41c207d Mon Sep 17 00:00:00 2001 From: Matt Boersma Date: Wed, 8 May 2024 08:56:08 -0600 Subject: [PATCH] Default to Azure Linux images --- azure/scope/machine.go | 2 +- azure/scope/machine_test.go | 2 +- azure/scope/machinepool.go | 2 +- azure/scope/machinepool_test.go | 2 +- azure/services/virtualmachineimages/images.go | 53 ++++++++++++++++++- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/azure/scope/machine.go b/azure/scope/machine.go index 67f090d8e35..e096446915a 100644 --- a/azure/scope/machine.go +++ b/azure/scope/machine.go @@ -718,7 +718,7 @@ func (m *MachineScope) GetVMImage(ctx context.Context) (*infrav1.Image, error) { } log.Info("No image specified for machine, using default Linux Image", "machine", m.AzureMachine.GetName()) - return svc.GetDefaultUbuntuImage(ctx, m.Location(), ptr.Deref(m.Machine.Spec.Version, "")) + return svc.GetDefaultLinuxImage(ctx, m.Location(), ptr.Deref(m.Machine.Spec.Version, "")) } // SetSubnetName defaults the AzureMachine subnet name to the name of one the subnets with the machine role when there is only one of them. diff --git a/azure/scope/machine_test.go b/azure/scope/machine_test.go index a482e9198ca..17a50767890 100644 --- a/azure/scope/machine_test.go +++ b/azure/scope/machine_test.go @@ -1702,7 +1702,7 @@ func TestMachineScope_GetVMImage(t *testing.T) { ClusterScoper: clusterMock, }, want: func() *infrav1.Image { - image, _ := svc.GetDefaultUbuntuImage(context.TODO(), "", "1.20.1") + image, _ := svc.GetDefaultLinuxImage(context.TODO(), "", "1.20.1") return image }(), expectedErr: "", diff --git a/azure/scope/machinepool.go b/azure/scope/machinepool.go index b7354bc9f53..3e0ebafb54b 100644 --- a/azure/scope/machinepool.go +++ b/azure/scope/machinepool.go @@ -772,7 +772,7 @@ func (m *MachinePoolScope) GetVMImage(ctx context.Context) (*infrav1.Image, erro log.V(4).Info("No image specified for machine, using default Windows Image", "machine", m.MachinePool.GetName(), "runtime", runtime, "windowsServerVersion", windowsServerVersion) defaultImage, err = svc.GetDefaultWindowsImage(ctx, m.Location(), ptr.Deref(m.MachinePool.Spec.Template.Spec.Version, ""), runtime, windowsServerVersion) } else { - defaultImage, err = svc.GetDefaultUbuntuImage(ctx, m.Location(), ptr.Deref(m.MachinePool.Spec.Template.Spec.Version, "")) + defaultImage, err = svc.GetDefaultLinuxImage(ctx, m.Location(), ptr.Deref(m.MachinePool.Spec.Template.Spec.Version, "")) } if err != nil { diff --git a/azure/scope/machinepool_test.go b/azure/scope/machinepool_test.go index 0f410516f8d..81a6dba759c 100644 --- a/azure/scope/machinepool_test.go +++ b/azure/scope/machinepool_test.go @@ -423,7 +423,7 @@ func TestMachinePoolScope_GetVMImage(t *testing.T) { ImagePlan: infrav1.ImagePlan{ Publisher: "cncf-upstream", Offer: "capi", - SKU: "k8s-1dot19dot11-ubuntu-1804", + SKU: "k8s-1dot19dot11-azurelinux-3", }, Version: "latest", ThirdPartyImage: false, diff --git a/azure/services/virtualmachineimages/images.go b/azure/services/virtualmachineimages/images.go index 54ba6691221..cb2255821f1 100644 --- a/azure/services/virtualmachineimages/images.go +++ b/azure/services/virtualmachineimages/images.go @@ -47,8 +47,59 @@ func New(auth azure.Authorizer) (*Service, error) { }, nil } +// GetDefaultLinuxImage returns the default image spec for a Linux node. +func (s *Service) GetDefaultLinuxImage(ctx context.Context, location, k8sVersion string) (*infrav1.Image, error) { + ctx, log, done := tele.StartSpanWithLogger(ctx, "virtualmachineimages.Service.GetDefaultLinuxImage") + defer done() + + // First try Azure Linux, then Ubuntu. + defaultImage, err := s.GetDefaultAzureLinuxImage(ctx, location, k8sVersion) + if err != nil { + log.V(4).Info("Failed to get default Azure Linux image, trying default Ubuntu image", "error", err) + return s.GetDefaultUbuntuImage(ctx, location, k8sVersion) + } + + return defaultImage, nil +} + +// GetDefaultAzureLinuxImage returns the default image spec for Azure Linux. +func (s *Service) GetDefaultAzureLinuxImage(ctx context.Context, location, k8sVersion string) (*infrav1.Image, error) { + ctx, log, done := tele.StartSpanWithLogger(ctx, "virtualmachineimages.Service.GetDefaultAzureLinuxImage") + defer done() + + // First try Azure Linux 3. + publisher, offer := azure.DefaultImagePublisherID, azure.DefaultImageOfferID + skuID, version, err := s.getSKUAndVersion( + ctx, location, publisher, offer, k8sVersion, "azurelinux-3") + if err != nil { + // If that fails, log the error and try Azure Linux 2. + log.V(4).Info("Failed to get default image for Azure Linux 3, trying Azure Linux 2", "error", err) + skuID, version, err = s.getSKUAndVersion( + ctx, location, publisher, offer, k8sVersion, "mariner-2") //TODO: switch to "azurelinux-2" + if err != nil { + return nil, errors.Wrap(err, "failed to get default image") + } + } + + defaultImage := &infrav1.Image{ + Marketplace: &infrav1.AzureMarketplaceImage{ + ImagePlan: infrav1.ImagePlan{ + Publisher: publisher, + Offer: offer, + SKU: skuID, + }, + Version: version, + }, + } + + return defaultImage, nil +} + // GetDefaultUbuntuImage returns the default image spec for Ubuntu. func (s *Service) GetDefaultUbuntuImage(ctx context.Context, location, k8sVersion string) (*infrav1.Image, error) { + ctx, _, done := tele.StartSpanWithLogger(ctx, "virtualmachineimages.Service.GetDefaultAzureLinuxImage") + defer done() + v, err := semver.ParseTolerant(k8sVersion) if err != nil { return nil, errors.Wrapf(err, "unable to parse Kubernetes version \"%s\"", k8sVersion) @@ -121,7 +172,7 @@ func (s *Service) GetDefaultWindowsImage(ctx context.Context, location, k8sVersi // getSKUAndVersion gets the SKU ID and version of the image to use for the provided version of Kubernetes. // note: osAndVersion is expected to be in the format of {os}-{version} (ex: ubuntu-2004 or windows-2022) -func (s *Service) getSKUAndVersion(ctx context.Context, location, publisher, offer, k8sVersion, osAndVersion string) (skuID string, imageVersion string, err error) { +func (s *Service) getSKUAndVersion(ctx context.Context, location, publisher, offer, k8sVersion, osAndVersion string) (skuID string, imageVersion string, err error) { //nolint:unparam // Keep "publisher" in the function signature. ctx, log, done := tele.StartSpanWithLogger(ctx, "virtualmachineimages.Service.getSKUAndVersion") defer done()