diff --git a/charts/internal/machineclass/templates/machineclass.yaml b/charts/internal/machineclass/templates/machineclass.yaml index 48cebf067..ee442fc72 100644 --- a/charts/internal/machineclass/templates/machineclass.yaml +++ b/charts/internal/machineclass/templates/machineclass.yaml @@ -35,6 +35,10 @@ spec: {{- if hasKey $machineClass "identityID" }} identityID: {{ $machineClass.identityID }} {{- end }} + {{- if hasKey $machineClass.network "acceleratedNetworking" }} + networkProfile: + acceleratedNetworking: {{ $machineClass.network.acceleratedNetworking }} + {{- end }} hardwareProfile: vmSize: {{ $machineClass.machineType }} osProfile: @@ -65,11 +69,11 @@ spec: name: {{ $machineClass.name }} namespace: {{ $.Release.Namespace }} subnetInfo: - vnetName: {{ $machineClass.vnetName }} - {{- if hasKey $machineClass "vnetResourceGroup" }} - vnetResourceGroup: {{ $machineClass.vnetResourceGroup}} + vnetName: {{ $machineClass.network.vnet }} + {{- if hasKey $machineClass.network "vnetResourceGroup" }} + vnetResourceGroup: {{ $machineClass.network.vnetResourceGroup}} {{- end }} - subnetName: {{ $machineClass.subnetName }} + subnetName: {{ $machineClass.network.subnet }} {{- if $machineClass.tags }} tags: {{ toYaml $machineClass.tags | indent 4 }} diff --git a/charts/internal/machineclass/values.yaml b/charts/internal/machineclass/values.yaml index 4b6858791..2c1f7689d 100644 --- a/charts/internal/machineclass/values.yaml +++ b/charts/internal/machineclass/values.yaml @@ -4,10 +4,13 @@ machineClasses: # foo: bar region: westeurope resourceGroup: my-resource-group - vnetName: my-vnet - subnetName: my-subnet-in-my-vnet zone: 1 # identityID: /subscriptions/subscription-id/resourceGroups/resource-group-name/providers/Microsoft.ManagedIdentity/userAssignedIdentities/identity-name + network: + vnet: my-vnet + subnet: my-subnet-in-my-vnet + # vnetResourceGroup: my-vnet-resource-group + # acceleratedNetworking: true tags: Name: shoot-crazy-botany kubernetes.io-cluster-shoot-crazy-botany: "1" @@ -29,8 +32,9 @@ machineClasses: - name: class-2-availability-set region: westeurope resourceGroup: my-resource-group - vnetName: my-vnet - subnetName: my-subnet-in-my-vnet + network: + vnet: my-vnet + subnet: my-subnet-in-my-vnet availabilitySetID: /subscriptions/subscription-id/resourceGroups/resource-group-name/providers/Microsoft.Compute/availabilitySets/availablity-set-name tags: Name: shoot-crazy-botany diff --git a/docs/usage-as-end-user.md b/docs/usage-as-end-user.md index 82ca06c27..e5ff2db63 100644 --- a/docs/usage-as-end-user.md +++ b/docs/usage-as-end-user.md @@ -210,3 +210,9 @@ spec: nginxIngress: enabled: true ``` + +## Miscellaneous + +### Azure Accelerated Networking +Machine(s) will be automatically configured to use [Azure Accelerated Networking](https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli) in case the machine type and machine image version is configured in the CloudProfile to be compatible with Accelerated Networking. +Supported machine types are listed in `.spec.providerConfig.acceleratedNetworingMachineTypes[]` and the supported machine image versions are listed in `.spec.providerConfig.machineImages[].versions[].acceleratedNetworking`. diff --git a/docs/usage-as-operator.md b/docs/usage-as-operator.md index e07c75263..7c313f7c6 100644 --- a/docs/usage-as-operator.md +++ b/docs/usage-as-operator.md @@ -6,10 +6,6 @@ In this document we are describing how this configuration looks like for Azure a ## `CloudProfileConfig` -The cloud profile configuration contains information about the update and failure domain counts in the Azure regions you want to offer. -Additionally, it contains the real machine image identifiers in the Azure environment. You can provide either URN or image ID. -You have to map every version that you specify in `.spec.machineImages[].versions` here such that the Azure extension knows the machine image identifiers for every version you want to offer. - An example `CloudProfileConfig` for the Azure extension looks as follows: ```yaml @@ -21,15 +17,25 @@ countUpdateDomains: countFaultDomains: - region: westeurope count: 3 +acceleratedNetworingMachineTypes: +- Standard_D3_v2 machineImages: - name: coreos versions: - version: 2135.6.0 urn: "CoreOS:CoreOS:Stable:2135.6.0" + acceleratedNetworking: true - version: 2303.3.0 id: "/Subscriptions/4bfa08b6-bad8-4b8e-aa00-741c0a859e36/Providers/Microsoft.Compute/Locations/westus/Publishers/CoreOS/ArtifactTypes/VMImage/Offers/CoreOS/Skus/Stable/Versions/2303.3.0" ``` +The cloud profile configuration contains information about the update via `.countUpdateDomains[]` and failure domain via `.countFaultDomains[]` counts in the Azure regions you want to offer. + +Additionally, it contains the real machine image identifiers in the Azure environment. You have to map every image version that you specify in `.spec.machineImages[].versions` such that the Azure extension knows the machine image identifiers for every version you want to offer. You can provide either URN (`.machineImages[].versions[].urn`) or image ID (`.machineImages[].versions[].id`) for each image version. It's also possible to specify for each image version if the version is supporting Azure Accelerated Networking via `.machineImages[].versions[].acceleratedNetworking`. + +In `.acceleratedNetworingMachineTypes[]` you can specify the machine types which are compatible with [Azure Accelerated Networking](https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli). + + ## Example `CloudProfile` manifest The possible values for `.spec.volumeTypes[].name` on Azure are `Standard_LRS`, `StandardSSD_LRS` and `Premium_LRS`. There is another volume type called `UltraSSD_LRS` but this type is not supported to use as os disk. If an end user select a volume type whose name is not equal to one of the valid values then the machine will be created with the default volume type which belong to the selected machine type. Therefore it is recommended to configure only the valid values for the `.spec.volumeType[].name` in the `CloudProfile`. @@ -53,6 +59,10 @@ spec: versions: - version: 2135.6.0 machineTypes: + - name: Standard_D3_v2 + cpu: "4" + gpu: "0" + memory: 14Gi - name: Standard_D4_v3 cpu: "4" gpu: "0" @@ -72,6 +82,8 @@ spec: providerConfig: apiVersion: azure.provider.extensions.gardener.cloud/v1alpha1 kind: CloudProfileConfig + acceleratedNetworingMachineTypes: + - Standard_D3_v2 countUpdateDomains: - region: westeurope count: 5 @@ -81,6 +93,9 @@ spec: machineImages: - name: coreos versions: + - version: 2303.3.0 + urn: CoreOS:CoreOS:Stable:2303.3.0 + acceleratedNetworking: true - version: 2135.6.0 urn: "CoreOS:CoreOS:Stable:2135.6.0" ``` diff --git a/hack/api-reference/api.md b/hack/api-reference/api.md index 3bbad2442..c4928f26c 100644 --- a/hack/api-reference/api.md +++ b/hack/api-reference/api.md @@ -89,6 +89,17 @@ string logical names and versions to provider-specific identifiers.

