1
0
Fork 0

Migrate to EndpointSlices API

This commit is contained in:
Jesper Noordsij 2024-06-21 14:56:03 +02:00 committed by GitHub
parent 61defcdd66
commit a8a92eb2a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
88 changed files with 2177 additions and 1555 deletions

View file

@ -16,10 +16,12 @@ import (
"github.com/traefik/traefik/v3/pkg/types"
traefikversion "github.com/traefik/traefik/v3/pkg/version"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
netv1 "k8s.io/api/networking/v1"
kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
kinformers "k8s.io/client-go/informers"
kclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
@ -41,7 +43,7 @@ type Client interface {
GetService(namespace, name string) (*corev1.Service, bool, error)
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
GetNodes() ([]*corev1.Node, bool, error)
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error)
UpdateIngressStatus(ing *netv1.Ingress, ingStatus []netv1.IngressLoadBalancerIngress) error
}
@ -185,7 +187,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
if err != nil {
return nil, err
}
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
_, err = factoryKube.Discovery().V1().EndpointSlices().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
@ -340,15 +342,20 @@ func (c *clientWrapper) GetService(namespace, name string) (*corev1.Service, boo
return service, exist, err
}
// GetEndpoints returns the named endpoints from the given namespace.
func (c *clientWrapper) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
// GetEndpointSlicesForService returns the EndpointSlices for the given service name in the given namespace.
func (c *clientWrapper) GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error) {
if !c.isWatchedNamespace(namespace) {
return nil, false, fmt.Errorf("failed to get endpoints %s/%s: namespace is not within watched namespaces", namespace, name)
return nil, fmt.Errorf("failed to get endpointslices for service %s/%s: namespace is not within watched namespaces", namespace, serviceName)
}
endpoint, err := c.factoriesKube[c.lookupNamespace(namespace)].Core().V1().Endpoints().Lister().Endpoints(namespace).Get(name)
exist, err := translateNotFoundError(err)
return endpoint, exist, err
serviceLabelRequirement, err := labels.NewRequirement(discoveryv1.LabelServiceName, selection.Equals, []string{serviceName})
if err != nil {
return nil, fmt.Errorf("failed to create service label selector requirement: %w", err)
}
serviceSelector := labels.NewSelector()
serviceSelector = serviceSelector.Add(*serviceLabelRequirement)
return c.factoriesKube[c.lookupNamespace(namespace)].Discovery().V1().EndpointSlices().Lister().EndpointSlices(namespace).List(serviceSelector)
}
// GetSecret returns the named secret from the given namespace.

View file

