Skip to content

Commit

Permalink
Merge pull request #894 from skmatti/resource-leak-fix
Browse files Browse the repository at this point in the history
Bugfix: Delete unused GCE load-balancer resources on ingress spec change
  • Loading branch information
k8s-ci-robot committed Nov 13, 2019
2 parents 6a2da60 + 3d188a0 commit 4741042
Show file tree
Hide file tree
Showing 6 changed files with 389 additions and 101 deletions.
21 changes: 20 additions & 1 deletion pkg/annotations/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const (
StaticIPNameKey = "kubernetes.io/ingress.global-static-ip-name"

// PreSharedCertKey represents the specific pre-shared SSL
// certicate for the Ingress controller to use. The controller *does not*
// certificate for the Ingress controller to use. The controller *does not*
// manage this certificate, it is the users responsibility to create/delete it.
// In GCP, the Ingress controller assigns the SSL certificate with this name
// to the target proxies of the Ingress.
Expand Down Expand Up @@ -77,6 +77,25 @@ const (
// - annotations:
// networking.gke.io/v1beta1.FrontendConfig: 'my-frontendconfig'
FrontendConfigKey = "networking.gke.io/v1beta1.FrontendConfig"

// UrlMapKey is the annotation key used by controller to record GCP URL map.
UrlMapKey = StatusPrefix + "/url-map"
// HttpForwardingRuleKey is the annotation key used by controller to record
// GCP http forwarding rule.
HttpForwardingRuleKey = StatusPrefix + "/forwarding-rule"
// HttpsForwardingRuleKey is the annotation key used by controller to record
// GCP https forwarding rule.
HttpsForwardingRuleKey = StatusPrefix + "/https-forwarding-rule"
// TargetHttpProxyKey is the annotation key used by controller to record
// GCP target http proxy.
TargetHttpProxyKey = StatusPrefix + "/target-proxy"
// TargetHttpsProxyKey is the annotation key used by controller to record
// GCP target https proxy.
TargetHttpsProxyKey = StatusPrefix + "/https-target-proxy"
// SSLCertKey is the annotation key used by controller to record GCP ssl cert.
SSLCertKey = StatusPrefix + "/ssl-cert"
// StaticIPKey is the annotation key used by controller to record GCP static ip.
StaticIPKey = StatusPrefix + "/static-ip"
)

// Ingress represents ingress annotations.
Expand Down
2 changes: 2 additions & 0 deletions pkg/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ var (
ASMConfigMapBasedConfigNamespace string
ASMConfigMapBasedConfigCMName string
EnableNonGCPMode bool
EnableDeleteUnusedFrontends bool

LeaderElection LeaderElectionConfiguration
}{}
Expand Down Expand Up @@ -206,6 +207,7 @@ L7 load balancing. CSV values accepted. Example: -node-port-ranges=80,8080,400-5
flag.StringVar(&F.ASMConfigMapBasedConfigNamespace, "asm-configmap-based-config-namespace", "kube-system,istio-system", "ASM Configmap based config: configmap namespace")
flag.StringVar(&F.ASMConfigMapBasedConfigCMName, "asm-configmap-based-config-cmname", "ingress-controller-asm-cm-config", "ASM Configmap based config: configmap name")
flag.BoolVar(&F.EnableNonGCPMode, "enable-non-gcp-mode", false, "Set to true when running on a non-GCP cluster.")
flag.BoolVar(&F.EnableDeleteUnusedFrontends, "enable-delete-unused-frontends", false, "Enable deleting unused gce frontend resources.")
}

type RateLimitSpecs struct {
Expand Down
21 changes: 15 additions & 6 deletions pkg/loadbalancers/addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"net/http"

"google.golang.org/api/compute/v1"
"k8s.io/ingress-gce/pkg/annotations"
"k8s.io/ingress-gce/pkg/flags"
"k8s.io/ingress-gce/pkg/utils"
"k8s.io/ingress-gce/pkg/utils/namer"
"k8s.io/klog"
Expand All @@ -31,26 +33,33 @@ func (l *L7) checkStaticIP() (err error) {
if l.fw == nil || l.fw.IPAddress == "" {
return fmt.Errorf("will not create static IP without a forwarding rule")
}
managedStaticIPName := l.namer.ForwardingRule(namer.HTTPProtocol)
// Don't manage staticIPs if the user has specified an IP.
if address, manageStaticIP := l.getEffectiveIP(); !manageStaticIP {
klog.V(3).Infof("Not managing user specified static IP %v", address)
if flags.F.EnableDeleteUnusedFrontends {
// Delete ingress controller managed static ip if exists.
if ip, ok := l.ingress.Annotations[annotations.StaticIPKey]; ok && ip == managedStaticIPName {
return l.deleteStaticIP()
}
}
return nil
}
staticIPName := l.namer.ForwardingRule(namer.HTTPProtocol)
ip, _ := l.cloud.GetGlobalAddress(staticIPName)

ip, _ := l.cloud.GetGlobalAddress(managedStaticIPName)
if ip == nil {
klog.V(3).Infof("Creating static ip %v", staticIPName)
err = l.cloud.ReserveGlobalAddress(&compute.Address{Name: staticIPName, Address: l.fw.IPAddress})
klog.V(3).Infof("Creating static ip %v", managedStaticIPName)
err = l.cloud.ReserveGlobalAddress(&compute.Address{Name: managedStaticIPName, Address: l.fw.IPAddress})
if err != nil {
if utils.IsHTTPErrorCode(err, http.StatusConflict) ||
utils.IsHTTPErrorCode(err, http.StatusBadRequest) {
klog.V(3).Infof("IP %v(%v) is already reserved, assuming it is OK to use.",
l.fw.IPAddress, staticIPName)
l.fw.IPAddress, managedStaticIPName)
return nil
}
return err
}
ip, err = l.cloud.GetGlobalAddress(staticIPName)
ip, err = l.cloud.GetGlobalAddress(managedStaticIPName)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 4741042

Please sign in to comment.