mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Updating TopologyCache to disregard unready endpoints in calculations
This commit is contained in:
parent
1367cca8fd
commit
9813ec7e8a
@ -516,7 +516,7 @@ func TestReconcile1EndpointSlicePublishNotReadyAddresses(t *testing.T) {
|
|||||||
endpointSlices := fetchEndpointSlices(t, client, namespace)
|
endpointSlices := fetchEndpointSlices(t, client, namespace)
|
||||||
for _, endpointSlice := range endpointSlices {
|
for _, endpointSlice := range endpointSlices {
|
||||||
for i, endpoint := range endpointSlice.Endpoints {
|
for i, endpoint := range endpointSlice.Endpoints {
|
||||||
if !*endpoint.Conditions.Ready {
|
if !endpointsliceutil.EndpointReady(endpoint) {
|
||||||
t.Errorf("Expected endpoints[%d] to be ready", i)
|
t.Errorf("Expected endpoints[%d] to be ready", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,16 +30,16 @@ type SliceInfo struct {
|
|||||||
Unchanged []*discovery.EndpointSlice
|
Unchanged []*discovery.EndpointSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
func (si *SliceInfo) getTotalEndpoints() int {
|
func (si *SliceInfo) getTotalReadyEndpoints() int {
|
||||||
totalEndpoints := 0
|
totalEndpoints := 0
|
||||||
for _, slice := range si.ToCreate {
|
for _, slice := range si.ToCreate {
|
||||||
totalEndpoints += len(slice.Endpoints)
|
totalEndpoints += numReadyEndpoints(slice.Endpoints)
|
||||||
}
|
}
|
||||||
for _, slice := range si.ToUpdate {
|
for _, slice := range si.ToUpdate {
|
||||||
totalEndpoints += len(slice.Endpoints)
|
totalEndpoints += numReadyEndpoints(slice.Endpoints)
|
||||||
}
|
}
|
||||||
for _, slice := range si.Unchanged {
|
for _, slice := range si.Unchanged {
|
||||||
totalEndpoints += len(slice.Endpoints)
|
totalEndpoints += numReadyEndpoints(slice.Endpoints)
|
||||||
}
|
}
|
||||||
return totalEndpoints
|
return totalEndpoints
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,15 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
discovery "k8s.io/api/discovery/v1"
|
discovery "k8s.io/api/discovery/v1"
|
||||||
|
utilpointer "k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetTotalEndpoints(t *testing.T) {
|
func Test_getTotalReadyEndpoints(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
si *SliceInfo
|
si *SliceInfo
|
||||||
expectedTotal int
|
expectedTotalReady int
|
||||||
|
expectedTotal int // this is really just testing the test helper
|
||||||
}{{
|
}{{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
si: &SliceInfo{},
|
si: &SliceInfo{},
|
||||||
@ -35,30 +37,49 @@ func TestGetTotalEndpoints(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
name: "empty slice",
|
name: "empty slice",
|
||||||
si: &SliceInfo{
|
si: &SliceInfo{
|
||||||
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(0)},
|
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(0, 0)},
|
||||||
},
|
},
|
||||||
|
expectedTotalReady: 0,
|
||||||
expectedTotal: 0,
|
expectedTotal: 0,
|
||||||
}, {
|
}, {
|
||||||
name: "multiple slices",
|
name: "multiple slices",
|
||||||
si: &SliceInfo{
|
si: &SliceInfo{
|
||||||
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(15), sliceWithNEndpoints(8)},
|
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(15, 0), sliceWithNEndpoints(8, 0)},
|
||||||
},
|
},
|
||||||
|
expectedTotalReady: 23,
|
||||||
expectedTotal: 23,
|
expectedTotal: 23,
|
||||||
}, {
|
}, {
|
||||||
name: "slices for all",
|
name: "slices for all",
|
||||||
si: &SliceInfo{
|
si: &SliceInfo{
|
||||||
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(15), sliceWithNEndpoints(8)},
|
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(15, 0), sliceWithNEndpoints(8, 0)},
|
||||||
ToUpdate: []*discovery.EndpointSlice{sliceWithNEndpoints(2)},
|
ToUpdate: []*discovery.EndpointSlice{sliceWithNEndpoints(2, 0)},
|
||||||
Unchanged: []*discovery.EndpointSlice{sliceWithNEndpoints(100), sliceWithNEndpoints(90)},
|
Unchanged: []*discovery.EndpointSlice{sliceWithNEndpoints(100, 0), sliceWithNEndpoints(90, 0)},
|
||||||
},
|
},
|
||||||
|
expectedTotalReady: 215,
|
||||||
expectedTotal: 215,
|
expectedTotal: 215,
|
||||||
|
}, {
|
||||||
|
name: "slices for all with some unready",
|
||||||
|
si: &SliceInfo{
|
||||||
|
ToCreate: []*discovery.EndpointSlice{sliceWithNEndpoints(15, 3), sliceWithNEndpoints(5, 4)},
|
||||||
|
ToUpdate: []*discovery.EndpointSlice{sliceWithNEndpoints(3, 8)},
|
||||||
|
Unchanged: []*discovery.EndpointSlice{sliceWithNEndpoints(98, 2), sliceWithNEndpoints(90, 6)},
|
||||||
|
},
|
||||||
|
expectedTotalReady: 211,
|
||||||
|
expectedTotal: 234,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
actualTotal := tc.si.getTotalEndpoints()
|
actualTotal := countEndpoints(tc.si.ToCreate) + countEndpoints(tc.si.ToUpdate) + countEndpoints(tc.si.Unchanged)
|
||||||
|
|
||||||
if actualTotal != tc.expectedTotal {
|
if actualTotal != tc.expectedTotal {
|
||||||
t.Errorf("Expected %d, got %d", tc.expectedTotal, actualTotal)
|
// This likely means that sliceWithNEndpoints or countEndpoints are not working as expected
|
||||||
|
t.Errorf("Problem with test or test helper. Expected %d total endpoints, got %d", tc.expectedTotal, actualTotal)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualTotalReady := tc.si.getTotalReadyEndpoints()
|
||||||
|
if actualTotalReady != tc.expectedTotalReady {
|
||||||
|
t.Errorf("Expected %d, got %d", tc.expectedTotalReady, actualTotalReady)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -66,14 +87,32 @@ func TestGetTotalEndpoints(t *testing.T) {
|
|||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
|
||||||
func sliceWithNEndpoints(n int) *discovery.EndpointSlice {
|
func sliceWithNEndpoints(ready, unready int) *discovery.EndpointSlice {
|
||||||
endpoints := []discovery.Endpoint{}
|
endpoints := make([]discovery.Endpoint, ready+unready)
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < ready; i++ {
|
||||||
endpoints = append(endpoints, discovery.Endpoint{Addresses: []string{fmt.Sprintf("10.1.2.%d", i)}})
|
endpoints[i] = discovery.Endpoint{
|
||||||
|
Addresses: []string{fmt.Sprintf("10.1.2.%d", i)},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < unready; i++ {
|
||||||
|
endpoints[ready+i] = discovery.Endpoint{
|
||||||
|
Addresses: []string{fmt.Sprintf("10.1.2.%d", ready+i)},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &discovery.EndpointSlice{
|
return &discovery.EndpointSlice{
|
||||||
Endpoints: endpoints,
|
Endpoints: endpoints,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func countEndpoints(slices []*discovery.EndpointSlice) int {
|
||||||
|
total := 0
|
||||||
|
for _, slice := range slices {
|
||||||
|
total += len(slice.Endpoints)
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
discovery "k8s.io/api/discovery/v1"
|
discovery "k8s.io/api/discovery/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
endpointsliceutil "k8s.io/kubernetes/pkg/controller/util/endpointslice"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -84,7 +85,7 @@ func (t *TopologyCache) GetOverloadedServices() []string {
|
|||||||
// AddHints adds or updates topology hints on EndpointSlices and returns updated
|
// AddHints adds or updates topology hints on EndpointSlices and returns updated
|
||||||
// lists of EndpointSlices to create and update.
|
// lists of EndpointSlices to create and update.
|
||||||
func (t *TopologyCache) AddHints(si *SliceInfo) ([]*discovery.EndpointSlice, []*discovery.EndpointSlice) {
|
func (t *TopologyCache) AddHints(si *SliceInfo) ([]*discovery.EndpointSlice, []*discovery.EndpointSlice) {
|
||||||
totalEndpoints := si.getTotalEndpoints()
|
totalEndpoints := si.getTotalReadyEndpoints()
|
||||||
allocations := t.getAllocations(totalEndpoints)
|
allocations := t.getAllocations(totalEndpoints)
|
||||||
|
|
||||||
if allocations == nil {
|
if allocations == nil {
|
||||||
@ -103,6 +104,10 @@ func (t *TopologyCache) AddHints(si *SliceInfo) ([]*discovery.EndpointSlice, []*
|
|||||||
// step 1: assign same-zone hints for all endpoints as a starting point.
|
// step 1: assign same-zone hints for all endpoints as a starting point.
|
||||||
for _, slice := range allocatableSlices {
|
for _, slice := range allocatableSlices {
|
||||||
for i, endpoint := range slice.Endpoints {
|
for i, endpoint := range slice.Endpoints {
|
||||||
|
if !endpointsliceutil.EndpointReady(endpoint) {
|
||||||
|
endpoint.Hints = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
if endpoint.Zone == nil || *endpoint.Zone == "" {
|
if endpoint.Zone == nil || *endpoint.Zone == "" {
|
||||||
klog.InfoS("Endpoint found without zone specified, removing hints from service", "serviceKey", si.ServiceKey)
|
klog.InfoS("Endpoint found without zone specified, removing hints from service", "serviceKey", si.ServiceKey)
|
||||||
t.RemoveHints(si.ServiceKey, si.AddressType)
|
t.RemoveHints(si.ServiceKey, si.AddressType)
|
||||||
|
@ -55,6 +55,7 @@ func TestAddHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -63,6 +64,7 @@ func TestAddHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
||||||
@ -80,9 +82,11 @@ func TestAddHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.2.4"},
|
Addresses: []string{"10.1.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -91,9 +95,11 @@ func TestAddHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.2.4"},
|
Addresses: []string{"10.1.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
||||||
@ -110,9 +116,59 @@ func TestAddHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.2.4"},
|
Addresses: []string{"10.1.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
expectedEndpointsByAddrType: map[discovery.AddressType]EndpointZoneInfo{
|
||||||
|
discovery.AddressTypeIPv4: {
|
||||||
|
"zone-a": 1,
|
||||||
|
"zone-b": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedSlicesToCreate: []*discovery.EndpointSlice{{
|
||||||
|
Endpoints: []discovery.Endpoint{{
|
||||||
|
Addresses: []string{"10.1.2.3"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}, {
|
||||||
|
Addresses: []string{"10.1.2.4"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
||||||
|
}, {
|
||||||
|
name: "slice to create with 2 ready, 1 unready, 1 unknown endpoints, zone ratios only require 2",
|
||||||
|
cpuRatiosByZone: map[string]float64{
|
||||||
|
"zone-a": 0.45,
|
||||||
|
"zone-b": 0.55,
|
||||||
|
},
|
||||||
|
sliceInfo: &SliceInfo{
|
||||||
|
ServiceKey: "ns/svc",
|
||||||
|
AddressType: discovery.AddressTypeIPv4,
|
||||||
|
ToCreate: []*discovery.EndpointSlice{{
|
||||||
|
Endpoints: []discovery.Endpoint{{
|
||||||
|
Addresses: []string{"10.1.2.3"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}, {
|
||||||
|
Addresses: []string{"10.1.2.4"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}, {
|
||||||
|
Addresses: []string{"10.1.2.5"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
|
||||||
|
}, {
|
||||||
|
Addresses: []string{"10.1.2.6"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -127,10 +183,21 @@ func TestAddHints(t *testing.T) {
|
|||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.2.4"},
|
Addresses: []string{"10.1.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}, {
|
||||||
|
Addresses: []string{"10.1.2.5"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Hints: nil,
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
|
||||||
|
}, {
|
||||||
|
Addresses: []string{"10.1.2.6"},
|
||||||
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Hints: nil,
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
expectedSlicesToUpdate: []*discovery.EndpointSlice{},
|
||||||
@ -148,40 +215,50 @@ func TestAddHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.2.4"},
|
Addresses: []string{"10.1.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.3.3"},
|
Addresses: []string{"10.1.3.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-c"),
|
Zone: utilpointer.StringPtr("zone-c"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.3.4"},
|
Addresses: []string{"10.1.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-c"),
|
Zone: utilpointer.StringPtr("zone-c"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.3.4"},
|
Addresses: []string{"10.1.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
ToUpdate: []*discovery.EndpointSlice{{
|
ToUpdate: []*discovery.EndpointSlice{{
|
||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.2.2.3"},
|
Addresses: []string{"10.2.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.2.2.4"},
|
Addresses: []string{"10.2.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.2.3.3"},
|
Addresses: []string{"10.2.3.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.2.3.4"},
|
Addresses: []string{"10.2.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-c"),
|
Zone: utilpointer.StringPtr("zone-c"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.2.3.4"},
|
Addresses: []string{"10.2.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -197,24 +274,29 @@ func TestAddHints(t *testing.T) {
|
|||||||
Addresses: []string{"10.1.2.3"},
|
Addresses: []string{"10.1.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.2.4"},
|
Addresses: []string{"10.1.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.1.3.3"},
|
Addresses: []string{"10.1.3.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-c"),
|
Zone: utilpointer.StringPtr("zone-c"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.3.4"},
|
Addresses: []string{"10.1.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-c"),
|
Zone: utilpointer.StringPtr("zone-c"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.1.3.4"},
|
Addresses: []string{"10.1.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
expectedSlicesToUpdate: []*discovery.EndpointSlice{{
|
expectedSlicesToUpdate: []*discovery.EndpointSlice{{
|
||||||
@ -222,24 +304,29 @@ func TestAddHints(t *testing.T) {
|
|||||||
Addresses: []string{"10.2.2.3"},
|
Addresses: []string{"10.2.2.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.2.2.4"},
|
Addresses: []string{"10.2.2.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Addresses: []string{"10.2.3.3"},
|
Addresses: []string{"10.2.3.3"},
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.2.3.4"},
|
Addresses: []string{"10.2.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-c"),
|
Zone: utilpointer.StringPtr("zone-c"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Addresses: []string{"10.2.3.4"},
|
Addresses: []string{"10.2.3.4"},
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
|
@ -19,9 +19,10 @@ package topologycache
|
|||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
discovery "k8s.io/api/discovery/v1"
|
discovery "k8s.io/api/discovery/v1"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
endpointsliceutil "k8s.io/kubernetes/pkg/controller/util/endpointslice"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemoveHintsFromSlices removes topology hints on EndpointSlices and returns
|
// RemoveHintsFromSlices removes topology hints on EndpointSlices and returns
|
||||||
@ -75,6 +76,10 @@ func redistributeHints(slices []*discovery.EndpointSlice, givingZones, receiving
|
|||||||
|
|
||||||
for _, slice := range slices {
|
for _, slice := range slices {
|
||||||
for i, endpoint := range slice.Endpoints {
|
for i, endpoint := range slice.Endpoints {
|
||||||
|
if !endpointsliceutil.EndpointReady(endpoint) {
|
||||||
|
endpoint.Hints = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
if len(givingZones) == 0 || len(receivingZones) == 0 {
|
if len(givingZones) == 0 || len(receivingZones) == 0 {
|
||||||
return redistributions
|
return redistributions
|
||||||
}
|
}
|
||||||
@ -185,6 +190,9 @@ func getMost(zones map[string]float64) (string, float64) {
|
|||||||
func getHintsByZone(slice *discovery.EndpointSlice, allocatedHintsByZone EndpointZoneInfo, allocations map[string]Allocation) map[string]int {
|
func getHintsByZone(slice *discovery.EndpointSlice, allocatedHintsByZone EndpointZoneInfo, allocations map[string]Allocation) map[string]int {
|
||||||
hintsByZone := map[string]int{}
|
hintsByZone := map[string]int{}
|
||||||
for _, endpoint := range slice.Endpoints {
|
for _, endpoint := range slice.Endpoints {
|
||||||
|
if !endpointsliceutil.EndpointReady(endpoint) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if endpoint.Hints == nil || len(endpoint.Hints.ForZones) == 0 {
|
if endpoint.Hints == nil || len(endpoint.Hints.ForZones) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -248,3 +256,15 @@ func NodeReady(nodeStatus v1.NodeStatus) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// numReadyEndpoints returns the number of Endpoints that are ready from the
|
||||||
|
// specified list.
|
||||||
|
func numReadyEndpoints(endpoints []discovery.Endpoint) int {
|
||||||
|
var total int
|
||||||
|
for _, ep := range endpoints {
|
||||||
|
if ep.Conditions.Ready != nil && *ep.Conditions.Ready {
|
||||||
|
total++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
@ -43,6 +43,7 @@ func Test_redistributeHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
givingZones: map[string]int{"zone-a": 1},
|
givingZones: map[string]int{"zone-a": 1},
|
||||||
@ -54,12 +55,15 @@ func Test_redistributeHints(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}, {
|
}, {
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
givingZones: map[string]int{"zone-a": 2},
|
givingZones: map[string]int{"zone-a": 2},
|
||||||
@ -213,6 +217,30 @@ func Test_getHintsByZone(t *testing.T) {
|
|||||||
Endpoints: []discovery.Endpoint{{
|
Endpoints: []discovery.Endpoint{{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
allocations: map[string]Allocation{
|
||||||
|
"zone-a": {Maximum: 3},
|
||||||
|
},
|
||||||
|
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
|
||||||
|
expectedHintsByZone: map[string]int{
|
||||||
|
"zone-a": 1,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "single zone hint with 1 unready endpoint and 1 unknown endpoint",
|
||||||
|
slice: discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{{
|
||||||
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
|
}, {
|
||||||
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
|
||||||
|
}, {
|
||||||
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
allocations: map[string]Allocation{
|
allocations: map[string]Allocation{
|
||||||
@ -229,14 +257,17 @@ func Test_getHintsByZone(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-b"),
|
Zone: utilpointer.StringPtr("zone-b"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -257,6 +288,7 @@ func Test_getHintsByZone(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-non-existent"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-non-existent"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -272,6 +304,7 @@ func Test_getHintsByZone(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: nil,
|
Hints: nil,
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -287,6 +320,7 @@ func Test_getHintsByZone(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -302,10 +336,12 @@ func Test_getHintsByZone(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Zone: utilpointer.StringPtr("zone-a"),
|
Zone: utilpointer.StringPtr("zone-a"),
|
||||||
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
|
||||||
|
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
27
pkg/controller/util/endpointslice/utils.go
Normal file
27
pkg/controller/util/endpointslice/utils.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package endpointslice
|
||||||
|
|
||||||
|
import (
|
||||||
|
discovery "k8s.io/api/discovery/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EndpointReady returns true if an Endpoint has the Ready condition set to
|
||||||
|
// true.
|
||||||
|
func EndpointReady(endpoint discovery.Endpoint) bool {
|
||||||
|
return endpoint.Conditions.Ready != nil && *endpoint.Conditions.Ready
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user