Set balancing mode
@@ -20,6 +20,7 @@ import (
"fmt"
"net/http"
"strconv"
+ "strings"
"time"
"k8s.io/kubernetes/pkg/util/sets"
@@ -32,6 +33,41 @@ import (
"k8s.io/ingress/controllers/gce/utils"
)
+// BalancingMode represents the loadbalancing configuration of an individual
+// Backend in a BackendService. This is *effectively* a cluster wide setting
+// since you can't mix modes across Backends pointing to the same IG, and you
+// can't have a single node in more than 1 loadbalanced IG.
+type BalancingMode string
+
+const (
+ // Rate balances incoming requests based on observed RPS.
+ // As of this writing, it's the only balancing mode supported by GCE's
+ // internal LB. This setting doesn't make sense for Kubernets clusters
+ // because requests can get proxied between instance groups in different
+ // zones by kube-proxy without GCE even knowing it. Setting equal RPS on
+ // all IGs should achieve roughly equal distribution of requests.
+ Rate BalancingMode = "RATE"
+ // Utilization balances incoming requests based on observed utilization.
+ // This mode is only useful if you want to divert traffic away from IGs
+ // running other compute intensive workloads. Utilization statistics are
+ // aggregated per instances, not per container, and requests can get proxied
+ // between instance groups in different zones by kube-proxy without GCE even
+ // knowing about it.
+ Utilization BalancingMode = "UTILIZATION"
+ // Connections balances incoming requests based on a connection counter.
+ // This setting currently doesn't make sense for Kubernetes clusters,
+ // because we use NodePort Services as HTTP LB backends, so GCE's connection
+ // counters don't accurately represent connections per container.
+ Connections BalancingMode = "CONNECTION"
+)
+
+// maxRPS is the RPS setting for all Backends with BalancingMode RATE. The exact
+// value doesn't matter, as long as it's the same for all Backends. Requests
+// received by GCLB above this RPS are NOT dropped, GCLB continues to distribute
+// them across IGs.
+// TODO: Should this be math.MaxInt64?
+const maxRPS = 1
+
// Backends implements BackendPool.
type Backends struct {
cloud BackendServices
@@ -116,21 +152,36 @@ func (b *Backends) create(igs []*compute.InstanceGroup, namedPort *compute.Named
if err != nil {
return nil, err
}
+ errs := []string{}
+ for _, bm := range []BalancingMode{Rate, Utilization} {
+ backends := getBackendsForIGs(igs)
+ for _, b := range backends {
+ switch bm {
+ case Rate:
+ b.MaxRate = maxRPS
+ default:
+ // TODO: Set utilization and connection limits when we accept them
+ // as valid fields.
+ }
+ b.BalancingMode = string(bm)
+ }
// Create a new backend
backend := &compute.BackendService{
Name: name,
Protocol: "HTTP",
- Backends: getBackendsForIGs(igs),
- // Api expects one, means little to kubernetes.
+ Backends: backends,
HealthChecks: []string{hc.SelfLink},
Port: namedPort.Port,
PortName: namedPort.Name,
}
if err := b.cloud.CreateBackendService(backend); err != nil {
- return nil, err
+ glog.Infof("Error creating backend service with balancing mode %v", bm)
+ errs = append(errs, fmt.Sprintf("%v", err))
}
return b.Get(namedPort.Port)
}
+ return nil, fmt.Errorf("%v", strings.Join(errs, "\n"))
+}
// Add will get or create a Backend for the given port.
func (b *Backends) Add(port int64) error {
