Commit 55daf3b8 authored by Dr. Stefan Schimanski's avatar Dr. Stefan Schimanski

Don't wrongly identify endpoint addresses only due to equal IP

Before this patch the endpoint IP was used to identify endpoint addresses. This leads to wrong unification of endpoints of different pods having the same IP (e.g. non container IP in case of Mesos). This patch takes the EndpointAddress.targetRef.UID into consideration as well.
parent 67d45821
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"sort" "sort"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
) )
...@@ -33,31 +34,35 @@ import ( ...@@ -33,31 +34,35 @@ import (
// form for things like comparison. The result is a newly allocated slice. // form for things like comparison. The result is a newly allocated slice.
func RepackSubsets(subsets []api.EndpointSubset) []api.EndpointSubset { func RepackSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
// First map each unique port definition to the sets of hosts that // First map each unique port definition to the sets of hosts that
// offer it. The sets of hosts must be de-duped, using IP as the key. // offer it. The sets of hosts must be de-duped, using IP+UID as the key.
type ipString string type addressKey struct {
allAddrs := map[ipString]*api.EndpointAddress{} ip string
uid types.UID
}
allAddrs := map[addressKey]*api.EndpointAddress{}
portsToAddrs := map[api.EndpointPort]addressSet{} portsToAddrs := map[api.EndpointPort]addressSet{}
for i := range subsets { for i := range subsets {
for j := range subsets[i].Ports { for j := range subsets[i].Ports {
epp := &subsets[i].Ports[j] epp := &subsets[i].Ports[j]
for k := range subsets[i].Addresses { for k := range subsets[i].Addresses {
epa := &subsets[i].Addresses[k] epa := &subsets[i].Addresses[k]
ipstr := ipString(epa.IP) ak := addressKey{ip: epa.IP}
// Accumulate the most "complete" address we can. if epa.TargetRef != nil {
if allAddrs[ipstr] == nil { ak.uid = epa.TargetRef.UID
}
// Accumulate the address.
if allAddrs[ak] == nil {
// Make a copy so we don't write to the // Make a copy so we don't write to the
// input args of this function. // input args of this function.
p := &api.EndpointAddress{} p := &api.EndpointAddress{}
*p = *epa *p = *epa
allAddrs[ipstr] = p allAddrs[ak] = p
} else if allAddrs[ipstr].TargetRef == nil {
allAddrs[ipstr].TargetRef = epa.TargetRef
} }
// Remember that this port maps to this address. // Remember that this port maps to this address.
if _, found := portsToAddrs[*epp]; !found { if _, found := portsToAddrs[*epp]; !found {
portsToAddrs[*epp] = addressSet{} portsToAddrs[*epp] = addressSet{}
} }
portsToAddrs[*epp].Insert(allAddrs[ipstr]) portsToAddrs[*epp].Insert(allAddrs[ak])
} }
} }
} }
...@@ -104,18 +109,32 @@ func hashAddresses(addrs addressSet) string { ...@@ -104,18 +109,32 @@ func hashAddresses(addrs addressSet) string {
for k := range addrs { for k := range addrs {
slice = append(slice, k) slice = append(slice, k)
} }
sort.Sort(addrPtrsByIP(slice)) sort.Sort(addrPtrsByIpAndUID(slice))
hasher := md5.New() hasher := md5.New()
util.DeepHashObject(hasher, slice) util.DeepHashObject(hasher, slice)
return hex.EncodeToString(hasher.Sum(nil)[0:]) return hex.EncodeToString(hasher.Sum(nil)[0:])
} }
type addrPtrsByIP []*api.EndpointAddress func LessEndpointAddress(a, b *api.EndpointAddress) bool {
ipComparison := bytes.Compare([]byte(a.IP), []byte(b.IP))
if ipComparison != 0 {
return ipComparison < 0
}
if (b.TargetRef == nil) {
return false
}
if (a.TargetRef == nil) {
return true
}
return a.TargetRef.UID < b.TargetRef.UID
}
type addrPtrsByIpAndUID []*api.EndpointAddress
func (sl addrPtrsByIP) Len() int { return len(sl) } func (sl addrPtrsByIpAndUID) Len() int { return len(sl) }
func (sl addrPtrsByIP) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } func (sl addrPtrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl addrPtrsByIP) Less(i, j int) bool { func (sl addrPtrsByIpAndUID) Less(i, j int) bool {
return bytes.Compare([]byte(sl[i].IP), []byte(sl[j].IP)) < 0 return LessEndpointAddress(sl[i], sl[j])
} }
// SortSubsets sorts an array of EndpointSubset objects in place. For ease of // SortSubsets sorts an array of EndpointSubset objects in place. For ease of
...@@ -123,7 +142,7 @@ func (sl addrPtrsByIP) Less(i, j int) bool { ...@@ -123,7 +142,7 @@ func (sl addrPtrsByIP) Less(i, j int) bool {
func SortSubsets(subsets []api.EndpointSubset) []api.EndpointSubset { func SortSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
for i := range subsets { for i := range subsets {
ss := &subsets[i] ss := &subsets[i]
sort.Sort(addrsByIP(ss.Addresses)) sort.Sort(addrsByIpAndUID(ss.Addresses))
sort.Sort(portsByHash(ss.Ports)) sort.Sort(portsByHash(ss.Ports))
} }
sort.Sort(subsetsByHash(subsets)) sort.Sort(subsetsByHash(subsets))
...@@ -146,12 +165,12 @@ func (sl subsetsByHash) Less(i, j int) bool { ...@@ -146,12 +165,12 @@ func (sl subsetsByHash) Less(i, j int) bool {
return bytes.Compare(h1, h2) < 0 return bytes.Compare(h1, h2) < 0
} }
type addrsByIP []api.EndpointAddress type addrsByIpAndUID []api.EndpointAddress
func (sl addrsByIP) Len() int { return len(sl) } func (sl addrsByIpAndUID) Len() int { return len(sl) }
func (sl addrsByIP) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } func (sl addrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl addrsByIP) Less(i, j int) bool { func (sl addrsByIpAndUID) Less(i, j int) bool {
return bytes.Compare([]byte(sl[i].IP), []byte(sl[j].IP)) < 0 return LessEndpointAddress(&sl[i], &sl[j])
} }
type portsByHash []api.EndpointPort type portsByHash []api.EndpointPort
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment