in pkg/loadbalancers/forwarding_rules.go [198:297]
func (l *L4) ensureForwardingRule(loadBalancerName, bsLink string, options gce.ILBOptions, existingFwdRule *composite.ForwardingRule) (*composite.ForwardingRule, error) {
key, err := l.CreateKey(loadBalancerName)
if err != nil {
return nil, err
}
// version used for creating the existing forwarding rule.
version := meta.VersionGA
if l.cloud.IsLegacyNetwork() {
l.recorder.Event(l.Service, v1.EventTypeWarning, "ILBOptionsIgnored", "Internal LoadBalancer options are not supported with Legacy Networks.")
options = gce.ILBOptions{}
}
subnetworkURL := l.cloud.SubnetworkURL()
// Custom subnet feature is always enabled when running L4 controller.
// Changes to subnet annotation will be picked up and reflected in the forwarding rule.
// Removing the annotation will set the forwarding rule to use the default subnet.
if options.SubnetName != "" {
subnetKey := *key
subnetKey.Name = options.SubnetName
subnetworkURL = cloud.SelfLink(meta.VersionGA, l.cloud.NetworkProjectID(), "subnetworks", &subnetKey)
}
// Determine IP which will be used for this LB. If no forwarding rule has been established
// or specified in the Service spec, then requestedIP = "".
ipToUse := l4lbIPToUse(l.Service, existingFwdRule, subnetworkURL)
klog.V(2).Infof("ensureForwardingRule(%v): Using subnet %q for LoadBalancer IP %s", loadBalancerName, subnetworkURL, ipToUse)
var addrMgr *addressManager
// If the network is not a legacy network, use the address manager
if !l.cloud.IsLegacyNetwork() {
nm := types.NamespacedName{Namespace: l.Service.Namespace, Name: l.Service.Name}.String()
// ILB can be created only in Premium Tier
addrMgr = newAddressManager(l.cloud, nm, l.cloud.Region(), subnetworkURL, loadBalancerName, ipToUse, cloud.SchemeInternal, cloud.NetworkTierPremium)
ipToUse, err = addrMgr.HoldAddress()
if err != nil {
return nil, err
}
klog.V(2).Infof("ensureForwardingRule(%v): reserved IP %q for the forwarding rule", loadBalancerName, ipToUse)
defer func() {
// Release the address that was reserved, in all cases. If the forwarding rule was successfully created,
// the ephemeral IP is not needed anymore. If it was not created, the address should be released to prevent leaks.
if err := addrMgr.ReleaseAddress(); err != nil {
klog.Errorf("ensureInternalLoadBalancer: failed to release address reservation, possibly causing an orphan: %v", err)
}
}()
}
ports, _, _, protocol := utils.GetPortsAndProtocol(l.Service.Spec.Ports)
// Create the forwarding rule
frDesc, err := utils.MakeL4LBServiceDescription(utils.ServiceKeyFunc(l.Service.Namespace, l.Service.Name), ipToUse,
version, false, utils.ILB)
if err != nil {
return nil, fmt.Errorf("Failed to compute description for forwarding rule %s, err: %w", loadBalancerName,
err)
}
fr := &composite.ForwardingRule{
Name: loadBalancerName,
IPAddress: ipToUse,
Ports: ports,
IPProtocol: string(protocol),
LoadBalancingScheme: string(cloud.SchemeInternal),
Subnetwork: subnetworkURL,
Network: l.cloud.NetworkURL(),
NetworkTier: cloud.NetworkTierDefault.ToGCEValue(),
Version: version,
BackendService: bsLink,
AllowGlobalAccess: options.AllowGlobalAccess,
Description: frDesc,
}
if len(ports) > maxL4ILBPorts {
fr.Ports = nil
fr.AllPorts = true
}
if existingFwdRule != nil {
equal, err := Equal(existingFwdRule, fr)
if err != nil {
return existingFwdRule, err
}
if equal {
// nothing to do
klog.V(2).Infof("ensureForwardingRule: Skipping update of unchanged forwarding rule - %s", fr.Name)
return existingFwdRule, nil
}
frDiff := cmp.Diff(existingFwdRule, fr)
// If the forwarding rule pointed to a backend service which does not match the controller naming scheme,
// that resouce could be leaked. It is not being deleted here because that is a user-managed resource.
klog.V(2).Infof("ensureForwardingRule: forwarding rule changed - Existing - %+v\n, New - %+v\n, Diff(-existing, +new) - %s\n. Deleting existing forwarding rule.", existingFwdRule, fr, frDiff)
if err = utils.IgnoreHTTPNotFound(composite.DeleteForwardingRule(l.cloud, key, version)); err != nil {
return nil, err
}
l.recorder.Eventf(l.Service, corev1.EventTypeNormal, events.SyncIngress, "ForwardingRule %q deleted", key.Name)
}
klog.V(2).Infof("ensureForwardingRule: Creating/Recreating forwarding rule - %s", fr.Name)
if err = composite.CreateForwardingRule(l.cloud, key, fr); err != nil {
return nil, err
}
return composite.GetForwardingRule(l.cloud, key, fr.Version)
}