Skip to content

Commit

Permalink
Reserve Static IPv6 address before syncing L4 NetLB
Browse files Browse the repository at this point in the history
This will prevent losing address while recreating forwarding rule
  • Loading branch information
panslava committed Jun 8, 2023
1 parent b09b781 commit 6c37b1a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 10 deletions.
54 changes: 44 additions & 10 deletions pkg/loadbalancers/forwarding_rules_ipv6.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/cloud-provider-gcp/providers/gce"
"k8s.io/ingress-gce/pkg/composite"
"k8s.io/ingress-gce/pkg/events"
Expand Down Expand Up @@ -128,19 +129,51 @@ func (l4 *L4) deleteChangedIPv6ForwardingRule(existingFwdRule *composite.Forward
func (l4netlb *L4NetLB) ensureIPv6ForwardingRule(bsLink string) (*composite.ForwardingRule, error) {
start := time.Now()

expectedIPv6FwdRule, err := l4netlb.buildExpectedIPv6ForwardingRule(bsLink)
klog.V(2).Infof("Ensuring external ipv6 forwarding rule for L4 NetLB Service %s/%s, backend service link: %s", l4netlb.Service.Namespace, l4netlb.Service.Name, bsLink)
defer func() {
klog.V(2).Infof("Finished ensuring external ipv6 forwarding rule for L4 NetLB Service %s/%s, time taken: %v", l4netlb.Service.Namespace, l4netlb.Service.Name, time.Since(start))
}()

expectedIPv6FrName := l4netlb.ipv6FRName()
existingIPv6FwdRule, err := l4netlb.forwardingRules.Get(expectedIPv6FrName)
if err != nil {
return nil, fmt.Errorf("l4netlb.buildExpectedIPv6ForwardingRule(%s) returned error %w, want nil", bsLink, err)
klog.Errorf("l4netlb.forwardingRules.Get(%s) returned error %v", expectedIPv6FrName, err)
return nil, err
}

klog.V(2).Infof("Ensuring external ipv6 forwarding rule %s for L4 NetLB Service %s/%s, backend service link: %s", expectedIPv6FwdRule.Name, l4netlb.Service.Namespace, l4netlb.Service.Name, bsLink)
defer func() {
klog.V(2).Infof("Finished ensuring external ipv6 forwarding rule %s for L4 NetLB Service %s/%s, time taken: %v", expectedIPv6FwdRule.Name, l4netlb.Service.Namespace, l4netlb.Service.Name, time.Since(start))
}()
customSubnetName := gce.GetLoadBalancerAnnotationSubnet(l4netlb.Service)
subnetworkURL := l4netlb.cloud.SubnetworkURL()
if customSubnetName != "" {
subnetworkURL, err = l4netlb.getSubnetworkURLByName(customSubnetName)
if err != nil {
return nil, err
}
}

// Determine IP which will be used for this LB. If no forwarding rule has been established
// or specified in the Service spec, then requestedIP = "".
ipv6ToUse := ipv6IPToUse(existingIPv6FwdRule, subnetworkURL)
if !l4netlb.cloud.IsLegacyNetwork() {
nm := types.NamespacedName{Namespace: l4netlb.Service.Namespace, Name: l4netlb.Service.Name}.String()
addrMgr := newAddressManager(l4netlb.cloud, nm, l4netlb.cloud.Region(), subnetworkURL, expectedIPv6FrName, ipv6ToUse, cloud.SchemeExternal, cloud.NetworkTierPremium, IPv6Version)

ipv6ToUse, _, err = addrMgr.HoldAddress()
if err != nil {
return nil, err
}
klog.V(2).Infof("ensureIPv6ForwardingRule(%v): reserved IP %q for the forwarding rule %s", nm, ipv6ToUse, expectedIPv6FrName)
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("ensureIPv6ForwardingRule: failed to release address reservation, possibly causing an orphan: %v", err)
}
}()
}

existingIPv6FwdRule, err := l4netlb.forwardingRules.Get(expectedIPv6FwdRule.Name)
expectedIPv6FwdRule, err := l4netlb.buildExpectedIPv6ForwardingRule(bsLink, ipv6ToUse, subnetworkURL)
if err != nil {
return nil, fmt.Errorf("l4netlb.forwardingRules.GetForwardingRule(%s) returned error %w, want nil", expectedIPv6FwdRule.Name, err)
return nil, fmt.Errorf("l4netlb.buildExpectedIPv6ForwardingRule(%s) returned error %w, want nil", bsLink, err)
}

if existingIPv6FwdRule != nil {
Expand All @@ -167,7 +200,7 @@ func (l4netlb *L4NetLB) ensureIPv6ForwardingRule(bsLink string) (*composite.Forw
return createdFr, err
}

func (l4netlb *L4NetLB) buildExpectedIPv6ForwardingRule(bsLink string) (*composite.ForwardingRule, error) {
func (l4netlb *L4NetLB) buildExpectedIPv6ForwardingRule(bsLink, ipv6ToUse, subnetworkURL string) (*composite.ForwardingRule, error) {
frName := l4netlb.ipv6FRName()

frDesc, err := utils.MakeL4IPv6ForwardingRuleDescription(l4netlb.Service)
Expand All @@ -181,13 +214,14 @@ func (l4netlb *L4NetLB) buildExpectedIPv6ForwardingRule(bsLink string) (*composi
fr := &composite.ForwardingRule{
Name: frName,
Description: frDesc,
IPAddress: ipv6ToUse,
IPProtocol: protocol,
PortRange: portRange,
LoadBalancingScheme: string(cloud.SchemeExternal),
BackendService: bsLink,
IpVersion: IPv6Version,
NetworkTier: cloud.NetworkTierPremium.ToGCEValue(),
Subnetwork: l4netlb.cloud.SubnetworkURL(),
Subnetwork: subnetworkURL,
}

return fr, nil
Expand Down
8 changes: 8 additions & 0 deletions pkg/loadbalancers/l4netlb.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,11 @@ func (l4netlb *L4NetLB) hasAnnotation(annotationKey string) bool {
func (l4netlb *L4NetLB) frName() string {
return utils.LegacyForwardingRuleName(l4netlb.Service)
}

func (l4netlb *L4NetLB) getSubnetworkURLByName(subnetName string) (string, error) {
subnetKey, err := l4netlb.createKey(subnetName)
if err != nil {
return "", err
}
return cloud.SelfLink(meta.VersionGA, l4netlb.cloud.NetworkProjectID(), "subnetworks", subnetKey), nil
}

0 comments on commit 6c37b1a

Please sign in to comment.