@ -6,6 +6,7 @@ import (
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
netv1 "k8s.io/api/networking/v1"
)
@ -15,15 +16,15 @@ type clientMock struct {
ingresses []*netv1.Ingress
services []*corev1.Service
secrets []*corev1.Secret
endpoints []*corev1.Endpoints
endpointSlices []*discoveryv1.EndpointSlice
nodes []*corev1.Node
ingressClasses []*netv1.IngressClass
apiServiceError error
apiSecretError error
apiEndpointsError error
apiNodesError error
apiIngressStatusError error
apiServiceError error
apiSecretError error
apiEndpointSlicesError error
apiNodesError error
apiIngressStatusError error
watchChan chan interface{}
}
@ -43,8 +44,8 @@ func newClientMock(path string) clientMock {
c.services = append(c.services, o)
case *corev1.Secret:
c.secrets = append(c.secrets, o)
case *corev1.Endpoints:
c.endpoints = append(c.endpoints, o)
case *discoveryv1.EndpointSlice:
c.endpointSlices = append(c.endpointSlices, o)
case *corev1.Node:
c.nodes = append(c.nodes, o)
case *netv1.Ingress:
@ -76,18 +77,19 @@ func (c clientMock) GetService(namespace, name string) (*corev1.Service, bool, e
return nil, false, c.apiServiceError
}
func (c clientMock) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
if c.apiEndpointsError != nil {
return nil, false, c.apiEndpointsError
func (c clientMock) GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error) {
if c.apiEndpointSlicesError != nil {
return nil, c.apiEndpointSlicesError
}
for _, endpoints := range c.endpoints {
if endpoints.Namespace == namespace && endpoints.Name == name {
return endpoints, true, nil
var result []*discoveryv1.EndpointSlice
for _, endpointSlice := range c.endpointSlices {
if endpointSlice.Namespace == namespace && endpointSlice.Labels[discoveryv1.LabelServiceName] == serviceName {
result = append(result, endpointSlice)
}
}
return &corev1.Endpoints{}, false, nil
return result, nil
}
func (c clientMock) GetNodes() ([]*corev1.Node, bool, error) {

View file

@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
netv1 "k8s.io/api/networking/v1"
kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -188,10 +189,10 @@ func TestClientIgnoresHelmOwnedSecrets(t *testing.T) {
assert.False(t, found)
}
func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
emptyEndpoint := &corev1.Endpoints{
func TestClientIgnoresEmptyEndpointSliceUpdates(t *testing.T) {
emptyEndpointSlice := &discoveryv1.EndpointSlice{
ObjectMeta: metav1.ObjectMeta{
Name: "empty-endpoint",
Name: "empty-endpointslice",
Namespace: "test",
ResourceVersion: "1244",
Annotations: map[string]string{
@ -200,25 +201,31 @@ func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
},
}
filledEndpoint := &corev1.Endpoints{
samplePortName := "testing"
samplePortNumber := int32(1337)
samplePortProtocol := corev1.ProtocolTCP
sampleAddressReady := true
filledEndpointSlice := &discoveryv1.EndpointSlice{
ObjectMeta: metav1.ObjectMeta{
Name: "filled-endpoint",
Name: "filled-endpointslice",
Namespace: "test",
ResourceVersion: "1234",
},
Subsets: []corev1.EndpointSubset{{
Addresses: []corev1.EndpointAddress{{
IP: "10.13.37.1",
}},
Ports: []corev1.EndpointPort{{
Name: "testing",
Port: 1337,
Protocol: "tcp",
}},
AddressType: discoveryv1.AddressTypeIPv4,
Endpoints: []discoveryv1.Endpoint{{
Addresses: []string{"10.13.37.1"},
Conditions: discoveryv1.EndpointConditions{
Ready: &sampleAddressReady,
},
}},
Ports: []discoveryv1.EndpointPort{{
Name: &samplePortName,
Port: &samplePortNumber,
Protocol: &samplePortProtocol,
}},
}
kubeClient := kubefake.NewSimpleClientset(emptyEndpoint, filledEndpoint)
kubeClient := kubefake.NewSimpleClientset(emptyEndpointSlice, filledEndpointSlice)
discovery, _ := kubeClient.Discovery().(*discoveryfake.FakeDiscovery)
discovery.FakedServerVersion = &kversion.Info{
@ -234,50 +241,72 @@ func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
select {
case event := <-eventCh:
ep, ok := event.(*corev1.Endpoints)
ep, ok := event.(*discoveryv1.EndpointSlice)
require.True(t, ok)
assert.True(t, ep.Name == "empty-endpoint" || ep.Name == "filled-endpoint")
assert.True(t, ep.Name == "empty-endpointslice" || ep.Name == "filled-endpointslice")
case <-time.After(50 * time.Millisecond):
assert.Fail(t, "expected to receive event for endpoints")
assert.Fail(t, "expected to receive event for endpointslices")
}
emptyEndpoint, err = kubeClient.CoreV1().Endpoints("test").Get(context.TODO(), "empty-endpoint", metav1.GetOptions{})
emptyEndpointSlice, err = kubeClient.DiscoveryV1().EndpointSlices("test").Get(context.TODO(), "empty-endpointslice", metav1.GetOptions{})
assert.NoError(t, err)
// Update endpoint annotation and resource version (apparently not done by fake client itself)
// to show an update that should not trigger an update event on our eventCh.
// This reflects the behavior of kubernetes controllers which use endpoint annotations for leader election.
emptyEndpoint.Annotations["test-annotation"] = "___"
emptyEndpoint.ResourceVersion = "1245"
_, err = kubeClient.CoreV1().Endpoints("test").Update(context.TODO(), emptyEndpoint, metav1.UpdateOptions{})
emptyEndpointSlice.Annotations["test-annotation"] = "___"
emptyEndpointSlice.ResourceVersion = "1245"
_, err = kubeClient.DiscoveryV1().EndpointSlices("test").Update(context.TODO(), emptyEndpointSlice, metav1.UpdateOptions{})
require.NoError(t, err)
select {
case event := <-eventCh:
ep, ok := event.(*corev1.Endpoints)
ep, ok := event.(*discoveryv1.EndpointSlice)
require.True(t, ok)
assert.Fail(t, "didn't expect to receive event for empty endpoint update", ep.Name)
assert.Fail(t, "didn't expect to receive event for empty endpointslice update", ep.Name)
case <-time.After(50 * time.Millisecond):
}
filledEndpoint, err = kubeClient.CoreV1().Endpoints("test").Get(context.TODO(), "filled-endpoint", metav1.GetOptions{})
filledEndpointSlice, err = kubeClient.DiscoveryV1().EndpointSlices("test").Get(context.TODO(), "filled-endpointslice", metav1.GetOptions{})
assert.NoError(t, err)
filledEndpoint.Subsets[0].Addresses[0].IP = "10.13.37.2"
filledEndpoint.ResourceVersion = "1235"
_, err = kubeClient.CoreV1().Endpoints("test").Update(context.TODO(), filledEndpoint, metav1.UpdateOptions{})
filledEndpointSlice.Endpoints[0].Addresses[0] = "10.13.37.2"
filledEndpointSlice.ResourceVersion = "1235"
_, err = kubeClient.DiscoveryV1().EndpointSlices("test").Update(context.TODO(), filledEndpointSlice, metav1.UpdateOptions{})
require.NoError(t, err)
select {
case event := <-eventCh:
ep, ok := event.(*corev1.Endpoints)
ep, ok := event.(*discoveryv1.EndpointSlice)
require.True(t, ok)
assert.Equal(t, "filled-endpoint", ep.Name)
assert.Equal(t, "filled-endpointslice", ep.Name)
case <-time.After(50 * time.Millisecond):
assert.Fail(t, "expected to receive event for filled endpoint")
assert.Fail(t, "expected to receive event for filled endpointslice")
}
select {
case <-eventCh:
assert.Fail(t, "received more than one event")
case <-time.After(50 * time.Millisecond):
}
newPortNumber := int32(42)
filledEndpointSlice.Ports[0].Port = &newPortNumber
filledEndpointSlice.ResourceVersion = "1236"
_, err = kubeClient.DiscoveryV1().EndpointSlices("test").Update(context.TODO(), filledEndpointSlice, metav1.UpdateOptions{})
require.NoError(t, err)
select {
case event := <-eventCh:
ep, ok := event.(*discoveryv1.EndpointSlice)
require.True(t, ok)
assert.Equal(t, "filled-endpointslice", ep.Name)
case <-time.After(50 * time.Millisecond):
assert.Fail(t, "expected to receive event for filled endpointslice")
}
select {

View file

@ -1,32 +1,42 @@
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- name: tchouk
port: 8089
- 10.10.0.1
- 10.10.0.2
conditions:
ready: true
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: toto
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.11.0.1
- ip: 10.11.0.2
ports:
- name: tchouk
port: 8089
- 10.11.0.1
- 10.11.0.2
conditions:
ready: true
---
kind: Ingress

View file

@ -50,35 +50,41 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiversion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.30.0.1
ports:
- port: 8080
- addresses:
- ip: 10.41.0.1
ports:
- port: 8080
- 10.30.0.1
- 10.41.0.1
conditions:
ready: true
---
kind: Endpoints
apiversion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service2
name: service2-abc
namespace: testing
labels:
kubernetes.io/service-name: service2
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -40,18 +40,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -37,18 +37,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -30,18 +30,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -36,18 +36,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -52,15 +52,20 @@ spec:
externalName: "2001:0db8:3c4d:0015:0000:0000:1a2f:2a3b"
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service-bar
name: service-bar-abc
namespace: testing
labels:
kubernetes.io/service-name: service-bar
subsets:
addressType: IPv6
ports:
- name: http
port: 8080
endpoints:
- addresses:
- ip: "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b"
ports:
- name: http
port: 8080
- "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b"
conditions:
ready: true

View file

@ -30,18 +30,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8443
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8443
- addresses:
- ip: 10.21.0.1
ports:
- port: 8443
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -31,20 +31,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: https
port: 8443
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- name: https
port: 8443
- addresses:
- ip: 10.21.0.1
ports:
- name: https
port: 8443
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -31,20 +31,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: https-foo
port: 8443
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- name: https-foo
port: 8443
- addresses:
- ip: 10.21.0.1
ports:
- name: https-foo
port: 8443
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -29,18 +29,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -33,23 +33,42 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- name: tchouk
port: 8089
- 10.10.0.1
- 10.10.0.2
conditions:
ready: true
---
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1-def
namespace: testing
labels:
kubernetes.io/service-name: service1
addressType: IPv4
ports:
- name: carotte
port: 8090
endpoints:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
- ip: 10.10.0.3
ports:
- name: carotte
port: 8090
- 10.10.0.1
- 10.10.0.2
- 10.10.0.3
conditions:
ready: true

View file

@ -53,18 +53,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -41,18 +41,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -37,18 +37,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -31,14 +31,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -36,27 +36,38 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 80
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 80
- 10.10.0.1
conditions:
ready: true
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: defaultservice
name: defaultservice-abc
namespace: testing
labels:
kubernetes.io/service-name: defaultservice
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -30,14 +30,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -28,14 +28,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -30,14 +30,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -30,14 +30,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -31,14 +31,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -37,15 +37,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -64,14 +64,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -29,14 +29,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -64,14 +64,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -29,15 +29,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: foobar
port: 4711
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- name: foobar
port: 4711
- 10.10.0.1
conditions:
ready: true

View file

@ -31,14 +31,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -31,15 +31,20 @@ spec:
type: ClusterIP
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: example-com
name: example-com-abc
namespace: testing
labels:
kubernetes.io/service-name: example-com
subsets:
addressType: IPv4
ports:
- name: http
port: 80
endpoints:
- addresses:
- ip: 10.11.0.1
ports:
- name: http
port: 80
- 10.11.0.1
conditions:
ready: true

View file

@ -30,8 +30,14 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
addressType: IPv4
ports: null
endpoints: []

View file

@ -40,24 +40,43 @@ spec:
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
subsets:
labels:
kubernetes.io/service-name: service1
addressType: IPv4
ports:
- name: http-admin
port: 8079
protocol: TCP
endpoints:
- addresses:
- ip: 10.0.0.1
nodeName: admin.whoami.service1
ports:
- name: http-admin
port: 8079
protocol: TCP
- 10.0.0.1
conditions:
ready: true
nodeName: admin.whoami.service1
---
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1-def
namespace: testing
labels:
kubernetes.io/service-name: service1
addressType: IPv4
ports:
- name: http
port: 8080
protocol: TCP
endpoints:
- addresses:
- ip: 10.0.0.1
nodeName: whoami.service1
# targetRef:
ports:
- name: http
port: 8080
protocol: TCP
- 10.0.0.1
conditions:
ready: true
nodeName: whoami.service1

View file

@ -33,18 +33,23 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
- 10.10.0.1
- 10.10.0.2
conditions:
ready: true

View file

@ -33,24 +33,23 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
- addresses:
- ip: 10.21.0.1
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -33,24 +33,23 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
- addresses:
- ip: 10.21.0.1
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -28,14 +28,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -38,18 +38,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -40,18 +40,23 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
endpoints:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- name: carotte
port: 8090
- name: tchouk
port: 8089
- 10.10.0.1
- 10.10.0.2
conditions:
ready: true

View file

@ -52,35 +52,41 @@ spec:
clusterIP: 10.1.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service2
name: service2-abc
namespace: testing
labels:
kubernetes.io/service-name: service2
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.2
ports:
- port: 8080
- addresses:
- ip: 10.21.0.2
ports:
- port: 8080
- 10.10.0.2
- 10.21.0.2
conditions:
ready: true

View file

@ -30,15 +30,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8089
name: ""
endpoints:
- addresses:
- ip: 10.11.0.1
- ip: 10.11.0.2
ports:
- port: 8089
- 10.11.0.1
- 10.11.0.2
conditions:
ready: true

View file

@ -30,15 +30,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8089
name: ""
endpoints:
- addresses:
- ip: 10.11.0.1
- ip: 10.11.0.2
ports:
- port: 8089
- 10.11.0.1
- 10.11.0.2
conditions:
ready: true

View file

@ -30,14 +30,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -31,14 +31,20 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- 10.10.0.1
conditions:
ready: true

View file

@ -24,18 +24,21 @@ spec:
clusterIP: 10.0.0.1
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: service1
name: service1-abc
namespace: testing
labels:
kubernetes.io/service-name: service1
subsets:
addressType: IPv4
ports:
- port: 8080
name: ""
endpoints:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
- 10.10.0.1
- 10.21.0.1
conditions:
ready: true

View file

@ -83,15 +83,20 @@ spec:
type: ClusterIP
---
kind: Endpoints
apiVersion: v1
kind: EndpointSlice
apiVersion: discovery.k8s.io/v1
metadata:
name: example-com
name: example-com-abc
namespace: testing
labels:
kubernetes.io/service-name: example-com
subsets:
addressType: IPv4
ports:
- name: http
port: 80
endpoints:
- addresses:
- ip: 10.11.0.1
ports:
- name: http
port: 80
- 10.11.0.1
conditions:
ready: true

View file

@ -651,36 +651,41 @@ func (p *Provider) loadService(client Client, namespace string, backend netv1.In
return svc, nil
}
endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, backend.Service.Name)
if endpointsErr != nil {
return nil, endpointsErr
endpointSlices, err := client.GetEndpointSlicesForService(namespace, backend.Service.Name)
if err != nil {
return nil, fmt.Errorf("getting endpointslices: %w", err)
}
if !endpointsExists {
return nil, errors.New("endpoints not found")
}
for _, subset := range endpoints.Subsets {
addresses := map[string]struct{}{}
for _, endpointSlice := range endpointSlices {
var port int32
for _, p := range subset.Ports {
if portName == p.Name {
port = p.Port
for _, p := range endpointSlice.Ports {
if portName == *p.Name {
port = *p.Port
break
}
}
if port == 0 {
continue
}
protocol := getProtocol(portSpec, portName, svcConfig)
for _, addr := range subset.Addresses {
hostPort := net.JoinHostPort(addr.IP, strconv.Itoa(int(port)))
for _, endpoint := range endpointSlice.Endpoints {
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
continue
}
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, dynamic.Server{
URL: fmt.Sprintf("%s://%s", protocol, hostPort),
})
for _, address := range endpoint.Addresses {
if _, ok := addresses[address]; ok {
continue
}
addresses[address] = struct{}{}
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, dynamic.Server{
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(address, strconv.Itoa(int(port)))),
})
}
}
}