Skip to content

Commit

Permalink
internal lb private IP webhook default
Browse files Browse the repository at this point in the history
  • Loading branch information
Cecile Robert-Michon committed Oct 6, 2020
1 parent c9011ad commit 9bd7254
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 69 deletions.
16 changes: 12 additions & 4 deletions api/v1alpha3/azurecluster_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const (
DefaultControlPlaneSubnetCIDR = "10.0.0.0/16"
// DefaultNodeSubnetCIDR is the default Node Subnet CIDR
DefaultNodeSubnetCIDR = "10.1.0.0/16"
// DefaultInternalLBIPAddress is the default internal load balancer ip address
DefaultInternalLBIPAddress = "10.0.0.100"
)

const (
Expand All @@ -36,6 +38,8 @@ const (
DefaultControlPlaneSubnetIPv6CIDR = "2001:1234:5678:9abc::/64"
// DefaultNodeSubnetIPv6CIDR is the default Node Subnet CIDR
DefaultNodeSubnetIPv6CIDR = "2001:1234:5678:9abd::/64"
// DefaultInternalLBIPv6Address is the default internal load balancer ip address
DefaultInternalLBIPv6Address = "2001:1234:5678:9abc::100"
)

func (c *AzureCluster) setDefaults() {
Expand Down Expand Up @@ -136,11 +140,15 @@ func (c *AzureCluster) setAPIServerLBDefaults() {
lb.Name = generateInternalLBName(c.ObjectMeta.Name)
}
if len(lb.FrontendIPs) == 0 {
// for back compat, set the private IP to the subnet InternalLBIPAddress value.
privateIP := c.Spec.NetworkSpec.GetControlPlaneSubnet().InternalLBIPAddress
if privateIP == "" {
privateIP = DefaultInternalLBIPAddress
}
lb.FrontendIPs = []FrontendIP{
{
Name: generateFrontendIPConfigName(lb.Name),
// for back compat, set the private IP to the subnet InternalLBIPAddress value.
PrivateIPAddress: c.Spec.NetworkSpec.GetControlPlaneSubnet().InternalLBIPAddress,
Name: generateFrontendIPConfigName(lb.Name),
PrivateIPAddress: privateIP,
},
}
}
Expand Down Expand Up @@ -195,4 +203,4 @@ func generatePublicIPName(clusterName string) string {
// generateFrontendIPConfigName generates a load balancer frontend IP config name.
func generateFrontendIPConfigName(lbName string) string {
return fmt.Sprintf("%s-%s", lbName, "frontEnd")
}
}
7 changes: 0 additions & 7 deletions cloud/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,6 @@ import (
const (
// DefaultUserName is the default username for created vm
DefaultUserName = "capi"
// DefaultInternalLBIPAddress is the default internal load balancer ip address
DefaultInternalLBIPAddress = "10.0.0.100"
)

const (
// DefaultInternalLBIPv6Address is the default internal load balancer ip address
DefaultInternalLBIPv6Address = "2001:1234:5678:9abc::100"
)

const (
Expand Down
63 changes: 5 additions & 58 deletions cloud/services/loadbalancers/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ package loadbalancers

import (
"context"
"strings"

"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network"
"github.com/Azure/go-autorest/autorest/to"
"github.com/pkg/errors"
Expand All @@ -33,13 +31,13 @@ func (s *Service) Reconcile(ctx context.Context) error {
for _, lbSpec := range s.Scope.LBSpecs() {
s.Scope.V(2).Info("creating load balancer", "load balancer", lbSpec.Name)

frontendIPConfigs, frontendIDs, err := s.getFrontendIPConfigs(ctx, lbSpec)
frontendIPConfigs, frontendIDs, err := s.getFrontendIPConfigs(lbSpec)
if err != nil {
return err
}

lb := network.LoadBalancer{
Name: to.StringPtr(lbSpec.Name),
Name: to.StringPtr(lbSpec.Name),
Sku: &network.LoadBalancerSku{Name: network.LoadBalancerSkuNameStandard},
Location: to.StringPtr(s.Scope.Location()),
Tags: converters.TagsToMap(infrav1.Build(infrav1.BuildParams{
Expand Down Expand Up @@ -142,69 +140,18 @@ func (s *Service) Delete(ctx context.Context) error {
return nil
}

// getAvailablePrivateIP checks if the desired private IP address is available in a virtual network.
// If the IP address is taken or empty, it will make an attempt to find an available IP in the same subnet
// NOTE: this does not work for VNets with ipv6 CIDRs currently
func (s *Service) getAvailablePrivateIP(ctx context.Context, resourceGroup, vnetName, PreferredIPAddress string, subnetCIDRs []string) (string, error) {
if len(subnetCIDRs) == 0 {
return "", errors.Errorf("failed to find available IP: control plane subnet CIDRs should not be empty")
}
ip := PreferredIPAddress
if ip == "" {
ip = azure.DefaultInternalLBIPAddress
subnetCIDR := subnetCIDRs[0]
if subnetCIDR != infrav1.DefaultControlPlaneSubnetCIDR {
// If the user provided a custom subnet CIDR without providing a private IP, try finding an available IP in the subnet space
index := strings.LastIndex(subnetCIDR, ".")
ip = subnetCIDR[0:(index+1)] + "0"
}
}

result, err := s.VirtualNetworksClient.CheckIPAddressAvailability(ctx, resourceGroup, vnetName, ip)
if err != nil {
return "", errors.Wrap(err, "failed to check IP availability")
}
if !to.Bool(result.Available) {
if len(to.StringSlice(result.AvailableIPAddresses)) == 0 {
return "", errors.Errorf("IP %s is not available in VNet %s and there were no other available IPs found", ip, vnetName)
}
// TODO: make sure that the returned IP is in the right subnet since this check is done at the VNet level
ip = to.StringSlice(result.AvailableIPAddresses)[0]
}
return ip, nil
}

func (s *Service) getFrontendIPConfigs(ctx context.Context, lbSpec azure.LBSpec) ([]network.FrontendIPConfiguration, []network.SubResource, error) {
func (s *Service) getFrontendIPConfigs(lbSpec azure.LBSpec) ([]network.FrontendIPConfiguration, []network.SubResource, error) {
var frontendIPConfigurations []network.FrontendIPConfiguration
frontendIDs := make([]network.SubResource, 0)
for _, ipConfig := range lbSpec.FrontendIPConfigs {
var properties network.FrontendIPConfigurationPropertiesFormat
if lbSpec.Type == infrav1.Internal {
var privateIP string
// We check if there is an existing internal load balancer for back compat.
internalLB, err := s.Client.Get(ctx, s.Scope.ResourceGroup(), lbSpec.Name)
if err == nil {
ipConfigs := internalLB.LoadBalancerPropertiesFormat.FrontendIPConfigurations
if ipConfigs != nil && len(*ipConfigs) > 0 {
privateIP = to.String((*ipConfigs)[0].FrontendIPConfigurationPropertiesFormat.PrivateIPAddress)
}
} else if azure.ResourceNotFound(err) {
s.Scope.V(2).Info("internalLB not found in RG", "internal lb", lbSpec.Name, "resource group", s.Scope.ResourceGroup())
privateIP, err = s.getAvailablePrivateIP(ctx, s.Scope.Vnet().ResourceGroup, s.Scope.Vnet().Name, ipConfig.PrivateIPAddress, lbSpec.SubnetCidrs)
if err != nil {
return frontendIPConfigurations, frontendIDs, err
}
s.Scope.V(2).Info("setting internal load balancer IP", "private ip", privateIP)
ipConfig.PrivateIPAddress = privateIP
} else {
return frontendIPConfigurations, frontendIDs, errors.Wrap(err, "failed to look for existing internal LB")
}
properties = network.FrontendIPConfigurationPropertiesFormat{
PrivateIPAllocationMethod: network.Static,
Subnet: &network.Subnet{
ID: to.StringPtr(azure.SubnetID(s.Scope.SubscriptionID(), s.Scope.Vnet().ResourceGroup, s.Scope.Vnet().Name, lbSpec.SubnetName)),
},
PrivateIPAddress: to.StringPtr(privateIP),
PrivateIPAddress: to.StringPtr(ipConfig.PrivateIPAddress),
}
} else {
properties = network.FrontendIPConfigurationPropertiesFormat{
Expand All @@ -222,4 +169,4 @@ func (s *Service) getFrontendIPConfigs(ctx context.Context, lbSpec azure.LBSpec)
})
}
return frontendIPConfigurations, frontendIDs, nil
}
}

0 comments on commit 9bd7254

Please sign in to comment.