Skip to content

Commit 6045e06

Browse files
committed
azure: Add support for multi zonal NAT gateways
Adding support to install multiple NAT gateways per subnet. The zone in which they will be installed is not customizable due to needing an upstream PR to fix CAPZ. Also, allowing the users to bring their own subnets.
1 parent ec5eb80 commit 6045e06

File tree

2 files changed

+84
-17
lines changed

2 files changed

+84
-17
lines changed

pkg/asset/manifests/azure/cluster.go

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,20 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
179179

180180
azEnv := string(installConfig.Azure.CloudName)
181181

182-
computeSubnetSpec := capz.SubnetSpec{
182+
// Set default control plane subnets for default installs.
183+
defaultControlPlaneSubnet := capz.Subnets{
184+
{
185+
SubnetClassSpec: capz.SubnetClassSpec{
186+
Name: controlPlaneSubnet,
187+
Role: capz.SubnetControlPlane,
188+
CIDRBlocks: []string{
189+
subnets[0].String(),
190+
},
191+
},
192+
SecurityGroup: securityGroup,
193+
},
194+
}
195+
defaultComputeSubnetSpec := capz.SubnetSpec{
183196
ID: nodeSubnetID,
184197
SubnetClassSpec: capz.SubnetClassSpec{
185198
Name: computeSubnet,
@@ -191,10 +204,53 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
191204
SecurityGroup: securityGroup,
192205
}
193206

194-
if installConfig.Config.Azure.OutboundType == azure.NATGatewaySingleZoneOutboundType {
195-
computeSubnetSpec.NatGateway = capz.NatGateway{
196-
NatGatewayClassSpec: capz.NatGatewayClassSpec{Name: fmt.Sprintf("%s-natgw", clusterID.InfraID)},
207+
subnetSpec := []capz.SubnetSpec{}
208+
hasControlPlaneSubnet := false
209+
hasComputePlaneSubnet := false
210+
211+
// Add the user specified subnets to the spec.
212+
// For single zone, alter the compute subnet to have a NATGateway and add default control plane subnet
213+
// configuration.
214+
for index, spec := range installConfig.Config.Azure.Subnets {
215+
specGen := capz.SubnetSpec{
216+
ID: "UNKNOWN",
217+
SubnetClassSpec: capz.SubnetClassSpec{
218+
Name: spec.Name,
219+
Role: spec.Role,
220+
},
221+
SecurityGroup: securityGroup,
222+
}
223+
// The CIDR information is optional since it could be a byo subnet.
224+
if len(spec.SubnetCIDR) != 0 {
225+
specGen.CIDRBlocks = spec.SubnetCIDR
197226
}
227+
// If role is compute node and outbound type is single node, add a NAT gateway to the subnet.
228+
// Only adding a NAT gateway to the first subnet.
229+
if !hasComputePlaneSubnet && spec.Role == capz.SubnetNode && installConfig.Config.Azure.OutboundType == azure.NATGatewaySingleZoneOutboundType {
230+
specGen.NatGateway = capz.NatGateway{
231+
NatGatewayClassSpec: capz.NatGatewayClassSpec{Name: fmt.Sprintf("%s-natgw", clusterID.InfraID)},
232+
}
233+
} else if installConfig.Config.Azure.OutboundType == azure.NATGatewayMultiZoneOutboundType {
234+
if spec.NatGatewayName != "" {
235+
specGen.NatGateway = capz.NatGateway{
236+
NatGatewayIP: capz.PublicIPSpec{
237+
Name: fmt.Sprintf("%s-natgw-public-ip-%d", clusterID.InfraID, index),
238+
},
239+
NatGatewayClassSpec: capz.NatGatewayClassSpec{Name: spec.NatGatewayName},
240+
}
241+
}
242+
}
243+
hasControlPlaneSubnet = hasControlPlaneSubnet || spec.Role == capz.SubnetControlPlane
244+
hasComputePlaneSubnet = hasComputePlaneSubnet || spec.Role == capz.SubnetNode
245+
subnetSpec = append(subnetSpec, specGen)
246+
}
247+
// Make sure there's at least one subnet for compute and control plane.
248+
// Ordinary installs will get the default setup.
249+
if !hasComputePlaneSubnet {
250+
subnetSpec = append(subnetSpec, defaultComputeSubnetSpec)
251+
}
252+
if !hasControlPlaneSubnet {
253+
subnetSpec = append(subnetSpec, defaultControlPlaneSubnet...)
198254
}
199255

200256
azureCluster := &capz.AzureCluster{
@@ -236,19 +292,7 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
236292
},
237293
APIServerLB: &apiServerLB,
238294
ControlPlaneOutboundLB: controlPlaneOutboundLB,
239-
Subnets: capz.Subnets{
240-
{
241-
SubnetClassSpec: capz.SubnetClassSpec{
242-
Name: controlPlaneSubnet,
243-
Role: capz.SubnetControlPlane,
244-
CIDRBlocks: []string{
245-
subnets[0].String(),
246-
},
247-
},
248-
SecurityGroup: securityGroup,
249-
},
250-
computeSubnetSpec,
251-
},
295+
Subnets: subnetSpec,
252296
},
253297
},
254298
}

pkg/types/azure/platform.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66

77
"github.com/openshift/installer/pkg/types/dns"
8+
capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
89
)
910