+ + +acceleratedNetworkingMachineTypes
+ +[]string + + + +

AcceleratedNetworkingMachineTypes is a list of machine types which support accelerated networking.

+ +

ControlPlaneConfig @@ -726,6 +737,17 @@ string

ID is the VM image ID

+ + +acceleratedNetworking
+ +bool + + + +

AcceleratedNetworing is an indicator if the image does support Azure accelerated networking.

+ +

MachineImages diff --git a/pkg/apis/azure/types_cloudprofile.go b/pkg/apis/azure/types_cloudprofile.go index 3519fa85c..e0a4ba85b 100644 --- a/pkg/apis/azure/types_cloudprofile.go +++ b/pkg/apis/azure/types_cloudprofile.go @@ -31,6 +31,8 @@ type CloudProfileConfig struct { // MachineImages is the list of machine images that are understood by the controller. It maps // logical names and versions to provider-specific identifiers. MachineImages []MachineImages + // AcceleratedNetworkingMachineTypes is a list of machine types which support accelerated networking. + AcceleratedNetworkingMachineTypes []string } // DomainCount defines the region and the count for this domain count value. @@ -57,4 +59,6 @@ type MachineImageVersion struct { URN *string // ID is the image id. ID *string + // AcceleratedNetworing is an indicator if the image does support Azure accelerated networking. + AcceleratedNetworking *bool } diff --git a/pkg/apis/azure/v1alpha1/types_cloudprofile.go b/pkg/apis/azure/v1alpha1/types_cloudprofile.go index 2ae84746a..c39493e79 100644 --- a/pkg/apis/azure/v1alpha1/types_cloudprofile.go +++ b/pkg/apis/azure/v1alpha1/types_cloudprofile.go @@ -32,6 +32,8 @@ type CloudProfileConfig struct { // MachineImages is the list of machine images that are understood by the controller. It maps // logical names and versions to provider-specific identifiers. MachineImages []MachineImages `json:"machineImages"` + // AcceleratedNetworkingMachineTypes is a list of machine types which support accelerated networking. + AcceleratedNetworkingMachineTypes []string `json:"acceleratedNetworkingMachineTypes,omitempty"` } // DomainCount defines the region and the count for this domain count value. @@ -60,4 +62,6 @@ type MachineImageVersion struct { //ID is the VM image ID // +optional ID *string `json:"id,omitempty"` + // AcceleratedNetworing is an indicator if the image does support Azure accelerated networking. + AcceleratedNetworking *bool `json:"acceleratedNetworking,omitempty"` } diff --git a/pkg/apis/azure/v1alpha1/zz_generated.conversion.go b/pkg/apis/azure/v1alpha1/zz_generated.conversion.go index 30ed86a15..e2f228618 100644 --- a/pkg/apis/azure/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/azure/v1alpha1/zz_generated.conversion.go @@ -306,6 +306,7 @@ func autoConvert_v1alpha1_CloudProfileConfig_To_azure_CloudProfileConfig(in *Clo out.CountUpdateDomains = *(*[]azure.DomainCount)(unsafe.Pointer(&in.CountUpdateDomains)) out.CountFaultDomains = *(*[]azure.DomainCount)(unsafe.Pointer(&in.CountFaultDomains)) out.MachineImages = *(*[]azure.MachineImages)(unsafe.Pointer(&in.MachineImages)) + out.AcceleratedNetworkingMachineTypes = *(*[]string)(unsafe.Pointer(&in.AcceleratedNetworkingMachineTypes)) return nil } @@ -318,6 +319,7 @@ func autoConvert_azure_CloudProfileConfig_To_v1alpha1_CloudProfileConfig(in *azu out.CountUpdateDomains = *(*[]DomainCount)(unsafe.Pointer(&in.CountUpdateDomains)) out.CountFaultDomains = *(*[]DomainCount)(unsafe.Pointer(&in.CountFaultDomains)) out.MachineImages = *(*[]MachineImages)(unsafe.Pointer(&in.MachineImages)) + out.AcceleratedNetworkingMachineTypes = *(*[]string)(unsafe.Pointer(&in.AcceleratedNetworkingMachineTypes)) return nil } @@ -516,6 +518,7 @@ func autoConvert_v1alpha1_MachineImageVersion_To_azure_MachineImageVersion(in *M out.Version = in.Version out.URN = (*string)(unsafe.Pointer(in.URN)) out.ID = (*string)(unsafe.Pointer(in.ID)) + out.AcceleratedNetworking = (*bool)(unsafe.Pointer(in.AcceleratedNetworking)) return nil } @@ -528,6 +531,7 @@ func autoConvert_azure_MachineImageVersion_To_v1alpha1_MachineImageVersion(in *a out.Version = in.Version out.URN = (*string)(unsafe.Pointer(in.URN)) out.ID = (*string)(unsafe.Pointer(in.ID)) + out.AcceleratedNetworking = (*bool)(unsafe.Pointer(in.AcceleratedNetworking)) return nil } diff --git a/pkg/apis/azure/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/azure/v1alpha1/zz_generated.deepcopy.go index 7498ed217..011a812de 100644 --- a/pkg/apis/azure/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/azure/v1alpha1/zz_generated.deepcopy.go @@ -84,6 +84,11 @@ func (in *CloudProfileConfig) DeepCopyInto(out *CloudProfileConfig) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.AcceleratedNetworkingMachineTypes != nil { + in, out := &in.AcceleratedNetworkingMachineTypes, &out.AcceleratedNetworkingMachineTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -310,6 +315,11 @@ func (in *MachineImageVersion) DeepCopyInto(out *MachineImageVersion) { *out = new(string) **out = **in } + if in.AcceleratedNetworking != nil { + in, out := &in.AcceleratedNetworking, &out.AcceleratedNetworking + *out = new(bool) + **out = **in + } return } diff --git a/pkg/apis/azure/zz_generated.deepcopy.go b/pkg/apis/azure/zz_generated.deepcopy.go index d4be231a1..fb08c6a2a 100644 --- a/pkg/apis/azure/zz_generated.deepcopy.go +++ b/pkg/apis/azure/zz_generated.deepcopy.go @@ -84,6 +84,11 @@ func (in *CloudProfileConfig) DeepCopyInto(out *CloudProfileConfig) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.AcceleratedNetworkingMachineTypes != nil { + in, out := &in.AcceleratedNetworkingMachineTypes, &out.AcceleratedNetworkingMachineTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -310,6 +315,11 @@ func (in *MachineImageVersion) DeepCopyInto(out *MachineImageVersion) { *out = new(string) **out = **in } + if in.AcceleratedNetworking != nil { + in, out := &in.AcceleratedNetworking, &out.AcceleratedNetworking + *out = new(bool) + **out = **in + } return } diff --git a/pkg/controller/worker/machines.go b/pkg/controller/worker/machines.go index aa28d40ec..32b6a9274 100644 --- a/pkg/controller/worker/machines.go +++ b/pkg/controller/worker/machines.go @@ -174,12 +174,13 @@ func (w *workerDelegate) generateMachineConfig(ctx context.Context) error { Annotations: pool.Annotations, Taints: pool.Taints, } - + networkConfig = map[string]interface{}{ + "vnet": infrastructureStatus.Networks.VNet.Name, + "subnet": nodesSubnet.Name, + } machineClassSpec = map[string]interface{}{ "region": w.worker.Spec.Region, "resourceGroup": infrastructureStatus.ResourceGroup.Name, - "vnetName": infrastructureStatus.Networks.VNet.Name, - "subnetName": nodesSubnet.Name, "tags": map[string]interface{}{ "Name": w.worker.Namespace, fmt.Sprintf("kubernetes.io-cluster-%s", w.worker.Namespace): "1", @@ -198,12 +199,16 @@ func (w *workerDelegate) generateMachineConfig(ctx context.Context) error { machineClassSpec["vnetResourceGroup"] = *infrastructureStatus.Networks.VNet.ResourceGroup } + if w.enableAcceleratedNetworking(pool.MachineType, pool.MachineImage.Name, pool.MachineImage.Version) { + networkConfig["acceleratedNetworking"] = true + } + machineClassSpec["network"] = networkConfig + if zone != nil { machineDeployment.Minimum = worker.DistributeOverZones(zone.index, pool.Minimum, zone.count) machineDeployment.Maximum = worker.DistributeOverZones(zone.index, pool.Maximum, zone.count) machineDeployment.MaxSurge = worker.DistributePositiveIntOrPercent(zone.index, pool.MaxSurge, zone.count, pool.Maximum) machineDeployment.MaxUnavailable = worker.DistributePositiveIntOrPercent(zone.index, pool.MaxUnavailable, zone.count, pool.Minimum) - machineClassSpec["zone"] = zone.name } if availabilitySetID != nil { @@ -268,3 +273,32 @@ func (w *workerDelegate) generateMachineConfig(ctx context.Context) error { return nil } + +func (w *workerDelegate) enableAcceleratedNetworking(machineType, machineImageName, machineImageVersion string) bool { + // Check if used operating system and version are supporting accelerated networking. + var osSupport bool + for _, image := range w.cloudProfileConfig.MachineImages { + if image.Name != machineImageName { + continue + } + for _, imageVersion := range image.Versions { + if imageVersion.Version == machineImageVersion { + if imageVersion.AcceleratedNetworking != nil && *imageVersion.AcceleratedNetworking { + osSupport = true + } else { + return false + } + } + } + } + + // Check if machine type is in list of accelerated networking supporting machine types. + var machineTypeSupport bool + for _, machType := range w.cloudProfileConfig.AcceleratedNetworkingMachineTypes { + if machType == machineType { + machineTypeSupport = true + break + } + } + return osSupport && machineTypeSupport +} diff --git a/pkg/controller/worker/machines_test.go b/pkg/controller/worker/machines_test.go index 20ddde97c..fcfd7764d 100644 --- a/pkg/controller/worker/machines_test.go +++ b/pkg/controller/worker/machines_test.go @@ -84,7 +84,6 @@ var _ = Describe("Machines", func() { var ( namespace string cloudProfileName string - identityID = "identity-id" azureClientID string azureClientSecret string @@ -100,6 +99,7 @@ var _ = Describe("Machines", func() { vnetName string subnetName string availabilitySetID string + identityID string machineType string userData []byte volumeSize int @@ -151,6 +151,7 @@ var _ = Describe("Machines", func() { userData = []byte("some-user-data") volumeSize = 20 sshKey = "public-key" + identityID = "identity-id" namePool1 = "pool-1" minPool1 = 5 @@ -176,7 +177,6 @@ var _ = Describe("Machines", func() { }, }, } - cloudProfileConfig := &apiv1alpha1.CloudProfileConfig{ TypeMeta: metav1.TypeMeta{ APIVersion: apiv1alpha1.SchemeGroupVersion.String(), @@ -306,10 +306,12 @@ var _ = Describe("Machines", func() { BeforeEach(func() { defaultMachineClass = map[string]interface{}{ - "region": region, - "resourceGroup": resourceGroupName, - "vnetName": vnetName, - "subnetName": subnetName, + "region": region, + "resourceGroup": resourceGroupName, + "network": map[string]interface{}{ + "vnet": vnetName, + "subnet": subnetName, + }, "availabilitySetID": availabilitySetID, "tags": map[string]interface{}{ "Name": namespace, @@ -409,9 +411,7 @@ var _ = Describe("Machines", func() { }) It("should fail because the secret cannot be read", func() { - c.EXPECT(). - Get(context.TODO(), gomock.Any(), gomock.AssignableToTypeOf(&corev1.Secret{})). - Return(fmt.Errorf("error")) + c.EXPECT().Get(context.TODO(), gomock.Any(), gomock.AssignableToTypeOf(&corev1.Secret{})).Return(fmt.Errorf("error")) result, err := workerDelegate.GenerateMachineDeployments(context.TODO()) Expect(err).To(HaveOccurred())