@@ -2,20 +2,24 @@ package azure
22
33import (
44 "fmt"
5+ "slices"
56 "sort"
67
78 "github.com/pkg/errors"
89 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910 "k8s.io/apimachinery/pkg/runtime"
11+ "k8s.io/apimachinery/pkg/util/sets"
1012
1113 clusterapi "github.com/openshift/api/machine/v1beta1"
14+ "github.com/openshift/installer/pkg/asset/installconfig"
1215 icazure "github.com/openshift/installer/pkg/asset/installconfig/azure"
1316 "github.com/openshift/installer/pkg/types"
1417 "github.com/openshift/installer/pkg/types/azure"
1518)
1619
1720// MachineSets returns a list of machinesets for a machinepool.
18- func MachineSets (clusterID string , config * types.InstallConfig , pool * types.MachinePool , osImage , role , userDataSecret string , capabilities map [string ]string , useImageGallery bool , subnetZones []string , session * icazure.Session ) ([]* clusterapi.MachineSet , error ) {
21+ func MachineSets (clusterID string , ic * installconfig.InstallConfig , pool * types.MachinePool , osImage , role , userDataSecret string , capabilities map [string ]string , useImageGallery bool , subnetZones []string , session * icazure.Session ) ([]* clusterapi.MachineSet , error ) {
22+ config := ic .Config
1923 if configPlatform := config .Platform .Name (); configPlatform != azure .Name {
2024 return nil , fmt .Errorf ("non-azure configuration: %q" , configPlatform )
2125 }
@@ -47,6 +51,27 @@ func MachineSets(clusterID string, config *types.InstallConfig, pool *types.Mach
4751 sort .Strings (azs )
4852 subnetIndex := - 1
4953 var machinesets []* clusterapi.MachineSet
54+
55+ if config .Azure .OutboundType == azure .NATGatewayMultiZoneOutboundType {
56+ return getMultiZoneMachineSets (multiZoneMachineSetInput {
57+ networkResourceGroup : networkResourceGroup ,
58+ virtualNetworkName : virtualNetworkName ,
59+ platform : platform ,
60+ mpool : mpool ,
61+ osImage : osImage ,
62+ userDataSecret : userDataSecret ,
63+ clusterID : clusterID ,
64+ role : role ,
65+ capabilities : capabilities ,
66+ useImageGallery : useImageGallery ,
67+ session : session ,
68+ subnetSpec : config .Azure .Subnets ,
69+ replicas : total ,
70+ ic : ic ,
71+ azs : azs ,
72+ pool : pool ,
73+ })
74+ }
5075 for idx , az := range azs {
5176 replicas := int32 (total / numOfAZs )
5277 if int64 (idx ) < total % numOfAZs {
@@ -102,3 +127,115 @@ func MachineSets(clusterID string, config *types.InstallConfig, pool *types.Mach
102127 }
103128 return machinesets , nil
104129}
130+
131+ type multiZoneMachineSetInput struct {
132+ networkResourceGroup string
133+ platform * azure.Platform
134+ mpool * azure.MachinePool
135+ osImage string
136+ userDataSecret string
137+ clusterID string
138+ role string
139+ capabilities map [string ]string
140+ useImageGallery bool
141+ session * icazure.Session
142+ virtualNetworkName string
143+ subnetSpec []azure.SubnetSpec
144+ replicas int64
145+ ic * installconfig.InstallConfig
146+ azs []string
147+ pool * types.MachinePool
148+ }
149+
150+ func getMultiZoneMachineSets (in multiZoneMachineSetInput ) ([]* clusterapi.MachineSet , error ) {
151+ // Deep copy metadata map.
152+ zoneSubnetmap := map [string ][]string {}
153+ subnetCount := 0
154+ for key , value := range in .ic .Azure .ZonesSubnetMap {
155+ if slices .Contains (in .azs , key ) {
156+ zoneSubnetmap [key ] = sets .NewString (value ... ).List ()
157+ subnetCount += len (value )
158+ }
159+ }
160+ machineSets := []* clusterapi.MachineSet {}
161+ replicasToCreate := int32 (in .replicas )
162+ replicaPerSet := max (replicasToCreate / int32 (subnetCount ), 1 )
163+ remainder := replicasToCreate % int32 (subnetCount )
164+ if replicasToCreate < int32 (subnetCount ) {
165+ remainder = 0
166+ }
167+ numAZUsed := map [string ]int {}
168+ for _ , az := range in .azs {
169+ numAZUsed [az ] = 0
170+ }
171+ for replicasToCreate != 0 && len (zoneSubnetmap ) != 0 {
172+ for idx , az := range in .azs {
173+ if _ , ok := zoneSubnetmap [az ]; ! ok {
174+ continue
175+ }
176+ subnet := zoneSubnetmap [az ][0 ]
177+ if len (zoneSubnetmap [az ]) == 1 {
178+ delete (zoneSubnetmap , az )
179+ } else {
180+ zoneSubnetmap [az ] = zoneSubnetmap [az ][1 :]
181+ }
182+ currentReplica := replicaPerSet
183+ if remainder != 0 {
184+ currentReplica ++
185+ remainder --
186+ }
187+ provider , err := provider (in .platform , in .mpool , in .osImage , in .userDataSecret , in .clusterID , in .role , & idx , in .capabilities , in .useImageGallery , in .session , in .networkResourceGroup , in .virtualNetworkName , subnet )
188+ if err != nil {
189+ return nil , errors .Wrap (err , "failed to create provider" )
190+ }
191+ name := fmt .Sprintf ("%s-%s-%s%s-%d" , in .clusterID , in .pool .Name , in .platform .Region , az , numAZUsed [az ])
192+ if numAZUsed [az ] == 0 {
193+ name = fmt .Sprintf ("%s-%s-%s%s" , in .clusterID , in .pool .Name , in .platform .Region , az )
194+ }
195+ numAZUsed [az ]++
196+ mset := & clusterapi.MachineSet {
197+ TypeMeta : metav1.TypeMeta {
198+ APIVersion : "machine.openshift.io/v1beta1" ,
199+ Kind : "MachineSet" ,
200+ },
201+ ObjectMeta : metav1.ObjectMeta {
202+ Namespace : "openshift-machine-api" ,
203+ Name : name ,
204+ Labels : map [string ]string {
205+ "machine.openshift.io/cluster-api-cluster" : in .clusterID ,
206+ "machine.openshift.io/cluster-api-machine-role" : in .role ,
207+ "machine.openshift.io/cluster-api-machine-type" : in .role ,
208+ },
209+ },
210+ Spec : clusterapi.MachineSetSpec {
211+ Replicas : & currentReplica ,
212+ Selector : metav1.LabelSelector {
213+ MatchLabels : map [string ]string {
214+ "machine.openshift.io/cluster-api-machineset" : name ,
215+ "machine.openshift.io/cluster-api-cluster" : in .clusterID ,
216+ },
217+ },
218+ Template : clusterapi.MachineTemplateSpec {
219+ ObjectMeta : clusterapi.ObjectMeta {
220+ Labels : map [string ]string {
221+ "machine.openshift.io/cluster-api-machineset" : name ,
222+ "machine.openshift.io/cluster-api-cluster" : in .clusterID ,
223+ "machine.openshift.io/cluster-api-machine-role" : in .role ,
224+ "machine.openshift.io/cluster-api-machine-type" : in .role ,
225+ },
226+ },
227+ Spec : clusterapi.MachineSpec {
228+ ProviderSpec : clusterapi.ProviderSpec {
229+ Value : & runtime.RawExtension {Object : provider },
230+ },
231+ // we don't need to set Versions, because we control those via cluster operators.
232+ },
233+ },
234+ },
235+ }
236+ machineSets = append (machineSets , mset )
237+ replicasToCreate -= currentReplica
238+ }
239+ }
240+ return machineSets , nil
241+ }
0 commit comments