1011
// aro is a setting to enable aro-only modifications
@@ -23,6 +24,9 @@ const (
2324
// see https://learn.microsoft.com/en-us/azure/virtual-network/nat-gateway/nat-gateway-resource
2425
NATGatewaySingleZoneOutboundType OutboundType = "NATGatewaySingleZone"
2526

27+
// NATGatewayMultiZoneOutboundType uses NAT gateways in multiple zones in the compute node subnets for outbound access.
28+
NATGatewayMultiZoneOutboundType OutboundType = "MultiZoneNatGateway"
29+
2630
// UserDefinedRoutingOutboundType uses user defined routing for egress from the cluster.
2731
// see https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-udr-overview
2832
UserDefinedRoutingOutboundType OutboundType = "UserDefinedRouting"
@@ -83,6 +87,11 @@ type Platform struct {
8387
// +optional
8488
OutboundType OutboundType `json:"outboundType"`
8589

90+
// Subnets is the list of subnets the user can bring into the cluster to be used.
91+
//
92+
// +optional
93+
Subnets []SubnetSpec `json:"subnets,omitempty"`
94+
8695
// ResourceGroupName is the name of an already existing resource group where the cluster should be installed.
8796
// This resource group should only be used for this specific cluster and the cluster components will assume
8897
// ownership of all resources in the resource group. Destroying the cluster using installer will delete this
@@ -110,6 +119,20 @@ type Platform struct {
110119
UserProvisionedDNS dns.UserProvisionedDNS `json:"userProvisionedDNS,omitempty"`
111120
}
112121

122+
// SubnetSpec specifies the properties the subnet needs to be used in the cluster.
123+
type SubnetSpec struct {
124+
// Name of the subnet.
125+
Name string `json:"name"`
126+
// Role specifies the actual role which the subnet should be used in.
127+
Role capz.SubnetRole `json:"role"`
128+
// SubnetCIDR specifies the CIDR for the subnet if it needs to be created.
129+
// Should not be mentioned if the subnet is a bring your own subnet.
130+
SubnetCIDR []string `json:"cidr"`
131+
// NatGatewayName specifies the name of the NAT gateway to be created for this subnet.
132+
// Can only be used if the outbound type is set to MultiZoneNatGateway.
133+
NatGatewayName string `json:"natGateway"`
134+
}
135+
113136
// KeyVault defines an Azure Key Vault.
114137
type KeyVault struct {
115138
// ResourceGroup defines the Azure resource group used by the key

0 commit comments

Comments
 (0)