Skip to content

Commit 71713ba

Browse files
committed
azure: Fix Load balancer IP setup
Fixing the issue where the load balancer IP was not set in the range of the machine network CIDRs by setting it to the first IP in the CIDR range. Also extending this logic to non-existing vnet installs since the problem can happen even during normal installs.
1 parent 690783b commit 71713ba

File tree

1 file changed

+108
-21
lines changed

1 file changed

+108
-21
lines changed

pkg/asset/manifests/azure/cluster.go

Lines changed: 108 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
azic "github.com/openshift/installer/pkg/asset/installconfig/azure"
1818
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
1919
"github.com/openshift/installer/pkg/asset/manifests/capiutils/cidr"
20+
"github.com/openshift/installer/pkg/ipnet"
2021
"github.com/openshift/installer/pkg/types"
2122
"github.com/openshift/installer/pkg/types/azure"
2223
)
@@ -104,6 +105,48 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
104105
}
105106

106107
virtualNetworkID := ""
108+
lbip := capz.DefaultInternalLBIPAddress
109+
lbip = getIPWithinCIDR(subnets, lbip)
110+
111+
if controlPlaneSub := installConfig.Config.Azure.ControlPlaneSubnet; controlPlaneSub != "" {
112+
client, err := installConfig.Azure.Client()
113+
if err != nil {
114+
return nil, fmt.Errorf("failed to get azure client: %w", err)
115+
}
116+
ctx := context.TODO()
117+
controlPlaneSubnet, err := client.GetControlPlaneSubnet(ctx, installConfig.Config.Azure.NetworkResourceGroupName, installConfig.Config.Azure.VirtualNetwork, controlPlaneSub)
118+
if err != nil || controlPlaneSubnet == nil {
119+
return nil, fmt.Errorf("failed to get azure control plane subnet: %w", err)
120+
} else if controlPlaneSubnet.AddressPrefixes == nil && controlPlaneSubnet.AddressPrefix == nil {
121+
return nil, fmt.Errorf("failed to get azure control plane subnet addresses: %w", err)
122+
}
123+
subnetList := []*net.IPNet{}
124+
if controlPlaneSubnet.AddressPrefixes != nil {
125+
for _, sub := range *controlPlaneSubnet.AddressPrefixes {
126+
_, ipnet, err := net.ParseCIDR(sub)
127+
if err != nil {
128+
return nil, fmt.Errorf("failed to get translate azure control plane subnet addresses: %w", err)
129+
}
130+
subnetList = append(subnetList, ipnet)
131+
}
132+
}
133+
134+
if controlPlaneSubnet.AddressPrefix != nil {
135+
_, ipnet, err := net.ParseCIDR(*controlPlaneSubnet.AddressPrefix)
136+
if err != nil {
137+
return nil, fmt.Errorf("failed to get translate azure control plane subnet address prefix: %w", err)
138+
}
139+
subnetList = append(subnetList, ipnet)
140+
}
141+
lbip = getIPWithinCIDR(subnetList, lbip)
142+
}
143+
144+
apiServerLB.FrontendIPs = []capz.FrontendIP{{
145+
Name: fmt.Sprintf("%s-internal-frontEnd", clusterID.InfraID),
146+
FrontendIPClass: capz.FrontendIPClass{
147+
PrivateIPAddress: lbip,
148+
},
149+
}}
107150
if installConfig.Config.Azure.VirtualNetwork != "" {
108151
client, err := installConfig.Azure.Client()
109152
if err != nil {
@@ -117,16 +160,12 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
117160
if virtualNetwork != nil {
118161
virtualNetworkID = *virtualNetwork.ID
119162
}
120-
lbip, err := getNextAvailableIP(ctx, installConfig)
163+
lbip, err := getNextAvailableIPForLoadBalancer(ctx, installConfig, lbip)
121164
if err != nil {
122165
return nil, err
123166
}
124-
apiServerLB.FrontendIPs = []capz.FrontendIP{{
125-
Name: fmt.Sprintf("%s-internal-frontEnd", clusterID.InfraID),
126-
FrontendIPClass: capz.FrontendIPClass{
127-
PrivateIPAddress: lbip,
128-
},
129-
},
167+
apiServerLB.FrontendIPs[0].FrontendIPClass = capz.FrontendIPClass{
168+
PrivateIPAddress: lbip,
130169
}
131170
}
132171

@@ -255,25 +294,77 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
255294
}, nil
256295
}
257296

