Migrate to EndpointSlices API
This commit is contained in:
parent
61defcdd66
commit
a8a92eb2a5
88 changed files with 2177 additions and 1555 deletions
|
@ -35,12 +35,18 @@ rules:
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- extensions
|
- extensions
|
||||||
- networking.k8s.io
|
- networking.k8s.io
|
||||||
|
|
27
docs/content/migration/v3.md
Normal file
27
docs/content/migration/v3.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
title: "Traefik Migration Documentation"
|
||||||
|
description: "Learn the steps needed to migrate to new Traefik Proxy v3 versions. Read the technical documentation."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Migration: Steps needed between the versions
|
||||||
|
|
||||||
|
## v3.0 to v3.1
|
||||||
|
|
||||||
|
### Kubernetes Provider RBACs
|
||||||
|
|
||||||
|
Starting with v3.1, the Kubernetes Providers now use the [EndpointSlices API](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) (Kubernetes >=v1.21) to discover service endpoint addresses.
|
||||||
|
|
||||||
|
Therefore, in the corresponding RBACs (see [KubernetesIngress](../routing/providers/kubernetes-ingress.md#configuration-example), [KubernetesCRD](../reference/dynamic-configuration/kubernetes-crd.md#rbac), and [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) provider RBACs),
|
||||||
|
the `endpoints` right has to be removed and the following `endpointslices` right has to be added.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
...
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
...
|
||||||
|
```
|
|
@ -183,7 +183,7 @@ _Optional, Default: ""_
|
||||||
|
|
||||||
A label selector can be defined to filter on specific resource objects only,
|
A label selector can be defined to filter on specific resource objects only,
|
||||||
this applies only to Traefik [Custom Resources](../routing/providers/kubernetes-crd.md#custom-resource-definition-crd)
|
this applies only to Traefik [Custom Resources](../routing/providers/kubernetes-crd.md#custom-resource-definition-crd)
|
||||||
and has no effect on Kubernetes `Secrets`, `Endpoints` and `Services`.
|
and has no effect on Kubernetes `Secrets`, `EndpointSlices` and `Services`.
|
||||||
If left empty, Traefik processes all resource objects in the configured namespaces.
|
If left empty, Traefik processes all resource objects in the configured namespaces.
|
||||||
|
|
||||||
See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) for details.
|
See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) for details.
|
||||||
|
|
|
@ -8,13 +8,19 @@ rules:
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
- nodes
|
- nodes
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- extensions
|
- extensions
|
||||||
- networking.k8s.io
|
- networking.k8s.io
|
||||||
|
|
|
@ -15,12 +15,18 @@ rules:
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- gateway.networking.k8s.io
|
- gateway.networking.k8s.io
|
||||||
resources:
|
resources:
|
||||||
|
|
|
@ -29,12 +29,18 @@ which in turn will create the resulting routers, services, handlers, etc.
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- extensions
|
- extensions
|
||||||
- networking.k8s.io
|
- networking.k8s.io
|
||||||
|
@ -427,12 +433,19 @@ This way, any Ingress attached to this Entrypoint will have TLS termination by d
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- extensions
|
- extensions
|
||||||
- networking.k8s.io
|
- networking.k8s.io
|
||||||
|
@ -612,12 +625,19 @@ For more options, please refer to the available [annotations](#on-ingress).
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- extensions
|
- extensions
|
||||||
- networking.k8s.io
|
- networking.k8s.io
|
||||||
|
|
|
@ -172,6 +172,7 @@ nav:
|
||||||
- 'HTTP Challenge': 'user-guides/docker-compose/acme-http/index.md'
|
- 'HTTP Challenge': 'user-guides/docker-compose/acme-http/index.md'
|
||||||
- 'DNS Challenge': 'user-guides/docker-compose/acme-dns/index.md'
|
- 'DNS Challenge': 'user-guides/docker-compose/acme-dns/index.md'
|
||||||
- 'Migration':
|
- 'Migration':
|
||||||
|
- 'Traefik v3 minor migrations': 'migration/v3.md'
|
||||||
- 'Traefik v2 to v3':
|
- 'Traefik v2 to v3':
|
||||||
- 'Migration guide': 'migration/v2-to-v3.md'
|
- 'Migration guide': 'migration/v2-to-v3.md'
|
||||||
- 'Configuration changes for v3': 'migration/v2-to-v3-details.md'
|
- 'Configuration changes for v3': 'migration/v2-to-v3-details.md'
|
||||||
|
|
|
@ -15,12 +15,19 @@ rules:
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
- endpoints
|
|
||||||
- secrets
|
- secrets
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- gateway.networking.k8s.io
|
- gateway.networking.k8s.io
|
||||||
resources:
|
resources:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
server:
|
server:
|
||||||
image: rancher/k3s:v1.20.15-k3s1
|
image: rancher/k3s:v1.21.14-k3s1
|
||||||
privileged: true
|
privileged: true
|
||||||
command:
|
command:
|
||||||
- server
|
- server
|
||||||
|
@ -26,7 +26,7 @@ services:
|
||||||
- ./fixtures/k8s:/var/lib/rancher/k3s/server/manifests
|
- ./fixtures/k8s:/var/lib/rancher/k3s/server/manifests
|
||||||
|
|
||||||
node:
|
node:
|
||||||
image: rancher/k3s:v1.20.15-k3s1
|
image: rancher/k3s:v1.21.14-k3s1
|
||||||
privileged: true
|
privileged: true
|
||||||
environment:
|
environment:
|
||||||
K3S_TOKEN: somethingtotallyrandom
|
K3S_TOKEN: somethingtotallyrandom
|
||||||
|
|
|
@ -17,9 +17,11 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
"github.com/traefik/traefik/v3/pkg/version"
|
"github.com/traefik/traefik/v3/pkg/version"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/selection"
|
||||||
kinformers "k8s.io/client-go/informers"
|
kinformers "k8s.io/client-go/informers"
|
||||||
kclientset "k8s.io/client-go/kubernetes"
|
kclientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
@ -46,7 +48,7 @@ type Client interface {
|
||||||
GetTLSStores() []*traefikv1alpha1.TLSStore
|
GetTLSStores() []*traefikv1alpha1.TLSStore
|
||||||
GetService(namespace, name string) (*corev1.Service, bool, error)
|
GetService(namespace, name string) (*corev1.Service, bool, error)
|
||||||
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
||||||
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
|
GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error)
|
||||||
GetNodes() ([]*corev1.Node, bool, error)
|
GetNodes() ([]*corev1.Node, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +221,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
_, err = factoryKube.Discovery().V1().EndpointSlices().Informer().AddEventHandler(eventHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -444,15 +446,20 @@ func (c *clientWrapper) GetService(namespace, name string) (*corev1.Service, boo
|
||||||
return service, exist, err
|
return service, exist, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEndpoints returns the named endpoints from the given namespace.
|
// GetEndpointSlicesForService returns the EndpointSlices for the given service name in the given namespace.
|
||||||
func (c *clientWrapper) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
func (c *clientWrapper) GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error) {
|
||||||
if !c.isWatchedNamespace(namespace) {
|
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)
|
serviceLabelRequirement, err := labels.NewRequirement(discoveryv1.LabelServiceName, selection.Equals, []string{serviceName})
|
||||||
exist, err := translateNotFoundError(err)
|
if err != nil {
|
||||||
return endpoint, exist, err
|
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.
|
// GetSecret returns the named secret from the given namespace.
|
||||||
|
|
|
@ -13,19 +13,24 @@ spec:
|
||||||
task: whoami
|
task: whoami
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami
|
name: whoami-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 80
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -43,19 +48,24 @@ spec:
|
||||||
task: whoami2
|
task: whoami2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami2
|
name: whoami2-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami2
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -74,19 +84,24 @@ spec:
|
||||||
task: whoami2
|
task: whoami2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitls
|
name: whoamitls-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitls
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: websecure
|
||||||
|
port: 8443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.5
|
- 10.10.0.5
|
||||||
- ip: 10.10.0.6
|
- 10.10.0.6
|
||||||
ports:
|
conditions:
|
||||||
- name: websecure
|
ready: true
|
||||||
port: 8443
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -99,25 +114,29 @@ spec:
|
||||||
ports:
|
ports:
|
||||||
- name: websecure2
|
- name: websecure2
|
||||||
port: 8443
|
port: 8443
|
||||||
scheme: https
|
|
||||||
selector:
|
selector:
|
||||||
app: traefiklabs
|
app: traefiklabs
|
||||||
task: whoami3
|
task: whoami3
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami3
|
name: whoami3-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami3
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: websecure2
|
||||||
|
port: 8443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.7
|
- 10.10.0.7
|
||||||
- ip: 10.10.0.8
|
- 10.10.0.8
|
||||||
ports:
|
conditions:
|
||||||
- name: websecure2
|
ready: true
|
||||||
port: 8443
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -135,18 +154,23 @@ spec:
|
||||||
task: whoami-ipv6
|
task: whoami-ipv6
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami-ipv6
|
name: whoami-ipv6-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-ipv6
|
||||||
|
|
||||||
subsets:
|
addressType: IPv6
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: "2001:db8:85a3:8d3:1319:8a2e:370:7348"
|
- "2001:db8:85a3:8d3:1319:8a2e:370:7348"
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -216,25 +240,30 @@ spec:
|
||||||
task: whoami
|
task: whoami
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami-svc
|
name: whoami-svc-abc
|
||||||
namespace: cross-ns
|
namespace: cross-ns
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 80
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami-without-endpoints-subsets
|
name: whoami-without-endpointslice-endpoints
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
@ -247,11 +276,16 @@ spec:
|
||||||
task: whoami
|
task: whoami
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami-without-endpoints-subsets
|
name: whoami-without-endpointslice-endpoints-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-without-endpointslice-endpoints
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
endpoints: []
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -13,19 +13,24 @@ spec:
|
||||||
task: whoamitcp
|
task: whoamitcp
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp
|
name: whoamitcp-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp
|
||||||
|
port: 8000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp
|
ready: true
|
||||||
port: 8000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -43,19 +48,24 @@ spec:
|
||||||
task: whoamitcp2
|
task: whoamitcp2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp2
|
name: whoamitcp2-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp2
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp2
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp2
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -73,19 +83,24 @@ spec:
|
||||||
task: whoamitcptls2
|
task: whoamitcptls2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcptls
|
name: whoamitcptls-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcptls
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: websecure
|
||||||
|
port: 443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.5
|
- 10.10.0.5
|
||||||
- ip: 10.10.0.6
|
- 10.10.0.6
|
||||||
ports:
|
conditions:
|
||||||
- name: websecure
|
ready: true
|
||||||
port: 443
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -103,34 +118,44 @@ spec:
|
||||||
task: whoamitcp3
|
task: whoamitcp3
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp3
|
name: whoamitcp3-abc
|
||||||
namespace: ns3
|
namespace: ns3
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp3
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp3
|
||||||
|
port: 8083
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.7
|
- 10.10.0.7
|
||||||
- ip: 10.10.0.8
|
- 10.10.0.8
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp3
|
ready: true
|
||||||
port: 8083
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp3
|
name: whoamitcp3-abc
|
||||||
namespace: ns4
|
namespace: ns4
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp3
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp4
|
||||||
|
port: 8084
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.9
|
- 10.10.0.9
|
||||||
- ip: 10.10.0.10
|
- 10.10.0.10
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp4
|
ready: true
|
||||||
port: 8084
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -148,19 +173,24 @@ spec:
|
||||||
task: whoamitcp-ipv6
|
task: whoamitcp-ipv6
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp-ipv6
|
name: whoamitcp-ipv6-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp-ipv6
|
||||||
|
|
||||||
subsets:
|
addressType: IPv6
|
||||||
|
ports:
|
||||||
|
- name: myapp-ipv6
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: "fd00:10:244:0:1::3"
|
- "fd00:10:244:0:1::3"
|
||||||
- ip: "2001:db8:85a3:8d3:1319:8a2e:370:7348"
|
- "2001:db8:85a3:8d3:1319:8a2e:370:7348"
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp-ipv6
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -212,25 +242,30 @@ spec:
|
||||||
task: whoamitcp
|
task: whoamitcp
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp-cross-ns
|
name: whoamitcp-cross-ns-abc
|
||||||
namespace: cross-ns
|
namespace: cross-ns
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp-cross-ns
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp
|
||||||
|
port: 8000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp
|
ready: true
|
||||||
port: 8000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp-without-endpoints-subsets
|
name: whoamitcp-without-endpointslice-endpoints
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
@ -243,11 +278,16 @@ spec:
|
||||||
task: whoamitcp
|
task: whoamitcp
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp-without-endpoints-subsets
|
name: whoamitcp-without-endpointslice-endpoints-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp-without-endpointslice-endpoints
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
endpoints: []
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -11,5 +11,5 @@ spec:
|
||||||
routes:
|
routes:
|
||||||
- match: HostSNI(`foo.com`)
|
- match: HostSNI(`foo.com`)
|
||||||
services:
|
services:
|
||||||
- name: whoamitcp-without-endpoints-subsets
|
- name: whoamitcp-without-endpointslice-endpoints
|
||||||
port: 8000
|
port: 8000
|
||||||
|
|
|
@ -13,19 +13,24 @@ spec:
|
||||||
task: whoamiudp
|
task: whoamiudp
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp
|
name: whoamiudp-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp
|
||||||
|
port: 8000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp
|
ready: true
|
||||||
port: 8000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -43,19 +48,24 @@ spec:
|
||||||
task: whoamiudp2
|
task: whoamiudp2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp2
|
name: whoamiudp2-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp2
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp2
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp2
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -73,34 +83,44 @@ spec:
|
||||||
task: whoamiudp3
|
task: whoamiudp3
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp3
|
name: whoamiudp3-abc
|
||||||
namespace: ns3
|
namespace: ns3
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp3
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp3
|
||||||
|
port: 8083
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.7
|
- 10.10.0.7
|
||||||
- ip: 10.10.0.8
|
- 10.10.0.8
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp3
|
ready: true
|
||||||
port: 8083
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp3
|
name: whoamiudp3-abc
|
||||||
namespace: ns4
|
namespace: ns4
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp3
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp4
|
||||||
|
port: 8084
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.9
|
- 10.10.0.9
|
||||||
- ip: 10.10.0.10
|
- 10.10.0.10
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp4
|
ready: true
|
||||||
port: 8084
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -118,18 +138,23 @@ spec:
|
||||||
task: whoamiudp-ipv6
|
task: whoamiudp-ipv6
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp-ipv6
|
name: whoamiudp-ipv6-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp-ipv6
|
||||||
|
|
||||||
subsets:
|
addressType: IPv6
|
||||||
|
ports:
|
||||||
|
- name: myapp-ipv6
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: "fd00:10:244:0:1::3"
|
- "fd00:10:244:0:1::3"
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp-ipv6
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -171,25 +196,30 @@ spec:
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp-cross-ns
|
name: whoamiudp-cross-ns-abc
|
||||||
namespace: cross-ns
|
namespace: cross-ns
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp-cross-ns
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: myapp
|
||||||
|
port: 8000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: myapp
|
ready: true
|
||||||
port: 8000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp-without-endpoints-subsets
|
name: whoamiudp-without-endpointslice-endpoints
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
@ -202,11 +232,16 @@ spec:
|
||||||
task: whoamiudp
|
task: whoamiudp
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamiudp-without-endpoints-subsets
|
name: whoamiudp-without-endpointslice-endpoints-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamiudp-without-endpointslice-endpoints
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
endpoints: []
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- services:
|
- services:
|
||||||
- name: whoamiudp-without-endpoints-subsets
|
- name: whoamiudp-without-endpointslice-endpoints
|
||||||
port: 8000
|
port: 8000
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-duplicated-endpointaddresses
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
selector:
|
||||||
|
app: traefiklabs
|
||||||
|
task: whoami
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-duplicated-endpointaddresses-abc
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc-duplicated-endpointaddresses
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.1
|
||||||
|
- 10.10.0.2
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-duplicated-endpointaddresses-def
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc-duplicated-endpointaddresses
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.1
|
||||||
|
- 10.10.0.2
|
||||||
|
- 10.10.0.3
|
||||||
|
- 10.10.0.4
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: test.route
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- foo
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
||||||
|
kind: Rule
|
||||||
|
priority: 12
|
||||||
|
services:
|
||||||
|
- name: whoami-svc-duplicated-endpointaddresses
|
||||||
|
port: 8080
|
|
@ -13,5 +13,5 @@ spec:
|
||||||
kind: Rule
|
kind: Rule
|
||||||
priority: 12
|
priority: 12
|
||||||
services:
|
services:
|
||||||
- name: whoami-without-endpoints-subsets
|
- name: whoami-without-endpointslice-endpoints
|
||||||
port: 80
|
port: 80
|
||||||
|
|
|
@ -30,7 +30,7 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
weighted:
|
weighted:
|
||||||
services:
|
services:
|
||||||
- name: whoami-without-endpoints-subsets
|
- name: whoami-without-endpointslice-endpoints
|
||||||
weight: 1
|
weight: 1
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ metadata:
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
mirroring:
|
mirroring:
|
||||||
name: whoami-without-endpoints-subsets
|
name: whoami-without-endpointslice-endpoints
|
||||||
port: 80
|
port: 80
|
||||||
mirrors:
|
mirrors:
|
||||||
- name: whoami-without-endpoints-subsets
|
- name: whoami-without-endpointslice-endpoints
|
||||||
port: 80
|
port: 80
|
||||||
- name: test-weighted
|
- name: test-weighted
|
||||||
kind: TraefikService
|
kind: TraefikService
|
||||||
|
@ -61,5 +61,5 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
errors:
|
errors:
|
||||||
service:
|
service:
|
||||||
name: whoami-without-endpoints-subsets
|
name: whoami-without-endpointslice-endpoints
|
||||||
port: 80
|
port: 80
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami4
|
name: whoami4-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami4
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -28,20 +33,25 @@ spec:
|
||||||
app: traefiklabs
|
app: traefiklabs
|
||||||
task: whoami4
|
task: whoami4
|
||||||
|
|
||||||
------
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami4
|
name: whoami4-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami4
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -28,20 +33,25 @@ spec:
|
||||||
app: traefiklabs
|
app: traefiklabs
|
||||||
task: whoami4
|
task: whoami4
|
||||||
|
|
||||||
------
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-multiple-endpointaddresses
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
selector:
|
||||||
|
app: traefiklabs
|
||||||
|
task: whoami
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-multiple-endpointaddresses-abc
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc-multiple-endpointaddresses
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.1
|
||||||
|
- 10.10.0.2
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.3
|
||||||
|
- 10.10.0.4
|
||||||
|
conditions:
|
||||||
|
ready: false
|
||||||
|
serving: true
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.5
|
||||||
|
- 10.10.0.6
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: test.route
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- foo
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
||||||
|
kind: Rule
|
||||||
|
priority: 12
|
||||||
|
services:
|
||||||
|
- name: whoami-svc-multiple-endpointaddresses
|
||||||
|
port: 80
|
|
@ -0,0 +1,94 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-multiple-endpointslices
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
- name: web2
|
||||||
|
port: 8080
|
||||||
|
selector:
|
||||||
|
app: traefiklabs
|
||||||
|
task: whoami
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-multiple-endpointslices-abc
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc-multiple-endpointslices
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.1
|
||||||
|
- 10.10.0.2
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-multiple-endpointslices-def
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc-multiple-endpointslices
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web2
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.3
|
||||||
|
- 10.10.0.4
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: whoami-svc-multiple-endpointslices-ghi
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-svc-multiple-endpointslices
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web2
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.5
|
||||||
|
- 10.10.0.6
|
||||||
|
conditions:
|
||||||
|
ready: true
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: test.route
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- foo
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
||||||
|
kind: Rule
|
||||||
|
priority: 12
|
||||||
|
services:
|
||||||
|
- name: whoami-svc-multiple-endpointslices
|
||||||
|
port: 8080
|
|
@ -1,54 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: whoami-svc-multiple-subsets
|
|
||||||
namespace: default
|
|
||||||
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: web
|
|
||||||
port: 80
|
|
||||||
- name: web2
|
|
||||||
port: 8080
|
|
||||||
selector:
|
|
||||||
app: traefiklabs
|
|
||||||
task: whoami
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: Endpoints
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: whoami-svc-multiple-subsets
|
|
||||||
namespace: default
|
|
||||||
|
|
||||||
subsets:
|
|
||||||
- addresses:
|
|
||||||
- ip: 10.10.0.1
|
|
||||||
- ip: 10.10.0.2
|
|
||||||
ports:
|
|
||||||
- name: web
|
|
||||||
port: 80
|
|
||||||
- addresses:
|
|
||||||
- ip: 10.10.0.3
|
|
||||||
- ip: 10.10.0.4
|
|
||||||
ports:
|
|
||||||
- name: web2
|
|
||||||
port: 8080
|
|
||||||
---
|
|
||||||
apiVersion: traefik.io/v1alpha1
|
|
||||||
kind: IngressRoute
|
|
||||||
metadata:
|
|
||||||
name: test.route
|
|
||||||
namespace: default
|
|
||||||
|
|
||||||
spec:
|
|
||||||
entryPoints:
|
|
||||||
- foo
|
|
||||||
|
|
||||||
routes:
|
|
||||||
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
|
||||||
kind: Rule
|
|
||||||
priority: 12
|
|
||||||
services:
|
|
||||||
- name: whoami-svc-multiple-subsets
|
|
||||||
port: 8080
|
|
|
@ -1,47 +1,62 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami6
|
name: whoami6-abc
|
||||||
namespace: baz
|
namespace: baz
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami6
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.5
|
- 10.10.0.5
|
||||||
- ip: 10.10.0.6
|
- 10.10.0.6
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: foo
|
namespace: foo
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami4
|
name: whoami4-abc
|
||||||
namespace: foo
|
namespace: foo
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami4
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -1,62 +1,82 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami4
|
name: whoami4-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami4
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 80
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami6
|
name: whoami6-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami6
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.5
|
- 10.10.0.5
|
||||||
- ip: 10.10.0.6
|
- 10.10.0.6
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 80
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami7
|
name: whoami7-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami7
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.7
|
- 10.10.0.7
|
||||||
- ip: 10.10.0.8
|
- 10.10.0.8
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
|
|
@ -1,32 +1,42 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami4
|
name: whoami4-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami4
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami5
|
name: whoami5-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami5
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -409,9 +409,8 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var servers []dynamic.Server
|
|
||||||
if service.Spec.Type != corev1.ServiceTypeExternalName && svc.HealthCheck != nil {
|
if service.Spec.Type != corev1.ServiceTypeExternalName && svc.HealthCheck != nil {
|
||||||
return nil, fmt.Errorf("HealthCheck allowed only for ExternalName services: %s/%s", namespace, sanitizedName)
|
return nil, fmt.Errorf("healthCheck allowed only for ExternalName services: %s/%s", namespace, sanitizedName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if service.Spec.Type == corev1.ServiceTypeExternalName {
|
if service.Spec.Type == corev1.ServiceTypeExternalName {
|
||||||
|
@ -426,9 +425,7 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
|
||||||
|
|
||||||
hostPort := net.JoinHostPort(service.Spec.ExternalName, strconv.Itoa(int(svcPort.Port)))
|
hostPort := net.JoinHostPort(service.Spec.ExternalName, strconv.Itoa(int(svcPort.Port)))
|
||||||
|
|
||||||
return append(servers, dynamic.Server{
|
return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, hostPort)}}, nil
|
||||||
URL: fmt.Sprintf("%s://%s", protocol, hostPort),
|
|
||||||
}), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeLB := c.NativeLBByDefault
|
nativeLB := c.NativeLBByDefault
|
||||||
|
@ -449,6 +446,7 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
|
||||||
return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, address)}}, nil
|
return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, address)}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var servers []dynamic.Server
|
||||||
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
|
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
|
||||||
nodes, nodesExists, nodesErr := c.client.GetNodes()
|
nodes, nodesExists, nodesErr := c.client.GetNodes()
|
||||||
if nodesErr != nil {
|
if nodesErr != nil {
|
||||||
|
@ -482,27 +480,20 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, endpointsExists, endpointsErr := c.client.GetEndpoints(namespace, sanitizedName)
|
endpointSlices, err := c.client.GetEndpointSlicesForService(namespace, sanitizedName)
|
||||||
if endpointsErr != nil {
|
if err != nil {
|
||||||
return nil, endpointsErr
|
return nil, fmt.Errorf("getting endpointslices: %w", err)
|
||||||
}
|
|
||||||
if !endpointsExists {
|
|
||||||
return nil, fmt.Errorf("endpoints not found for %s/%s", namespace, sanitizedName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(endpoints.Subsets) == 0 && !c.allowEmptyServices {
|
addresses := map[string]struct{}{}
|
||||||
return nil, fmt.Errorf("subset not found for %s/%s", namespace, sanitizedName)
|
for _, endpointSlice := range endpointSlices {
|
||||||
}
|
|
||||||
|
|
||||||
for _, subset := range endpoints.Subsets {
|
|
||||||
var port int32
|
var port int32
|
||||||
for _, p := range subset.Ports {
|
for _, p := range endpointSlice.Ports {
|
||||||
if svcPort.Name == p.Name {
|
if svcPort.Name == *p.Name {
|
||||||
port = p.Port
|
port = *p.Port
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -512,15 +503,28 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range subset.Addresses {
|
for _, endpoint := range endpointSlice.Endpoints {
|
||||||
hostPort := net.JoinHostPort(addr.IP, strconv.Itoa(int(port)))
|
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
servers = append(servers, dynamic.Server{
|
for _, address := range endpoint.Addresses {
|
||||||
URL: fmt.Sprintf("%s://%s", protocol, hostPort),
|
if _, ok := addresses[address]; ok {
|
||||||
})
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses[address] = struct{}{}
|
||||||
|
servers = append(servers, dynamic.Server{
|
||||||
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(address, strconv.Itoa(int(port)))),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(servers) == 0 && !c.allowEmptyServices {
|
||||||
|
return nil, fmt.Errorf("no servers found for %s/%s", namespace, sanitizedName)
|
||||||
|
}
|
||||||
|
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,6 @@ func (p *Provider) loadTCPServers(client Client, namespace string, svc traefikv1
|
||||||
}
|
}
|
||||||
|
|
||||||
var servers []dynamic.TCPServer
|
var servers []dynamic.TCPServer
|
||||||
|
|
||||||
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
|
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
|
||||||
nodes, nodesExists, nodesErr := client.GetNodes()
|
nodes, nodesExists, nodesErr := client.GetNodes()
|
||||||
if nodesErr != nil {
|
if nodesErr != nil {
|
||||||
|
@ -284,40 +283,47 @@ func (p *Provider) loadTCPServers(client Client, namespace string, svc traefikv1
|
||||||
return []dynamic.TCPServer{{Address: address}}, nil
|
return []dynamic.TCPServer{{Address: address}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, svc.Name)
|
endpointSlices, err := client.GetEndpointSlicesForService(namespace, svc.Name)
|
||||||
if endpointsErr != nil {
|
if err != nil {
|
||||||
return nil, endpointsErr
|
return nil, fmt.Errorf("getting endpointslices: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !endpointsExists {
|
addresses := map[string]struct{}{}
|
||||||
return nil, errors.New("endpoints not found")
|
for _, endpointSlice := range endpointSlices {
|
||||||
}
|
var port int32
|
||||||
|
for _, p := range endpointSlice.Ports {
|
||||||
if len(endpoints.Subsets) == 0 && !p.AllowEmptyServices {
|
if svcPort.Name == *p.Name {
|
||||||
return nil, errors.New("subset not found")
|
port = *p.Port
|
||||||
}
|
|
||||||
|
|
||||||
var port int32
|
|
||||||
for _, subset := range endpoints.Subsets {
|
|
||||||
for _, p := range subset.Ports {
|
|
||||||
if svcPort.Name == p.Name {
|
|
||||||
port = p.Port
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
return nil, errors.New("cannot define a port")
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range subset.Addresses {
|
for _, endpoint := range endpointSlice.Endpoints {
|
||||||
servers = append(servers, dynamic.TCPServer{
|
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
|
||||||
Address: net.JoinHostPort(addr.IP, strconv.Itoa(int(port))),
|
continue
|
||||||
})
|
}
|
||||||
|
|
||||||
|
for _, address := range endpoint.Addresses {
|
||||||
|
if _, ok := addresses[address]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses[address] = struct{}{}
|
||||||
|
servers = append(servers, dynamic.TCPServer{
|
||||||
|
Address: net.JoinHostPort(address, strconv.Itoa(int(port))),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(servers) == 0 && !p.AllowEmptyServices {
|
||||||
|
return nil, fmt.Errorf("no servers found for %s/%s", namespace, svc.Name)
|
||||||
|
}
|
||||||
|
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4620,9 +4620,9 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "IngressRoute, service with multiple subsets",
|
desc: "IngressRoute, service with multiple endpoint addresses on endpointslice",
|
||||||
allowEmptyServices: true,
|
allowEmptyServices: true,
|
||||||
paths: []string{"services.yml", "with_multiple_subsets.yml"},
|
paths: []string{"services.yml", "with_multiple_endpointaddresses.yml"},
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
UDP: &dynamic.UDPConfiguration{
|
UDP: &dynamic.UDPConfiguration{
|
||||||
Routers: map[string]*dynamic.UDPRouter{},
|
Routers: map[string]*dynamic.UDPRouter{},
|
||||||
|
@ -4648,6 +4648,66 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
"default-test-route-6b204d94623b3df4370c": {
|
"default-test-route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.2:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.5:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.6:80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PassHostHeader: Bool(true),
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||||
|
},
|
||||||
|
TLS: &dynamic.TLSConfiguration{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "IngressRoute, service with duplicated endpointaddresses",
|
||||||
|
allowEmptyServices: true,
|
||||||
|
paths: []string{"services.yml", "with_duplicated_endpointaddresses.yml"},
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
UDP: &dynamic.UDPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.UDPRouter{},
|
||||||
|
Services: map[string]*dynamic.UDPService{},
|
||||||
|
},
|
||||||
|
TCP: &dynamic.TCPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
|
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
||||||
|
Services: map[string]*dynamic.TCPService{},
|
||||||
|
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
||||||
|
},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"default-test-route-6b204d94623b3df4370c": {
|
||||||
|
EntryPoints: []string{"foo"},
|
||||||
|
Service: "default-test-route-6b204d94623b3df4370c",
|
||||||
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
|
Priority: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Services: map[string]*dynamic.Service{
|
||||||
|
"default-test-route-6b204d94623b3df4370c": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:8080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.2:8080",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
URL: "http://10.10.0.3:8080",
|
URL: "http://10.10.0.3:8080",
|
||||||
},
|
},
|
||||||
|
@ -4726,7 +4786,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
Weighted: &dynamic.WeightedRoundRobin{
|
Weighted: &dynamic.WeightedRoundRobin{
|
||||||
Services: []dynamic.WRRService{
|
Services: []dynamic.WRRService{
|
||||||
{
|
{
|
||||||
Name: "default-whoami-without-endpoints-subsets-80",
|
Name: "default-whoami-without-endpointslice-endpoints-80",
|
||||||
Weight: func(i int) *int { return &i }(1),
|
Weight: func(i int) *int { return &i }(1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -4734,10 +4794,10 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
"default-test-mirror": {
|
"default-test-mirror": {
|
||||||
Mirroring: &dynamic.Mirroring{
|
Mirroring: &dynamic.Mirroring{
|
||||||
Service: "default-whoami-without-endpoints-subsets-80",
|
Service: "default-whoami-without-endpointslice-endpoints-80",
|
||||||
Mirrors: []dynamic.MirrorService{
|
Mirrors: []dynamic.MirrorService{
|
||||||
{
|
{
|
||||||
Name: "default-whoami-without-endpoints-subsets-80",
|
Name: "default-whoami-without-endpointslice-endpoints-80",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "default-test-weighted",
|
Name: "default-test-weighted",
|
||||||
|
@ -4745,7 +4805,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default-whoami-without-endpoints-subsets-80": {
|
"default-whoami-without-endpointslice-endpoints-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: Bool(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
@ -4799,6 +4859,87 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadIngressRoutes_multipleEndpointAddresses(t *testing.T) {
|
||||||
|
wantConf := &dynamic.Configuration{
|
||||||
|
UDP: &dynamic.UDPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.UDPRouter{},
|
||||||
|
Services: map[string]*dynamic.UDPService{},
|
||||||
|
},
|
||||||
|
TCP: &dynamic.TCPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
|
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
||||||
|
Services: map[string]*dynamic.TCPService{},
|
||||||
|
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
||||||
|
},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"default-test-route-6b204d94623b3df4370c": {
|
||||||
|
EntryPoints: []string{"foo"},
|
||||||
|
Service: "default-test-route-6b204d94623b3df4370c",
|
||||||
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
|
Priority: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Services: map[string]*dynamic.Service{
|
||||||
|
"default-test-route-6b204d94623b3df4370c": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
PassHostHeader: Bool(true),
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||||
|
},
|
||||||
|
TLS: &dynamic.TLSConfiguration{},
|
||||||
|
}
|
||||||
|
wantServers := []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.3:8080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.4:8080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.5:8080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.6:8080",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sObjects, crdObjects := readResources(t, []string{"services.yml", "with_multiple_endpointslices.yml"})
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, crdClient)
|
||||||
|
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, stopCh)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if k8sObjects != nil || crdObjects != nil {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
p := Provider{}
|
||||||
|
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||||
|
|
||||||
|
service, ok := conf.HTTP.Services["default-test-route-6b204d94623b3df4370c"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, service)
|
||||||
|
require.NotNil(t, service.LoadBalancer)
|
||||||
|
assert.ElementsMatch(t, wantServers, service.LoadBalancer.Servers)
|
||||||
|
|
||||||
|
service.LoadBalancer.Servers = nil
|
||||||
|
assert.Equal(t, wantConf, conf)
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadIngressRouteUDPs(t *testing.T) {
|
func TestLoadIngressRouteUDPs(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|
|
@ -122,7 +122,6 @@ func (p *Provider) loadUDPServers(client Client, namespace string, svc traefikv1
|
||||||
}
|
}
|
||||||
|
|
||||||
var servers []dynamic.UDPServer
|
var servers []dynamic.UDPServer
|
||||||
|
|
||||||
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
|
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
|
||||||
nodes, nodesExists, nodesErr := client.GetNodes()
|
nodes, nodesExists, nodesErr := client.GetNodes()
|
||||||
if nodesErr != nil {
|
if nodesErr != nil {
|
||||||
|
@ -168,39 +167,46 @@ func (p *Provider) loadUDPServers(client Client, namespace string, svc traefikv1
|
||||||
return []dynamic.UDPServer{{Address: address}}, nil
|
return []dynamic.UDPServer{{Address: address}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, svc.Name)
|
endpointSlices, err := client.GetEndpointSlicesForService(namespace, svc.Name)
|
||||||
if endpointsErr != nil {
|
if err != nil {
|
||||||
return nil, endpointsErr
|
return nil, fmt.Errorf("getting endpointslices: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !endpointsExists {
|
addresses := map[string]struct{}{}
|
||||||
return nil, errors.New("endpoints not found")
|
for _, endpointSlice := range endpointSlices {
|
||||||
}
|
var port int32
|
||||||
|
for _, p := range endpointSlice.Ports {
|
||||||
if len(endpoints.Subsets) == 0 && !p.AllowEmptyServices {
|
if svcPort.Name == *p.Name {
|
||||||
return nil, errors.New("subset not found")
|
port = *p.Port
|
||||||
}
|
|
||||||
|
|
||||||
var port int32
|
|
||||||
for _, subset := range endpoints.Subsets {
|
|
||||||
for _, p := range subset.Ports {
|
|
||||||
if svcPort.Name == p.Name {
|
|
||||||
port = p.Port
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
return nil, errors.New("cannot define a port")
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range subset.Addresses {
|
for _, endpoint := range endpointSlice.Endpoints {
|
||||||
servers = append(servers, dynamic.UDPServer{
|
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
|
||||||
Address: net.JoinHostPort(addr.IP, strconv.Itoa(int(port))),
|
continue
|
||||||
})
|
}
|
||||||
|
|
||||||
|
for _, address := range endpoint.Addresses {
|
||||||
|
if _, ok := addresses[address]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses[address] = struct{}{}
|
||||||
|
servers = append(servers, dynamic.UDPServer{
|
||||||
|
Address: net.JoinHostPort(address, strconv.Itoa(int(port))),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(servers) == 0 && !p.AllowEmptyServices {
|
||||||
|
return nil, fmt.Errorf("no servers found for %s/%s", namespace, svc.Name)
|
||||||
|
}
|
||||||
|
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,11 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/selection"
|
||||||
ktypes "k8s.io/apimachinery/pkg/types"
|
ktypes "k8s.io/apimachinery/pkg/types"
|
||||||
kinformers "k8s.io/client-go/informers"
|
kinformers "k8s.io/client-go/informers"
|
||||||
kclientset "k8s.io/client-go/kubernetes"
|
kclientset "k8s.io/client-go/kubernetes"
|
||||||
|
@ -61,9 +63,9 @@ type Client interface {
|
||||||
ListTLSRoutes() ([]*gatev1alpha2.TLSRoute, error)
|
ListTLSRoutes() ([]*gatev1alpha2.TLSRoute, error)
|
||||||
ListNamespaces(selector labels.Selector) ([]string, error)
|
ListNamespaces(selector labels.Selector) ([]string, error)
|
||||||
ListReferenceGrants(namespace string) ([]*gatev1beta1.ReferenceGrant, error)
|
ListReferenceGrants(namespace string) ([]*gatev1beta1.ReferenceGrant, error)
|
||||||
|
ListEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error)
|
||||||
GetService(namespace, name string) (*corev1.Service, bool, error)
|
GetService(namespace, name string) (*corev1.Service, bool, error)
|
||||||
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
||||||
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientWrapper struct {
|
type clientWrapper struct {
|
||||||
|
@ -222,7 +224,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
_, err = factoryKube.Discovery().V1().EndpointSlices().Informer().AddEventHandler(eventHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -543,16 +545,20 @@ func (c *clientWrapper) GetService(namespace, name string) (*corev1.Service, boo
|
||||||
return service, exist, err
|
return service, exist, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEndpoints returns the named endpoints from the given namespace.
|
// ListEndpointSlicesForService returns the EndpointSlices for the given service name in the given namespace.
|
||||||
func (c *clientWrapper) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
func (c *clientWrapper) ListEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error) {
|
||||||
if !c.isWatchedNamespace(namespace) {
|
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)
|
serviceLabelRequirement, err := labels.NewRequirement(discoveryv1.LabelServiceName, selection.Equals, []string{serviceName})
|
||||||
exist, err := translateNotFoundError(err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create service label selector requirement: %w", err)
|
||||||
|
}
|
||||||
|
serviceSelector := labels.NewSelector()
|
||||||
|
serviceSelector = serviceSelector.Add(*serviceLabelRequirement)
|
||||||
|
|
||||||
return endpoint, exist, err
|
return c.factoriesKube[c.lookupNamespace(namespace)].Discovery().V1().EndpointSlices().Lister().EndpointSlices(namespace).List(serviceSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSecret returns the named secret from the given namespace.
|
// GetSecret returns the named secret from the given namespace.
|
||||||
|
|
|
@ -17,21 +17,26 @@ spec:
|
||||||
task: whoami
|
task: whoami
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami
|
name: whoami-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
- name: web2
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 80
|
|
||||||
- name: web2
|
|
||||||
port: 8000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -53,21 +58,26 @@ spec:
|
||||||
task: whoami
|
task: whoami
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami-bar
|
name: whoami-bar-abc
|
||||||
namespace: bar
|
namespace: bar
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami-bar
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
- name: web2
|
||||||
|
port: 8000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.11
|
- 10.10.0.11
|
||||||
- ip: 10.10.0.12
|
- 10.10.0.12
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 80
|
|
||||||
- name: web2
|
|
||||||
port: 8000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -86,19 +96,24 @@ spec:
|
||||||
task: whoami2
|
task: whoami2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami2
|
name: whoami2-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami2
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
- ip: 10.10.0.4
|
- 10.10.0.4
|
||||||
ports:
|
conditions:
|
||||||
- name: web
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -117,19 +132,24 @@ spec:
|
||||||
task: whoami2
|
task: whoami2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitls
|
name: whoamitls-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitls
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: websecure
|
||||||
|
port: 8443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.5
|
- 10.10.0.5
|
||||||
- ip: 10.10.0.6
|
- 10.10.0.6
|
||||||
ports:
|
conditions:
|
||||||
- name: websecure
|
ready: true
|
||||||
port: 8443
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -148,19 +168,24 @@ spec:
|
||||||
task: whoami3
|
task: whoami3
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoami3
|
name: whoami3-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoami3
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: websecure2
|
||||||
|
port: 8443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.7
|
- 10.10.0.7
|
||||||
- ip: 10.10.0.8
|
- 10.10.0.8
|
||||||
ports:
|
conditions:
|
||||||
- name: websecure2
|
ready: true
|
||||||
port: 8443
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -201,23 +226,28 @@ spec:
|
||||||
port: 443
|
port: 443
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp
|
name: whoamitcp-abc
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: tcp-1
|
||||||
|
protocol: TCP
|
||||||
|
port: 9000
|
||||||
|
- name: tcp-2
|
||||||
|
protocol: TCP
|
||||||
|
port: 10000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.9
|
- 10.10.0.9
|
||||||
- ip: 10.10.0.10
|
- 10.10.0.10
|
||||||
ports:
|
conditions:
|
||||||
- name: tcp-1
|
ready: true
|
||||||
protocol: TCP
|
|
||||||
port: 9000
|
|
||||||
- name: tcp-2
|
|
||||||
protocol: TCP
|
|
||||||
port: 10000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -236,23 +266,28 @@ spec:
|
||||||
name: tcp-2
|
name: tcp-2
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: whoamitcp-bar
|
name: whoamitcp-bar-abc
|
||||||
namespace: bar
|
namespace: bar
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: whoamitcp-bar
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: tcp-1
|
||||||
|
protocol: TCP
|
||||||
|
port: 9000
|
||||||
|
- name: tcp-2
|
||||||
|
protocol: TCP
|
||||||
|
port: 10000
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.13
|
- 10.10.0.13
|
||||||
- ip: 10.10.0.14
|
- 10.10.0.14
|
||||||
ports:
|
conditions:
|
||||||
- name: tcp-1
|
ready: true
|
||||||
protocol: TCP
|
|
||||||
port: 9000
|
|
||||||
- name: tcp-2
|
|
||||||
protocol: TCP
|
|
||||||
port: 10000
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
@ -370,6 +370,10 @@ func (p *Provider) loadHTTPRouteFilterExtensionRef(namespace string, extensionRe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) loadHTTPServers(namespace string, backendRef gatev1.HTTPBackendRef) (*dynamic.ServersLoadBalancer, error) {
|
func (p *Provider) loadHTTPServers(namespace string, backendRef gatev1.HTTPBackendRef) (*dynamic.ServersLoadBalancer, error) {
|
||||||
|
if backendRef.Port == nil {
|
||||||
|
return nil, errors.New("port is required for Kubernetes Service reference")
|
||||||
|
}
|
||||||
|
|
||||||
service, exists, err := p.client.GetService(namespace, string(backendRef.Name))
|
service, exists, err := p.client.GetService(namespace, string(backendRef.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting service: %w", err)
|
return nil, fmt.Errorf("getting service: %w", err)
|
||||||
|
@ -378,56 +382,58 @@ func (p *Provider) loadHTTPServers(namespace string, backendRef gatev1.HTTPBacke
|
||||||
return nil, errors.New("service not found")
|
return nil, errors.New("service not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
var portSpec corev1.ServicePort
|
var svcPort *corev1.ServicePort
|
||||||
var match bool
|
|
||||||
|
|
||||||
for _, p := range service.Spec.Ports {
|
for _, p := range service.Spec.Ports {
|
||||||
if backendRef.Port == nil || p.Port == int32(*backendRef.Port) {
|
if p.Port == int32(*backendRef.Port) {
|
||||||
portSpec = p
|
svcPort = &p
|
||||||
match = true
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !match {
|
if svcPort == nil {
|
||||||
return nil, errors.New("service port not found")
|
return nil, fmt.Errorf("service port %d not found", *backendRef.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, endpointsExists, err := p.client.GetEndpoints(namespace, string(backendRef.Name))
|
endpointSlices, err := p.client.ListEndpointSlicesForService(namespace, string(backendRef.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting endpoints: %w", err)
|
return nil, fmt.Errorf("getting endpointslices: %w", err)
|
||||||
}
|
}
|
||||||
if !endpointsExists {
|
if len(endpointSlices) == 0 {
|
||||||
return nil, errors.New("endpoints not found")
|
return nil, errors.New("endpointslices not found")
|
||||||
}
|
|
||||||
|
|
||||||
if len(endpoints.Subsets) == 0 {
|
|
||||||
return nil, errors.New("subset not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lb := &dynamic.ServersLoadBalancer{}
|
lb := &dynamic.ServersLoadBalancer{}
|
||||||
lb.SetDefaults()
|
lb.SetDefaults()
|
||||||
|
|
||||||
var port int32
|
protocol := getProtocol(*svcPort)
|
||||||
var portStr string
|
|
||||||
for _, subset := range endpoints.Subsets {
|
addresses := map[string]struct{}{}
|
||||||
for _, p := range subset.Ports {
|
for _, endpointSlice := range endpointSlices {
|
||||||
if portSpec.Name == p.Name {
|
var port int32
|
||||||
port = p.Port
|
for _, p := range endpointSlice.Ports {
|
||||||
|
if svcPort.Name == *p.Name {
|
||||||
|
port = *p.Port
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
return nil, errors.New("cannot define a port")
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := getProtocol(portSpec)
|
for _, endpoint := range endpointSlice.Endpoints {
|
||||||
|
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
portStr = strconv.FormatInt(int64(port), 10)
|
for _, address := range endpoint.Addresses {
|
||||||
for _, addr := range subset.Addresses {
|
if _, ok := addresses[address]; ok {
|
||||||
lb.Servers = append(lb.Servers, dynamic.Server{
|
continue
|
||||||
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(addr.IP, portStr)),
|
}
|
||||||
})
|
|
||||||
|
addresses[address] = struct{}{}
|
||||||
|
lb.Servers = append(lb.Servers, dynamic.Server{
|
||||||
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(address, strconv.Itoa(int(port)))),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,82 +206,71 @@ func (p *Provider) loadTCPServices(namespace string, backendRefs []gatev1.Backen
|
||||||
return nil, nil, fmt.Errorf("unsupported BackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name)
|
return nil, nil, fmt.Errorf("unsupported BackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
svc := dynamic.TCPService{
|
if backendRef.Port == nil {
|
||||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{},
|
return nil, nil, errors.New("port is required for Kubernetes Service reference")
|
||||||
}
|
}
|
||||||
|
|
||||||
service, exists, err := p.client.GetService(namespace, string(backendRef.Name))
|
service, exists, err := p.client.GetService(namespace, string(backendRef.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, fmt.Errorf("getting service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, nil, errors.New("service not found")
|
return nil, nil, errors.New("service not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(service.Spec.Ports) > 1 && backendRef.Port == nil {
|
var svcPort *corev1.ServicePort
|
||||||
// If the port is unspecified and the backend is a Service
|
|
||||||
// object consisting of multiple port definitions, the route
|
|
||||||
// must be dropped from the Gateway. The controller should
|
|
||||||
// raise the "ResolvedRefs" condition on the Gateway with the
|
|
||||||
// "DroppedRoutes" reason. The gateway status for this route
|
|
||||||
// should be updated with a condition that describes the error
|
|
||||||
// more specifically.
|
|
||||||
log.Error().Msg("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var portSpec corev1.ServicePort
|
|
||||||
var match bool
|
|
||||||
|
|
||||||
for _, p := range service.Spec.Ports {
|
for _, p := range service.Spec.Ports {
|
||||||
if backendRef.Port == nil || p.Port == int32(*backendRef.Port) {
|
if p.Port == int32(*backendRef.Port) {
|
||||||
portSpec = p
|
svcPort = &p
|
||||||
match = true
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if svcPort == nil {
|
||||||
if !match {
|
return nil, nil, fmt.Errorf("service port %d not found", *backendRef.Port)
|
||||||
return nil, nil, errors.New("service port not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, endpointsExists, endpointsErr := p.client.GetEndpoints(namespace, string(backendRef.Name))
|
endpointSlices, err := p.client.ListEndpointSlicesForService(namespace, string(backendRef.Name))
|
||||||
if endpointsErr != nil {
|
if err != nil {
|
||||||
return nil, nil, endpointsErr
|
return nil, nil, fmt.Errorf("getting endpointslices: %w", err)
|
||||||
|
}
|
||||||
|
if len(endpointSlices) == 0 {
|
||||||
|
return nil, nil, errors.New("endpointslices not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !endpointsExists {
|
svc := dynamic.TCPService{LoadBalancer: &dynamic.TCPServersLoadBalancer{}}
|
||||||
return nil, nil, errors.New("endpoints not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(endpoints.Subsets) == 0 {
|
addresses := map[string]struct{}{}
|
||||||
return nil, nil, errors.New("subset not found")
|
for _, endpointSlice := range endpointSlices {
|
||||||
}
|
var port int32
|
||||||
|
for _, p := range endpointSlice.Ports {
|
||||||
var port int32
|
if svcPort.Name == *p.Name {
|
||||||
var portStr string
|
port = *p.Port
|
||||||
for _, subset := range endpoints.Subsets {
|
|
||||||
for _, p := range subset.Ports {
|
|
||||||
if portSpec.Name == p.Name {
|
|
||||||
port = p.Port
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
return nil, nil, errors.New("cannot define a port")
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
portStr = strconv.FormatInt(int64(port), 10)
|
for _, endpoint := range endpointSlice.Endpoints {
|
||||||
for _, addr := range subset.Addresses {
|
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
|
||||||
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, dynamic.TCPServer{
|
continue
|
||||||
Address: net.JoinHostPort(addr.IP, portStr),
|
}
|
||||||
})
|
|
||||||
|
for _, address := range endpoint.Addresses {
|
||||||
|
if _, ok := addresses[address]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses[address] = struct{}{}
|
||||||
|
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, dynamic.TCPServer{
|
||||||
|
Address: net.JoinHostPort(address, strconv.Itoa(int(port))),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceName := provider.Normalize(service.Namespace + "-" + service.Name + "-" + portStr)
|
serviceName := provider.Normalize(service.Namespace + "-" + service.Name + "-" + strconv.Itoa(int(svcPort.Port)))
|
||||||
services[serviceName] = &svc
|
services[serviceName] = &svc
|
||||||
|
|
||||||
wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: serviceName, Weight: &weight})
|
wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: serviceName, Weight: &weight})
|
||||||
|
|
|
@ -16,10 +16,12 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
traefikversion "github.com/traefik/traefik/v3/pkg/version"
|
traefikversion "github.com/traefik/traefik/v3/pkg/version"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
netv1 "k8s.io/api/networking/v1"
|
netv1 "k8s.io/api/networking/v1"
|
||||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/selection"
|
||||||
kinformers "k8s.io/client-go/informers"
|
kinformers "k8s.io/client-go/informers"
|
||||||
kclientset "k8s.io/client-go/kubernetes"
|
kclientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
@ -41,7 +43,7 @@ type Client interface {
|
||||||
GetService(namespace, name string) (*corev1.Service, bool, error)
|
GetService(namespace, name string) (*corev1.Service, bool, error)
|
||||||
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
||||||
GetNodes() ([]*corev1.Node, 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
|
UpdateIngressStatus(ing *netv1.Ingress, ingStatus []netv1.IngressLoadBalancerIngress) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +187,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
_, err = factoryKube.Discovery().V1().EndpointSlices().Informer().AddEventHandler(eventHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -340,15 +342,20 @@ func (c *clientWrapper) GetService(namespace, name string) (*corev1.Service, boo
|
||||||
return service, exist, err
|
return service, exist, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEndpoints returns the named endpoints from the given namespace.
|
// GetEndpointSlicesForService returns the EndpointSlices for the given service name in the given namespace.
|
||||||
func (c *clientWrapper) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
func (c *clientWrapper) GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error) {
|
||||||
if !c.isWatchedNamespace(namespace) {
|
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)
|
serviceLabelRequirement, err := labels.NewRequirement(discoveryv1.LabelServiceName, selection.Equals, []string{serviceName})
|
||||||
exist, err := translateNotFoundError(err)
|
if err != nil {
|
||||||
return endpoint, exist, err
|
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.
|
// GetSecret returns the named secret from the given namespace.
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
netv1 "k8s.io/api/networking/v1"
|
netv1 "k8s.io/api/networking/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,15 +16,15 @@ type clientMock struct {
|
||||||
ingresses []*netv1.Ingress
|
ingresses []*netv1.Ingress
|
||||||
services []*corev1.Service
|
services []*corev1.Service
|
||||||
secrets []*corev1.Secret
|
secrets []*corev1.Secret
|
||||||
endpoints []*corev1.Endpoints
|
endpointSlices []*discoveryv1.EndpointSlice
|
||||||
nodes []*corev1.Node
|
nodes []*corev1.Node
|
||||||
ingressClasses []*netv1.IngressClass
|
ingressClasses []*netv1.IngressClass
|
||||||
|
|
||||||
apiServiceError error
|
apiServiceError error
|
||||||
apiSecretError error
|
apiSecretError error
|
||||||
apiEndpointsError error
|
apiEndpointSlicesError error
|
||||||
apiNodesError error
|
apiNodesError error
|
||||||
apiIngressStatusError error
|
apiIngressStatusError error
|
||||||
|
|
||||||
watchChan chan interface{}
|
watchChan chan interface{}
|
||||||
}
|
}
|
||||||
|
@ -43,8 +44,8 @@ func newClientMock(path string) clientMock {
|
||||||
c.services = append(c.services, o)
|
c.services = append(c.services, o)
|
||||||
case *corev1.Secret:
|
case *corev1.Secret:
|
||||||
c.secrets = append(c.secrets, o)
|
c.secrets = append(c.secrets, o)
|
||||||
case *corev1.Endpoints:
|
case *discoveryv1.EndpointSlice:
|
||||||
c.endpoints = append(c.endpoints, o)
|
c.endpointSlices = append(c.endpointSlices, o)
|
||||||
case *corev1.Node:
|
case *corev1.Node:
|
||||||
c.nodes = append(c.nodes, o)
|
c.nodes = append(c.nodes, o)
|
||||||
case *netv1.Ingress:
|
case *netv1.Ingress:
|
||||||
|
@ -76,18 +77,19 @@ func (c clientMock) GetService(namespace, name string) (*corev1.Service, bool, e
|
||||||
return nil, false, c.apiServiceError
|
return nil, false, c.apiServiceError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c clientMock) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
func (c clientMock) GetEndpointSlicesForService(namespace, serviceName string) ([]*discoveryv1.EndpointSlice, error) {
|
||||||
if c.apiEndpointsError != nil {
|
if c.apiEndpointSlicesError != nil {
|
||||||
return nil, false, c.apiEndpointsError
|
return nil, c.apiEndpointSlicesError
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, endpoints := range c.endpoints {
|
var result []*discoveryv1.EndpointSlice
|
||||||
if endpoints.Namespace == namespace && endpoints.Name == name {
|
for _, endpointSlice := range c.endpointSlices {
|
||||||
return endpoints, true, nil
|
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) {
|
func (c clientMock) GetNodes() ([]*corev1.Node, bool, error) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
netv1 "k8s.io/api/networking/v1"
|
netv1 "k8s.io/api/networking/v1"
|
||||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -188,10 +189,10 @@ func TestClientIgnoresHelmOwnedSecrets(t *testing.T) {
|
||||||
assert.False(t, found)
|
assert.False(t, found)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
|
func TestClientIgnoresEmptyEndpointSliceUpdates(t *testing.T) {
|
||||||
emptyEndpoint := &corev1.Endpoints{
|
emptyEndpointSlice := &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "empty-endpoint",
|
Name: "empty-endpointslice",
|
||||||
Namespace: "test",
|
Namespace: "test",
|
||||||
ResourceVersion: "1244",
|
ResourceVersion: "1244",
|
||||||
Annotations: map[string]string{
|
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{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "filled-endpoint",
|
Name: "filled-endpointslice",
|
||||||
Namespace: "test",
|
Namespace: "test",
|
||||||
ResourceVersion: "1234",
|
ResourceVersion: "1234",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
AddressType: discoveryv1.AddressTypeIPv4,
|
||||||
Addresses: []corev1.EndpointAddress{{
|
Endpoints: []discoveryv1.Endpoint{{
|
||||||
IP: "10.13.37.1",
|
Addresses: []string{"10.13.37.1"},
|
||||||
}},
|
Conditions: discoveryv1.EndpointConditions{
|
||||||
Ports: []corev1.EndpointPort{{
|
Ready: &sampleAddressReady,
|
||||||
Name: "testing",
|
},
|
||||||
Port: 1337,
|
}},
|
||||||
Protocol: "tcp",
|
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, _ := kubeClient.Discovery().(*discoveryfake.FakeDiscovery)
|
||||||
discovery.FakedServerVersion = &kversion.Info{
|
discovery.FakedServerVersion = &kversion.Info{
|
||||||
|
@ -234,50 +241,72 @@ func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case event := <-eventCh:
|
case event := <-eventCh:
|
||||||
ep, ok := event.(*corev1.Endpoints)
|
ep, ok := event.(*discoveryv1.EndpointSlice)
|
||||||
require.True(t, ok)
|
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):
|
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)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Update endpoint annotation and resource version (apparently not done by fake client itself)
|
// 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.
|
// 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.
|
// This reflects the behavior of kubernetes controllers which use endpoint annotations for leader election.
|
||||||
emptyEndpoint.Annotations["test-annotation"] = "___"
|
emptyEndpointSlice.Annotations["test-annotation"] = "___"
|
||||||
emptyEndpoint.ResourceVersion = "1245"
|
emptyEndpointSlice.ResourceVersion = "1245"
|
||||||
_, err = kubeClient.CoreV1().Endpoints("test").Update(context.TODO(), emptyEndpoint, metav1.UpdateOptions{})
|
_, err = kubeClient.DiscoveryV1().EndpointSlices("test").Update(context.TODO(), emptyEndpointSlice, metav1.UpdateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case event := <-eventCh:
|
case event := <-eventCh:
|
||||||
ep, ok := event.(*corev1.Endpoints)
|
ep, ok := event.(*discoveryv1.EndpointSlice)
|
||||||
require.True(t, ok)
|
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):
|
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)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
filledEndpoint.Subsets[0].Addresses[0].IP = "10.13.37.2"
|
filledEndpointSlice.Endpoints[0].Addresses[0] = "10.13.37.2"
|
||||||
filledEndpoint.ResourceVersion = "1235"
|
filledEndpointSlice.ResourceVersion = "1235"
|
||||||
_, err = kubeClient.CoreV1().Endpoints("test").Update(context.TODO(), filledEndpoint, metav1.UpdateOptions{})
|
_, err = kubeClient.DiscoveryV1().EndpointSlices("test").Update(context.TODO(), filledEndpointSlice, metav1.UpdateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case event := <-eventCh:
|
case event := <-eventCh:
|
||||||
ep, ok := event.(*corev1.Endpoints)
|
ep, ok := event.(*discoveryv1.EndpointSlice)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
assert.Equal(t, "filled-endpoint", ep.Name)
|
assert.Equal(t, "filled-endpointslice", ep.Name)
|
||||||
case <-time.After(50 * time.Millisecond):
|
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 {
|
select {
|
||||||
|
|
|
@ -1,32 +1,42 @@
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: tchouk
|
ready: true
|
||||||
port: 8089
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: toto
|
namespace: toto
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.11.0.1
|
- 10.11.0.1
|
||||||
- ip: 10.11.0.2
|
- 10.11.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: tchouk
|
ready: true
|
||||||
port: 8089
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
|
|
|
@ -50,35 +50,41 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiversion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.30.0.1
|
- 10.30.0.1
|
||||||
ports:
|
- 10.41.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.41.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiversion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service2
|
name: service2-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service2
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -40,18 +40,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -37,18 +37,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -30,18 +30,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -36,18 +36,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -52,15 +52,20 @@ spec:
|
||||||
externalName: "2001:0db8:3c4d:0015:0000:0000:1a2f:2a3b"
|
externalName: "2001:0db8:3c4d:0015:0000:0000:1a2f:2a3b"
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service-bar
|
name: service-bar-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service-bar
|
||||||
|
|
||||||
subsets:
|
addressType: IPv6
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8080
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b"
|
- "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b"
|
||||||
ports:
|
conditions:
|
||||||
- name: http
|
ready: true
|
||||||
port: 8080
|
|
||||||
|
|
|
@ -30,18 +30,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8443
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8443
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8443
|
|
|
@ -31,20 +31,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: https
|
||||||
|
port: 8443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- name: https
|
conditions:
|
||||||
port: 8443
|
ready: true
|
||||||
- addresses:
|
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- name: https
|
|
||||||
port: 8443
|
|
||||||
|
|
|
@ -31,20 +31,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: https-foo
|
||||||
|
port: 8443
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- name: https-foo
|
conditions:
|
||||||
port: 8443
|
ready: true
|
||||||
- addresses:
|
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- name: https-foo
|
|
||||||
port: 8443
|
|
||||||
|
|
|
@ -29,18 +29,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -33,23 +33,42 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: tchouk
|
ready: true
|
||||||
port: 8089
|
|
||||||
|
---
|
||||||
|
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:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
- ip: 10.10.0.3
|
- 10.10.0.3
|
||||||
ports:
|
conditions:
|
||||||
- name: carotte
|
ready: true
|
||||||
port: 8090
|
|
|
@ -53,18 +53,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -41,18 +41,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -37,18 +37,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -31,14 +31,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -36,27 +36,38 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 80
|
ready: true
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: defaultservice
|
name: defaultservice-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: defaultservice
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -30,14 +30,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -28,14 +28,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -30,14 +30,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -30,14 +30,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -31,14 +31,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -37,15 +37,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
||||||
|
|
|
@ -64,14 +64,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -29,14 +29,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -64,14 +64,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -29,15 +29,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: foobar
|
||||||
|
port: 4711
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- name: foobar
|
ready: true
|
||||||
port: 4711
|
|
||||||
|
|
|
@ -31,14 +31,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -31,15 +31,20 @@ spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: example-com
|
name: example-com-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: example-com
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.11.0.1
|
- 10.11.0.1
|
||||||
ports:
|
conditions:
|
||||||
- name: http
|
ready: true
|
||||||
port: 80
|
|
||||||
|
|
|
@ -30,8 +30,14 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports: null
|
||||||
|
endpoints: []
|
||||||
|
|
|
@ -40,24 +40,43 @@ spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
kind: EndpointSlice
|
||||||
kind: Endpoints
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
subsets:
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: http-admin
|
||||||
|
port: 8079
|
||||||
|
protocol: TCP
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.0.0.1
|
- 10.0.0.1
|
||||||
nodeName: admin.whoami.service1
|
conditions:
|
||||||
ports:
|
ready: true
|
||||||
- name: http-admin
|
nodeName: admin.whoami.service1
|
||||||
port: 8079
|
|
||||||
protocol: TCP
|
---
|
||||||
|
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:
|
- addresses:
|
||||||
- ip: 10.0.0.1
|
- 10.0.0.1
|
||||||
nodeName: whoami.service1
|
conditions:
|
||||||
# targetRef:
|
ready: true
|
||||||
ports:
|
nodeName: whoami.service1
|
||||||
- name: http
|
|
||||||
port: 8080
|
|
||||||
protocol: TCP
|
|
|
@ -33,18 +33,23 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: carotte
|
||||||
|
port: 8090
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: carotte
|
ready: true
|
||||||
port: 8090
|
|
||||||
- name: tchouk
|
|
||||||
port: 8089
|
|
||||||
|
|
|
@ -33,24 +33,23 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: carotte
|
||||||
|
port: 8090
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- name: carotte
|
conditions:
|
||||||
port: 8090
|
ready: true
|
||||||
- name: tchouk
|
|
||||||
port: 8089
|
|
||||||
- addresses:
|
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- name: carotte
|
|
||||||
port: 8090
|
|
||||||
- name: tchouk
|
|
||||||
port: 8089
|
|
||||||
|
|
|
@ -33,24 +33,23 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: carotte
|
||||||
|
port: 8090
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- name: carotte
|
conditions:
|
||||||
port: 8090
|
ready: true
|
||||||
- name: tchouk
|
|
||||||
port: 8089
|
|
||||||
- addresses:
|
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- name: carotte
|
|
||||||
port: 8090
|
|
||||||
- name: tchouk
|
|
||||||
port: 8089
|
|
||||||
|
|
|
@ -28,14 +28,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -38,18 +38,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -40,18 +40,23 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: carotte
|
||||||
|
port: 8090
|
||||||
|
- name: tchouk
|
||||||
|
port: 8089
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
conditions:
|
||||||
- name: carotte
|
ready: true
|
||||||
port: 8090
|
|
||||||
- name: tchouk
|
|
||||||
port: 8089
|
|
||||||
|
|
|
@ -52,35 +52,41 @@ spec:
|
||||||
clusterIP: 10.1.0.1
|
clusterIP: 10.1.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service2
|
name: service2-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service2
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.2
|
- 10.10.0.2
|
||||||
ports:
|
- 10.21.0.2
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.2
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -30,15 +30,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8089
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.11.0.1
|
- 10.11.0.1
|
||||||
- ip: 10.11.0.2
|
- 10.11.0.2
|
||||||
ports:
|
conditions:
|
||||||
- port: 8089
|
ready: true
|
||||||
|
|
|
@ -30,15 +30,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8089
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.11.0.1
|
- 10.11.0.1
|
||||||
- ip: 10.11.0.2
|
- 10.11.0.2
|
||||||
ports:
|
conditions:
|
||||||
- port: 8089
|
ready: true
|
||||||
|
|
|
@ -30,14 +30,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -31,14 +31,20 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
conditions:
|
||||||
- port: 8080
|
ready: true
|
||||||
|
|
|
@ -24,18 +24,21 @@ spec:
|
||||||
clusterIP: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: service1
|
name: service1-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.10.0.1
|
- 10.10.0.1
|
||||||
ports:
|
- 10.21.0.1
|
||||||
- port: 8080
|
conditions:
|
||||||
- addresses:
|
ready: true
|
||||||
- ip: 10.21.0.1
|
|
||||||
ports:
|
|
||||||
- port: 8080
|
|
||||||
|
|
|
@ -83,15 +83,20 @@ spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: EndpointSlice
|
||||||
apiVersion: v1
|
apiVersion: discovery.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: example-com
|
name: example-com-abc
|
||||||
namespace: testing
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: example-com
|
||||||
|
|
||||||
subsets:
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
endpoints:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 10.11.0.1
|
- 10.11.0.1
|
||||||
ports:
|
conditions:
|
||||||
- name: http
|
ready: true
|
||||||
port: 80
|
|
||||||
|
|
|
@ -651,36 +651,41 @@ func (p *Provider) loadService(client Client, namespace string, backend netv1.In
|
||||||
return svc, nil
|
return svc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, backend.Service.Name)
|
endpointSlices, err := client.GetEndpointSlicesForService(namespace, backend.Service.Name)
|
||||||
if endpointsErr != nil {
|
if err != nil {
|
||||||
return nil, endpointsErr
|
return nil, fmt.Errorf("getting endpointslices: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !endpointsExists {
|
addresses := map[string]struct{}{}
|
||||||
return nil, errors.New("endpoints not found")
|
for _, endpointSlice := range endpointSlices {
|
||||||
}
|
|
||||||
|
|
||||||
for _, subset := range endpoints.Subsets {
|
|
||||||
var port int32
|
var port int32
|
||||||
for _, p := range subset.Ports {
|
for _, p := range endpointSlice.Ports {
|
||||||
if portName == p.Name {
|
if portName == *p.Name {
|
||||||
port = p.Port
|
port = *p.Port
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := getProtocol(portSpec, portName, svcConfig)
|
protocol := getProtocol(portSpec, portName, svcConfig)
|
||||||
|
|
||||||
for _, addr := range subset.Addresses {
|
for _, endpoint := range endpointSlice.Endpoints {
|
||||||
hostPort := net.JoinHostPort(addr.IP, strconv.Itoa(int(port)))
|
if endpoint.Conditions.Ready == nil || !*endpoint.Conditions.Ready {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, dynamic.Server{
|
for _, address := range endpoint.Addresses {
|
||||||
URL: fmt.Sprintf("%s://%s", protocol, hostPort),
|
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)))),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package k8s
|
package k8s
|
||||||
|
|
||||||
import (
|
import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -47,61 +47,54 @@ func objChanged(oldObj, newObj interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := oldObj.(*corev1.Endpoints); ok {
|
if _, ok := oldObj.(*discoveryv1.EndpointSlice); ok {
|
||||||
return endpointsChanged(oldObj.(*corev1.Endpoints), newObj.(*corev1.Endpoints))
|
return endpointSliceChanged(oldObj.(*discoveryv1.EndpointSlice), newObj.(*discoveryv1.EndpointSlice))
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func endpointsChanged(a, b *corev1.Endpoints) bool {
|
// In some Kubernetes versions leader election is done by updating an endpoint annotation every second,
|
||||||
if len(a.Subsets) != len(b.Subsets) {
|
// if there are no changes to the endpoints addresses, ports, and there are no addresses defined for an endpoint
|
||||||
|
// the event can safely be ignored and won't cause unnecessary config reloads.
|
||||||
|
// TODO: check if Kubernetes is still using EndpointSlice for leader election, which seems to not be the case anymore.
|
||||||
|
func endpointSliceChanged(a, b *discoveryv1.EndpointSlice) bool {
|
||||||
|
if len(a.Ports) != len(b.Ports) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, sa := range a.Subsets {
|
for i, aport := range a.Ports {
|
||||||
sb := b.Subsets[i]
|
bport := b.Ports[i]
|
||||||
if subsetsChanged(sa, sb) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func subsetsChanged(sa, sb corev1.EndpointSubset) bool {
|
|
||||||
if len(sa.Addresses) != len(sb.Addresses) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sa.Ports) != len(sb.Ports) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// in Addresses and Ports, we should be able to rely on
|
|
||||||
// these being sorted and able to be compared
|
|
||||||
// they are supposed to be in a canonical format
|
|
||||||
for addr, aaddr := range sa.Addresses {
|
|
||||||
baddr := sb.Addresses[addr]
|
|
||||||
if aaddr.IP != baddr.IP {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if aaddr.Hostname != baddr.Hostname {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for port, aport := range sa.Ports {
|
|
||||||
bport := sb.Ports[port]
|
|
||||||
if aport.Name != bport.Name {
|
if aport.Name != bport.Name {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if aport.Port != bport.Port {
|
if aport.Port != bport.Port {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if aport.Protocol != bport.Protocol {
|
if len(a.Endpoints) != len(b.Endpoints) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ea := range a.Endpoints {
|
||||||
|
eb := b.Endpoints[i]
|
||||||
|
if endpointChanged(ea, eb) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func endpointChanged(a, b discoveryv1.Endpoint) bool {
|
||||||
|
if len(a.Addresses) != len(b.Addresses) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, aaddr := range a.Addresses {
|
||||||
|
baddr := b.Addresses[i]
|
||||||
|
if aaddr != baddr {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
corev1 "k8s.io/api/core/v1"
|
discoveryv1 "k8s.io/api/discovery/v1"
|
||||||
netv1 "k8s.io/api/networking/v1"
|
netv1 "k8s.io/api/networking/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_detectChanges(t *testing.T) {
|
func Test_detectChanges(t *testing.T) {
|
||||||
|
portA := int32(80)
|
||||||
|
portB := int32(8080)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
oldObj interface{}
|
oldObj interface{}
|
||||||
|
@ -21,28 +23,28 @@ func Test_detectChanges(t *testing.T) {
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With empty endpoints",
|
name: "With empty endpointslice",
|
||||||
oldObj: &corev1.Endpoints{},
|
oldObj: &discoveryv1.EndpointSlice{},
|
||||||
newObj: &corev1.Endpoints{},
|
newObj: &discoveryv1.EndpointSlice{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With old nil",
|
name: "With old nil",
|
||||||
newObj: &corev1.Endpoints{},
|
newObj: &discoveryv1.EndpointSlice{},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With new nil",
|
name: "With new nil",
|
||||||
oldObj: &corev1.Endpoints{},
|
oldObj: &discoveryv1.EndpointSlice{},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With same version",
|
name: "With same version",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
|
@ -50,12 +52,12 @@ func Test_detectChanges(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With different version",
|
name: "With different version",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
},
|
},
|
||||||
|
@ -90,7 +92,7 @@ func Test_detectChanges(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With same annotations",
|
name: "With same annotations",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
|
@ -98,7 +100,7 @@ func Test_detectChanges(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
|
@ -109,7 +111,7 @@ func Test_detectChanges(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With different annotations",
|
name: "With different annotations",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
|
@ -117,7 +119,7 @@ func Test_detectChanges(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
|
@ -127,384 +129,94 @@ func Test_detectChanges(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With same subsets",
|
name: "With same endpoints and ports",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{},
|
Endpoints: []discoveryv1.Endpoint{},
|
||||||
|
Ports: []discoveryv1.EndpointPort{},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{},
|
Endpoints: []discoveryv1.Endpoint{},
|
||||||
|
Ports: []discoveryv1.EndpointPort{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With different len of subsets",
|
name: "With different len of endpoints",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{},
|
Endpoints: []discoveryv1.Endpoint{},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{}},
|
Endpoints: []discoveryv1.Endpoint{{}},
|
||||||
},
|
},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With same subsets with same len of addresses",
|
name: "With different endpoints",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
Endpoints: []discoveryv1.Endpoint{{
|
||||||
Addresses: []corev1.EndpointAddress{},
|
Addresses: []string{"10.10.10.10"},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
Endpoints: []discoveryv1.Endpoint{{
|
||||||
Addresses: []corev1.EndpointAddress{},
|
Addresses: []string{"10.10.10.11"},
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with different len of addresses",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{}},
|
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With same subsets with same len of ports",
|
name: "With different len of ports",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
Ports: []discoveryv1.EndpointPort{},
|
||||||
Ports: []corev1.EndpointPort{},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
Ports: []discoveryv1.EndpointPort{{}},
|
||||||
Ports: []corev1.EndpointPort{},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with different len of ports",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{}},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With same subsets with same len of addresses with same ip",
|
name: "With different ports",
|
||||||
oldObj: &corev1.Endpoints{
|
oldObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "1",
|
ResourceVersion: "1",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
Ports: []discoveryv1.EndpointPort{{
|
||||||
Addresses: []corev1.EndpointAddress{{
|
Port: &portA,
|
||||||
IP: "10.10.10.10",
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
newObj: &corev1.Endpoints{
|
newObj: &discoveryv1.EndpointSlice{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
ResourceVersion: "2",
|
ResourceVersion: "2",
|
||||||
},
|
},
|
||||||
Subsets: []corev1.EndpointSubset{{
|
Ports: []discoveryv1.EndpointPort{{
|
||||||
Addresses: []corev1.EndpointAddress{{
|
Port: &portB,
|
||||||
IP: "10.10.10.10",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of addresses with different ip",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
IP: "10.10.10.10",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
IP: "10.10.10.42",
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "With same subsets with same len of addresses with same hostname",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
Hostname: "foo",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
Hostname: "foo",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of addresses with same hostname",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
Hostname: "foo",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
Hostname: "bar",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of port with same name",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Name: "foo",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Name: "foo",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of port with different name",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Name: "foo",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Name: "bar",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of port with same port",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Port: 4242,
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Port: 4242,
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of port with different port",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Port: 4242,
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Port: 6969,
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of port with same protocol",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Protocol: "HTTP",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Protocol: "HTTP",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same len of port with different protocol",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Protocol: "HTTP",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Protocol: "TCP",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With same subsets with same subset",
|
|
||||||
oldObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
IP: "10.10.10.10",
|
|
||||||
Hostname: "foo",
|
|
||||||
}},
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Name: "bar",
|
|
||||||
Port: 4242,
|
|
||||||
Protocol: "HTTP",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
newObj: &corev1.Endpoints{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
ResourceVersion: "2",
|
|
||||||
},
|
|
||||||
Subsets: []corev1.EndpointSubset{{
|
|
||||||
Addresses: []corev1.EndpointAddress{{
|
|
||||||
IP: "10.10.10.10",
|
|
||||||
Hostname: "foo",
|
|
||||||
}},
|
|
||||||
Ports: []corev1.EndpointPort{{
|
|
||||||
Name: "bar",
|
|
||||||
Port: 4242,
|
|
||||||
Protocol: "HTTP",
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
// MustParseYaml parses a YAML to objects.
|
// MustParseYaml parses a YAML to objects.
|
||||||
func MustParseYaml(content []byte) []runtime.Object {
|
func MustParseYaml(content []byte) []runtime.Object {
|
||||||
acceptedK8sTypes := regexp.MustCompile(`^(Namespace|Deployment|Endpoints|Node|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|ServersTransportTCP|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute|ReferenceGrant)$`)
|
acceptedK8sTypes := regexp.MustCompile(`^(Namespace|Deployment|EndpointSlice|Node|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|ServersTransportTCP|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute|ReferenceGrant)$`)
|
||||||
|
|
||||||
files := strings.Split(string(content), "---\n")
|
files := strings.Split(string(content), "---\n")
|
||||||
retVal := make([]runtime.Object, 0, len(files))
|
retVal := make([]runtime.Object, 0, len(files))
|
||||||
|
|
Loading…
Reference in a new issue