Sticky Session Implementation

- Added process to cleanup stale session affinity records
- Automatically set cloud provided load balancer for sticky session if the service requires it - Note, this only works on GCE right now.
- Changed sessionAffinityMap a map to pointers instead of structs to improve performance
- Commented out cookie and protocol from sessionAffinityDetail to avoid confusion as it is not yet implemented.
This commit is contained in:
Mike Foley
2014-12-18 18:46:10 -05:00
parent c34f2d354c
commit c4e94efe16
8 changed files with 457 additions and 53 deletions

View File

@@ -48,7 +48,7 @@ type TCPLoadBalancer interface {
// TODO: Break this up into different interfaces (LB, etc) when we have more than one type of service
TCPLoadBalancerExists(name, region string) (bool, error)
// CreateTCPLoadBalancer creates a new tcp load balancer. Returns the IP address of the balancer
CreateTCPLoadBalancer(name, region string, externalIP net.IP, port int, hosts []string) (net.IP, error)
CreateTCPLoadBalancer(name, region string, externalIP net.IP, port int, hosts []string, affinityType api.AffinityType) (net.IP, error)
// UpdateTCPLoadBalancer updates hosts under the specified load balancer.
UpdateTCPLoadBalancer(name, region string, hosts []string) error
// DeleteTCPLoadBalancer deletes a specified load balancer.

View File

@@ -84,7 +84,7 @@ func (f *FakeCloud) TCPLoadBalancerExists(name, region string) (bool, error) {
// CreateTCPLoadBalancer is a test-spy implementation of TCPLoadBalancer.CreateTCPLoadBalancer.
// It adds an entry "create" into the internal method call record.
func (f *FakeCloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, port int, hosts []string) (net.IP, error) {
func (f *FakeCloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, port int, hosts []string, affinityType api.AffinityType) (net.IP, error) {
f.addCall("create")
return f.ExternalIP, f.Err
}

View File

@@ -155,14 +155,27 @@ func makeHostLink(projectID, zone, host string) string {
projectID, zone, host)
}
func (gce *GCECloud) makeTargetPool(name, region string, hosts []string) (string, error) {
// Session Affinity Type string
type GCEAffinityType string
const (
// AffinityTypeNone - no session affinity.
GCEAffinityTypeNone GCEAffinityType = "None"
// AffinityTypeClientIP is the Client IP based.
GCEAffinityTypeClientIP GCEAffinityType = "CLIENT_IP"
// AffinityTypeClientIP is the Client IP based.
GCEAffinityTypeClientIPProto GCEAffinityType = "CLIENT_IP_PROTO"
)
func (gce *GCECloud) makeTargetPool(name, region string, hosts []string, affinityType GCEAffinityType) (string, error) {
var instances []string
for _, host := range hosts {
instances = append(instances, makeHostLink(gce.projectID, gce.zone, host))
}
pool := &compute.TargetPool{
Name: name,
Instances: instances,
Name: name,
Instances: instances,
SessionAffinity: string(affinityType),
}
_, err := gce.service.TargetPools.Insert(gce.projectID, region, pool).Do()
if err != nil {
@@ -191,9 +204,22 @@ func (gce *GCECloud) TCPLoadBalancerExists(name, region string) (bool, error) {
return false, err
}
//translate from what K8s supports to what the cloud provider supports for session affinity.
func translateAffinityType(affinityType api.AffinityType) GCEAffinityType {
switch affinityType {
case api.AffinityTypeClientIP:
return GCEAffinityTypeClientIP
case api.AffinityTypeNone:
return GCEAffinityTypeNone
default:
glog.Errorf("unexpected affinity type: %v", affinityType)
return GCEAffinityTypeNone
}
}
// CreateTCPLoadBalancer is an implementation of TCPLoadBalancer.CreateTCPLoadBalancer.
func (gce *GCECloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, port int, hosts []string) (net.IP, error) {
pool, err := gce.makeTargetPool(name, region, hosts)
func (gce *GCECloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, port int, hosts []string, affinityType api.AffinityType) (net.IP, error) {
pool, err := gce.makeTargetPool(name, region, hosts, translateAffinityType(affinityType))
if err != nil {
return nil, err
}