258-
func getNextAvailableIP(ctx context.Context, installConfig *installconfig.InstallConfig) (string, error) {
259-
lbip := capz.DefaultInternalLBIPAddress
260-
machineCidr := installConfig.Config.MachineNetwork
297+
func getIPWithinCIDR(subnets []*net.IPNet, ip string) string {
298+
if subnets == nil || ip == "" {
299+
return ""
300+
}
301+
// Check if default lbip is within control plane network.
302+
// If not in control plane network, assign the first non-reserved IP in the CIDR to lbip.
303+
for _, subnet := range subnets {
304+
if subnet == nil {
305+
continue
306+
}
307+
if subnet.Contains(net.ParseIP(ip)) {
308+
return ip
309+
}
310+
}
311+
ipSubnets := make(net.IP, len(subnets[0].IP))
312+
copy(ipSubnets, subnets[0].IP)
313+
// Since the first 4 IP of the subnets are usually reserved[1], pick the next one that's available in the CIDR.
314+
// [1] - https://learn.microsoft.com/en-us/azure/virtual-network/ip-services/private-ip-addresses#allocation-method
315+
ipSubnets[len(ipSubnets)-1] += 4
316+
return ipSubnets.String()
317+
}
318+
319+
func getNextAvailableIPForLoadBalancer(ctx context.Context, installConfig *installconfig.InstallConfig, lbip string) (string, error) {
261320
client, err := installConfig.Azure.Client()
262321
if err != nil {
263322
return "", fmt.Errorf("failed to get azure client: %w", err)
264323
}
324+
networkResourceGroupName := installConfig.Config.Azure.NetworkResourceGroupName
325+
virtualNetworkName := installConfig.Config.Azure.VirtualNetwork
326+
machineCidr := installConfig.Config.MachineNetwork
327+
if cpSubnet := installConfig.Config.Azure.ControlPlaneSubnet; cpSubnet != "" {
328+
controlPlane, err := client.GetControlPlaneSubnet(ctx, networkResourceGroupName, virtualNetworkName, cpSubnet)
329+
if err != nil {
330+
return "", fmt.Errorf("failed to get control plane subnet: %w", err)
331+
}
332+
if controlPlane.AddressPrefix == nil && controlPlane.AddressPrefixes == nil {
333+
return "", fmt.Errorf("failed to get control plane subnet addresses: %w", err)
334+
}
335+
prefixes := []*ipnet.IPNet{}
336+
if controlPlane.AddressPrefixes != nil {
337+
for _, sub := range *controlPlane.AddressPrefixes {
338+
ipnet, err := ipnet.ParseCIDR(sub)
339+
if err != nil {
340+
return "", fmt.Errorf("failed to get translate azure control plane subnet addresses: %w", err)
341+
}
342+
prefixes = append(prefixes, ipnet)
343+
}
344+
}
265345

266-
availableIP, err := client.CheckIPAddressAvailability(ctx, installConfig.Config.Azure.NetworkResourceGroupName, installConfig.Config.Azure.VirtualNetwork, lbip)
346+
if controlPlane.AddressPrefix != nil {
347+
ipnet, err := ipnet.ParseCIDR(*controlPlane.AddressPrefix)
348+
if err != nil {
349+
return "", fmt.Errorf("failed to get translate azure control plane subnet address prefix: %w", err)
350+
}
351+
prefixes = append(prefixes, ipnet)
352+
}
353+
cidrRange := []types.MachineNetworkEntry{}
354+
for _, prefix := range prefixes {
355+
if prefix != nil {
356+
cidrRange = append(cidrRange, types.MachineNetworkEntry{CIDR: *prefix})
357+
}
358+
}
359+
machineCidr = cidrRange
360+
}
361+
availableIP, err := client.CheckIPAddressAvailability(ctx, networkResourceGroupName, virtualNetworkName, lbip)
267362
if err != nil {
268363
return "", fmt.Errorf("failed to get azure ip availability: %w", err)
269364
}
270365
if *availableIP.Available {
271366
for _, cidrRange := range machineCidr {
272-
_, ipnet, err := net.ParseCIDR(cidrRange.CIDR.String())
273-
if err != nil {
274-
return "", fmt.Errorf("failed to get machine network CIDR: %w", err)
275-
}
276-
if ipnet.Contains(net.ParseIP(lbip)) {
367+
if cidrRange.CIDR.Contains(net.ParseIP(lbip)) {
277368
return lbip, nil
278369
}
279370
}
@@ -283,11 +374,7 @@ func getNextAvailableIP(ctx context.Context, installConfig *installconfig.Instal
283374
}
284375
for _, ip := range *availableIP.AvailableIPAddresses {
285376
for _, cidrRange := range machineCidr {
286-
_, ipnet, err := net.ParseCIDR(cidrRange.CIDR.String())
287-
if err != nil {
288-
return "", fmt.Errorf("failed to get machine network CIDR: %w", err)
289-
}
290-
if ipnet.Contains(net.ParseIP(ip)) {
377+
if cidrRange.CIDR.Contains(net.ParseIP(lbip)) {
291378
return ip, nil
292379
}
293380
}

0 commit comments

Comments
 (0)