Repository: prometheus/prometheus (language: go)

Issue:
Consider removing support for deprecated k8s APIs in service discovery
### Proposal

Prometheus currently supports discovering the following roles with deprecated APIs:
* `discovery.k8s.io/v1beta1` of EndpointSlice, [no longer served as of k8s 1.25](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#endpointslice-v125)
* `networking.k8s.io/v1beta1` of Ingress, [no longer served as of k8s 1.22](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122)

Considering that k8s 1.22 is End of Life since 2022-12-08 and k8s 1.25 will be on 2023-10-28, it might be worth considering removing support for those, which will simplify the maintenance of the discovery code.
I haven't been able to find a policy that describes the supported k8s versions in Prometheus, would that also be something worth clarifying in the process?


Discussion / hints:
I do not think it costs us a lot to maintain the code, and when new deprecations will come we might to rewite the code to handle them again. for me it's a no-cost to keep them as far as I see it.
It's actually making contributions in that area trickier. Take for example #12338: it took me some time to figure out why the code is the way it is in the first place (I hadn't looked at the SD bits ever before), and then fix each test twice. Similarly, any change to ingress/endpointslices data lookup will need to be duplicated.
Worth noting that the API is not just deprecated though: it's just gone from supported versions of k8s.

Re: deprecations: the ones that this issues refers to were not GA and as such the stability guarantees around them weren't very strong. `networking.k8s.io/v1` Ingresses are GA for instance, and so them going away anytime soon is extremely unlikely. From the [deprecation policy](https://kubernetes.io/docs/reference/using-api/deprecation-policy/):
> There are no current plans for a major version revision of Kubernetes that removes GA APIs.
Okay, I understand better your feedback and it's important to us. I will
carry this issue to the proper maintainer.

Le mar. 26 sept. 2023, 19:15, Mickaël Carl ***@***.***> a
écrit :

> It's actually making contributions in that area trickier. Take for example
> #12338 <https://github.com/prometheus/prometheus/pull/12338>: it took me
> some time to figure out why the code is the way it is in the first place (I
> hadn't looked at the SD bits ever before), and then fix each test twice.
> Similarly, any change to ingress/endpointslices data lookup will need to be
> duplicated.
> Worth noting that the API is not just deprecated though: it's just gone
> from supported versions of k8s.
>
> Re: deprecations: the ones that this issues refers to were not GA and as
> such the stability guarantees around them weren't very strong.
> networking.k8s.io/v1 Ingresses are GA for instance, and so them going
> away anytime soon is extremely unlikely. From the deprecation policy
> <https://kubernetes.io/docs/reference/using-api/deprecation-policy/>:
>
> There are no current plans for a major version revision of Kubernetes that
> removes GA APIs.
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/prometheus/prometheus/issues/12884#issuecomment-1735961851>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AACHHJSQOVZVVOGWAPPSCHLX4MESVANCNFSM6AAAAAA5EBU2FA>
> .
> You are receiving this because you commented.Message ID:
> ***@***.***>
>

Even though I wholeheartedly agree with you @mickael-carl, I unfortunately know lots of companies that are using versions as old as 1.20 fully supported by the respective provider, so if we break that compatibility we'll force them to be stranded on old Prometheus versions. I don't like it myself either, but I think for Prometheus it would be best to keep this support for another year or two.
Well, the nice thing is that this wouldn't break 1.20 compatibility, only some APIs that were already marked as deprecated at that time. The only thing that would be broken would be folks still using the v1beta1 version of ingresses and that's a pretty easy thing to fix right?
I see what you mean. What would the actual compatibility be then? As in the first version that serves the v1 APIs?
Ingress v1 has been available since k8s 1.19, which has deprecated the v1beta1 API as well, from the changelog:
> `Ingress` and `IngressClass` resources have graduated to `networking.k8s.io/v1`. Ingress and IngressClass types in the `extensions/v1beta1` and `networking.k8s.io/v1beta1` API versions are deprecated and will no longer be served in 1.22+. Persisted objects can be accessed via the `networking.k8s.io/v1` API.
hmm .. I'm inclined to agree with you, but what do you think of running a Twitter and Mastodon poll to gauge an indication of versions used (just to make extra sure)?
This was reviewed during the Prometheus Bug Scrub.

@brancz some time has passed since the last comment, perhaps you could make a final call on whether we take the change in or not?

I personally agree on dropping support for v1beta1 kind because it was deprecated some time ago. We can always add it later if this caused an issue to many users.
@brancz while I wouldn't mind sending out such a survey, I actually wouldn't be able to, not having an account on any of those platforms 🙂 Additionally and fwiw (just to try and make my case a bit further), 1.29 just came out marking 10+ versions in a row for the availability of ingress v1, and the deprecation of ingress v1beta1. Similarly, it's now been 9 releases that EndpointSlice v1beta1 is deprecated.
Adding the "Prometheus 3.0" milestone since it could make sense for a new major version to drop deprecated APIs?
We discussed this at the dev summit today. There weren't many attendees, so take this with a grain of salt, but the general consensus was to drop the deprecated API with v3.

If anyone has issues with that, please comment here.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ad5bb50da2..17ac358fa50 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
 _Please add changes here that are only in the release-3.0 branch. These will be the source for the changelog when cutting the first release candidate for v3.0.0._
 
 * [CHANGE] PromQL: Range selectors and the lookback delta are now left-open, i.e. a sample coinciding with the lower time limit is excluded rather than included. #13904
+* [CHANGE] Kubernetes SD: Remove support for `discovery.k8s.io/v1beta1` API version of EndpointSlice. This version is no longer served as of Kubernetes v1.25. #14365
+* [CHANGE] Kubernetes SD: Remove support for `networking.k8s.io/v1beta1` API version of Ingress. This version is no longer served as of Kubernetes v1.22. #14365
 
 ## unreleased
 
diff --git a/discovery/kubernetes/endpointslice.go b/discovery/kubernetes/endpointslice.go
index 7a70255c122..2ac65ef4141 100644
--- a/discovery/kubernetes/endpointslice.go
+++ b/discovery/kubernetes/endpointslice.go
@@ -26,7 +26,6 @@ import (
 	"github.com/prometheus/common/model"
 	apiv1 "k8s.io/api/core/v1"
 	v1 "k8s.io/api/discovery/v1"
-	"k8s.io/api/discovery/v1beta1"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/util/workqueue"
 
@@ -103,9 +102,9 @@ func NewEndpointSlice(l log.Logger, eps cache.SharedIndexInformer, svc, pod, nod
 			return
 		}
 
-		// TODO(brancz): use cache.Indexer to index endpoints by
-		// disv1beta1.LabelServiceName so this operation doesn't have to
-		// iterate over all endpoint objects.
+		// TODO(brancz): use cache.Indexer to index endpointslices by
+		// LabelServiceName so this operation doesn't have to iterate over all
+		// endpoint objects.
 		for _, obj := range e.endpointSliceStore.List() {
 			esa, err := e.getEndpointSliceAdaptor(obj)
 			if err != nil {
@@ -241,8 +240,6 @@ func (e *EndpointSlice) getEndpointSliceAdaptor(o interface{}) (endpointSliceAda
 	switch endpointSlice := o.(type) {
 	case *v1.EndpointSlice:
 		return newEndpointSliceAdaptorFromV1(endpointSlice), nil
-	case *v1beta1.EndpointSlice:
-		return newEndpointSliceAdaptorFromV1beta1(endpointSlice), nil
 	default:
 		return nil, fmt.Errorf("received unexpected object: %v", o)
 	}
diff --git a/discovery/kubernetes/endpointslice_adaptor.go b/discovery/kubernetes/endpointslice_adaptor.go
index edd64fcb327..81243e2ce0a 100644
--- a/discovery/kubernetes/endpointslice_adaptor.go
+++ b/discovery/kubernetes/endpointslice_adaptor.go
@@ -16,7 +16,6 @@ package kubernetes
 import (
 	corev1 "k8s.io/api/core/v1"
 	v1 "k8s.io/api/discovery/v1"
-	"k8s.io/api/discovery/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -109,59 +108,6 @@ func (e *endpointSliceAdaptorV1) labelServiceName() string {
 	return v1.LabelServiceName
 }
 
-// Adaptor for k8s.io/api/discovery/v1beta1.
-type endpointSliceAdaptorV1Beta1 struct {
-	endpointSlice *v1beta1.EndpointSlice
-}
-
-func newEndpointSliceAdaptorFromV1beta1(endpointSlice *v1beta1.EndpointSlice) endpointSliceAdaptor {
-	return &endpointSliceAdaptorV1Beta1{endpointSlice: endpointSlice}
-}
-
-func (e *endpointSliceAdaptorV1Beta1) get() interface{} {
-	return e.endpointSlice
-}
-
-func (e *endpointSliceAdaptorV1Beta1) getObjectMeta() metav1.ObjectMeta {
-	return e.endpointSlice.ObjectMeta
-}
-
-func (e *endpointSliceAdaptorV1Beta1) name() string {
-	return e.endpointSlice.Name
-}
-
-func (e *endpointSliceAdaptorV1Beta1) namespace() string {
-	return e.endpointSlice.Namespace
-}
-
-func (e *endpointSliceAdaptorV1Beta1) addressType() string {
-	return string(e.endpointSlice.AddressType)
-}
-
-func (e *endpointSliceAdaptorV1Beta1) endpoints() []endpointSliceEndpointAdaptor {
-	eps := make([]endpointSliceEndpointAdaptor, 0, len(e.endpointSlice.Endpoints))
-	for i := 0; i < len(e.endpointSlice.Endpoints); i++ {
-		eps = append(eps, newEndpointSliceEndpointAdaptorFromV1beta1(e.endpointSlice.Endpoints[i]))
-	}
-	return eps
-}
-
-func (e *endpointSliceAdaptorV1Beta1) ports() []endpointSlicePortAdaptor {
-	ports := make([]endpointSlicePortAdaptor, 0, len(e.endpointSlice.Ports))
-	for i := 0; i < len(e.endpointSlice.Ports); i++ {
-		ports = append(ports, newEndpointSlicePortAdaptorFromV1beta1(e.endpointSlice.Ports[i]))
-	}
-	return ports
-}
-
-func (e *endpointSliceAdaptorV1Beta1) labels() map[string]string {
-	return e.endpointSlice.Labels
-}
-
-func (e *endpointSliceAdaptorV1Beta1) labelServiceName() string {
-	return v1beta1.LabelServiceName
-}
-
 type endpointSliceEndpointAdaptorV1 struct {
 	endpoint v1.Endpoint
 }
@@ -218,62 +164,6 @@ func (e *endpointSliceEndpointConditionsAdaptorV1) terminating() *bool {
 	return e.endpointConditions.Terminating
 }
 
-type endpointSliceEndpointAdaptorV1beta1 struct {
-	endpoint v1beta1.Endpoint
-}
-
-func newEndpointSliceEndpointAdaptorFromV1beta1(endpoint v1beta1.Endpoint) endpointSliceEndpointAdaptor {
-	return &endpointSliceEndpointAdaptorV1beta1{endpoint: endpoint}
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) addresses() []string {
-	return e.endpoint.Addresses
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) hostname() *string {
-	return e.endpoint.Hostname
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) nodename() *string {
-	return e.endpoint.NodeName
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) zone() *string {
-	return nil
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) conditions() endpointSliceEndpointConditionsAdaptor {
-	return newEndpointSliceEndpointConditionsAdaptorFromV1beta1(e.endpoint.Conditions)
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) targetRef() *corev1.ObjectReference {
-	return e.endpoint.TargetRef
-}
-
-func (e *endpointSliceEndpointAdaptorV1beta1) topology() map[string]string {
-	return e.endpoint.Topology
-}
-
-type endpointSliceEndpointConditionsAdaptorV1beta1 struct {
-	endpointConditions v1beta1.EndpointConditions
-}
-
-func newEndpointSliceEndpointConditionsAdaptorFromV1beta1(endpointConditions v1beta1.EndpointConditions) endpointSliceEndpointConditionsAdaptor {
-	return &endpointSliceEndpointConditionsAdaptorV1beta1{endpointConditions: endpointConditions}
-}
-
-func (e *endpointSliceEndpointConditionsAdaptorV1beta1) ready() *bool {
-	return e.endpointConditions.Ready
-}
-
-func (e *endpointSliceEndpointConditionsAdaptorV1beta1) serving() *bool {
-	return e.endpointConditions.Serving
-}
-
-func (e *endpointSliceEndpointConditionsAdaptorV1beta1) terminating() *bool {
-	return e.endpointConditions.Terminating
-}
-
 type endpointSlicePortAdaptorV1 struct {
 	endpointPort v1.EndpointPort
 }
@@ -298,28 +188,3 @@ func (e *endpointSlicePortAdaptorV1) protocol() *string {
 func (e *endpointSlicePortAdaptorV1) appProtocol() *string {
 	return e.endpointPort.AppProtocol
 }
-
-type endpointSlicePortAdaptorV1beta1 struct {
-	endpointPort v1beta1.EndpointPort
-}
-
-func newEndpointSlicePortAdaptorFromV1beta1(port v1beta1.EndpointPort) endpointSlicePortAdaptor {
-	return &endpointSlicePortAdaptorV1beta1{endpointPort: port}
-}
-
-func (e *endpointSlicePortAdaptorV1beta1) name() *string {
-	return e.endpointPort.Name
-}
-
-func (e *endpointSlicePortAdaptorV1beta1) port() *int32 {
-	return e.endpointPort.Port
-}
-
-func (e *endpointSlicePortAdaptorV1beta1) protocol() *string {
-	val := string(*e.endpointPort.Protocol)
-	return &val
-}
-
-func (e *endpointSlicePortAdaptorV1beta1) appProtocol() *string {
-	return e.endpointPort.AppProtocol
-}
diff --git a/discovery/kubernetes/ingress.go b/discovery/kubernetes/ingress.go
index 7b6366b257b..4d91e7a4602 100644
--- a/discovery/kubernetes/ingress.go
+++ b/discovery/kubernetes/ingress.go
@@ -24,7 +24,6 @@ import (
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/common/model"
 	v1 "k8s.io/api/networking/v1"
-	"k8s.io/api/networking/v1beta1"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/util/workqueue"
 
@@ -127,8 +126,6 @@ func (i *Ingress) process(ctx context.Context, ch chan<- []*targetgroup.Group) b
 	switch ingress := o.(type) {
 	case *v1.Ingress:
 		ia = newIngressAdaptorFromV1(ingress)
-	case *v1beta1.Ingress:
-		ia = newIngressAdaptorFromV1beta1(ingress)
 	default:
 		level.Error(i.logger).Log("msg", "converting to Ingress object failed", "err",
 			fmt.Errorf("received unexpected object: %v", o))
diff --git a/discovery/kubernetes/ingress_adaptor.go b/discovery/kubernetes/ingress_adaptor.go
index d1a7b7f2a2f..84281196b4a 100644
--- a/discovery/kubernetes/ingress_adaptor.go
+++ b/discovery/kubernetes/ingress_adaptor.go
@@ -15,7 +15,6 @@ package kubernetes
 
 import (
 	v1 "k8s.io/api/networking/v1"
-	"k8s.io/api/networking/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -89,56 +88,3 @@ func (i *ingressRuleAdaptorV1) paths() []string {
 }
 
 func (i *ingressRuleAdaptorV1) host() string { return i.rule.Host }
-
-// Adaptor for networking.k8s.io/v1beta1.
-type ingressAdaptorV1Beta1 struct {
-	ingress *v1beta1.Ingress
-}
-
-func newIngressAdaptorFromV1beta1(ingress *v1beta1.Ingress) ingressAdaptor {
-	return &ingressAdaptorV1Beta1{ingress: ingress}
-}
-func (i *ingressAdaptorV1Beta1) getObjectMeta() metav1.ObjectMeta { return i.ingress.ObjectMeta }
-func (i *ingressAdaptorV1Beta1) name() string                     { return i.ingress.Name }
-func (i *ingressAdaptorV1Beta1) namespace() string                { return i.ingress.Namespace }
-func (i *ingressAdaptorV1Beta1) labels() map[string]string        { return i.ingress.Labels }
-func (i *ingressAdaptorV1Beta1) annotations() map[string]string   { return i.ingress.Annotations }
-func (i *ingressAdaptorV1Beta1) ingressClassName() *string        { return i.ingress.Spec.IngressClassName }
-
-func (i *ingressAdaptorV1Beta1) tlsHosts() []string {
-	var hosts []string
-	for _, tls := range i.ingress.Spec.TLS {
-		hosts = append(hosts, tls.Hosts...)
-	}
-	return hosts
-}
-
-func (i *ingressAdaptorV1Beta1) rules() []ingressRuleAdaptor {
-	var rules []ingressRuleAdaptor
-	for _, rule := range i.ingress.Spec.Rules {
-		rules = append(rules, newIngressRuleAdaptorFromV1Beta1(rule))
-	}
-	return rules
-}
-
-type ingressRuleAdaptorV1Beta1 struct {
-	rule v1beta1.IngressRule
-}
-
-func newIngressRuleAdaptorFromV1Beta1(rule v1beta1.IngressRule) ingressRuleAdaptor {
-	return &ingressRuleAdaptorV1Beta1{rule: rule}
-}
-
-func (i *ingressRuleAdaptorV1Beta1) paths() []string {
-	rv := i.rule.IngressRuleValue
-	if rv.HTTP == nil {
-		return nil
-	}
-	paths := make([]string, len(rv.HTTP.Paths))
-	for n, p := range rv.HTTP.Paths {
-		paths[n] = p.Path
-	}
-	return paths
-}
-
-func (i *ingressRuleAdaptorV1Beta1) host() string { return i.rule.Host }
diff --git a/discovery/kubernetes/kubernetes.go b/discovery/kubernetes/kubernetes.go
index a8b6f85899d..93ac65d8dc2 100644
--- a/discovery/kubernetes/kubernetes.go
+++ b/discovery/kubernetes/kubernetes.go
@@ -25,8 +25,6 @@ import (
 
 	"github.com/prometheus/prometheus/util/strutil"
 
-	disv1beta1 "k8s.io/api/discovery/v1beta1"
-
 	"github.com/go-kit/log"
 	"github.com/go-kit/log/level"
 	"github.com/prometheus/client_golang/prometheus"
@@ -36,12 +34,10 @@ import (
 	apiv1 "k8s.io/api/core/v1"
 	disv1 "k8s.io/api/discovery/v1"
 	networkv1 "k8s.io/api/networking/v1"
-	"k8s.io/api/networking/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/fields"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
-	utilversion "k8s.io/apimachinery/pkg/util/version"
 	"k8s.io/apimachinery/pkg/watch"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
@@ -401,55 +397,22 @@ func (d *Discovery) Run(ctx context.Context, ch chan<- []*targetgroup.Group) {
 
 	switch d.role {
 	case RoleEndpointSlice:
-		// Check "networking.k8s.io/v1" availability with retries.
-		// If "v1" is not available, use "networking.k8s.io/v1beta1" for backward compatibility
-		var v1Supported bool
-		if retryOnError(ctx, 10*time.Second,
-			func() (err error) {
-				v1Supported, err = checkDiscoveryV1Supported(d.client)
-				if err != nil {
-					level.Error(d.logger).Log("msg", "Failed to check networking.k8s.io/v1 availability", "err", err)
-				}
-				return err
-			},
-		) {
-			d.Unlock()
-			return
-		}
-
 		for _, namespace := range namespaces {
 			var informer cache.SharedIndexInformer
-			if v1Supported {
-				e := d.client.DiscoveryV1().EndpointSlices(namespace)
-				elw := &cache.ListWatch{
-					ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
-						options.FieldSelector = d.selectors.endpointslice.field
-						options.LabelSelector = d.selectors.endpointslice.label
-						return e.List(ctx, options)
-					},
-					WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
-						options.FieldSelector = d.selectors.endpointslice.field
-						options.LabelSelector = d.selectors.endpointslice.label
-						return e.Watch(ctx, options)
-					},
-				}
-				informer = d.newEndpointSlicesByNodeInformer(elw, &disv1.EndpointSlice{})
-			} else {
-				e := d.client.DiscoveryV1beta1().EndpointSlices(namespace)
-				elw := &cache.ListWatch{
-					ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
-						options.FieldSelector = d.selectors.endpointslice.field
-						options.LabelSelector = d.selectors.endpointslice.label
-						return e.List(ctx, options)
-					},
-					WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
-						options.FieldSelector = d.selectors.endpointslice.field
-						options.LabelSelector = d.selectors.endpointslice.label
-						return e.Watch(ctx, options)
-					},
-				}
-				informer = d.newEndpointSlicesByNodeInformer(elw, &disv1beta1.EndpointSlice{})
+			e := d.client.DiscoveryV1().EndpointSlices(namespace)
+			elw := &cache.ListWatch{
+				ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
+					options.FieldSelector = d.selectors.endpointslice.field
+					options.LabelSelector = d.selectors.endpointslice.label
+					return e.List(ctx, options)
+				},
+				WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
+					options.FieldSelector = d.selectors.endpointslice.field
+					options.LabelSelector = d.selectors.endpointslice.label
+					return e.Watch(ctx, options)
+				},
 			}
+			informer = d.newEndpointSlicesByNodeInformer(elw, &disv1.EndpointSlice{})
 
 			s := d.client.CoreV1().Services(namespace)
 			slw := &cache.ListWatch{
@@ -609,55 +572,22 @@ func (d *Discovery) Run(ctx context.Context, ch chan<- []*targetgroup.Group) {
 			go svc.informer.Run(ctx.Done())
 		}
 	case RoleIngress:
-		// Check "networking.k8s.io/v1" availability with retries.
-		// If "v1" is not available, use "networking.k8s.io/v1beta1" for backward compatibility
-		var v1Supported bool
-		if retryOnError(ctx, 10*time.Second,
-			func() (err error) {
-				v1Supported, err = checkNetworkingV1Supported(d.client)
-				if err != nil {
-					level.Error(d.logger).Log("msg", "Failed to check networking.k8s.io/v1 availability", "err", err)
-				}
-				return err
-			},
-		) {
-			d.Unlock()
-			return
-		}
-
 		for _, namespace := range namespaces {
 			var informer cache.SharedInformer
-			if v1Supported {
-				i := d.client.NetworkingV1().Ingresses(namespace)
-				ilw := &cache.ListWatch{
-					ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
-						options.FieldSelector = d.selectors.ingress.field
-						options.LabelSelector = d.selectors.ingress.label
-						return i.List(ctx, options)
-					},
-					WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
-						options.FieldSelector = d.selectors.ingress.field
-						options.LabelSelector = d.selectors.ingress.label
-						return i.Watch(ctx, options)
-					},
-				}
-				informer = d.mustNewSharedInformer(ilw, &networkv1.Ingress{}, resyncDisabled)
-			} else {
-				i := d.client.NetworkingV1beta1().Ingresses(namespace)
-				ilw := &cache.ListWatch{
-					ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
-						options.FieldSelector = d.selectors.ingress.field
-						options.LabelSelector = d.selectors.ingress.label
-						return i.List(ctx, options)
-					},
-					WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
-						options.FieldSelector = d.selectors.ingress.field
-						options.LabelSelector = d.selectors.ingress.label
-						return i.Watch(ctx, options)
-					},
-				}
-				informer = d.mustNewSharedInformer(ilw, &v1beta1.Ingress{}, resyncDisabled)
+			i := d.client.NetworkingV1().Ingresses(namespace)
+			ilw := &cache.ListWatch{
+				ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
+					options.FieldSelector = d.selectors.ingress.field
+					options.LabelSelector = d.selectors.ingress.label
+					return i.List(ctx, options)
+				},
+				WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
+					options.FieldSelector = d.selectors.ingress.field
+					options.LabelSelector = d.selectors.ingress.label
+					return i.Watch(ctx, options)
+				},
 			}
+			informer = d.mustNewSharedInformer(ilw, &networkv1.Ingress{}, resyncDisabled)
 			ingress := NewIngress(
 				log.With(d.logger, "role", "ingress"),
 				informer,
@@ -720,20 +650,6 @@ func retryOnError(ctx context.Context, interval time.Duration, f func() error) (
 	}
 }
 
-func checkNetworkingV1Supported(client kubernetes.Interface) (bool, error) {
-	k8sVer, err := client.Discovery().ServerVersion()
-	if err != nil {
-		return false, err
-	}
-	semVer, err := utilversion.ParseSemantic(k8sVer.String())
-	if err != nil {
-		return false, err
-	}
-	// networking.k8s.io/v1 is available since Kubernetes v1.19
-	// https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.19.md
-	return semVer.Major() >= 1 && semVer.Minor() >= 19, nil
-}
-
 func (d *Discovery) newNodeInformer(ctx context.Context) cache.SharedInformer {
 	nlw := &cache.ListWatch{
 		ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
@@ -834,19 +750,6 @@ func (d *Discovery) newEndpointSlicesByNodeInformer(plw *cache.ListWatch, object
 					}
 				}
 			}
-		case *disv1beta1.EndpointSlice:
-			for _, target := range e.Endpoints {
-				if target.TargetRef != nil {
-					switch target.TargetRef.Kind {
-					case "Pod":
-						if target.NodeName != nil {
-							nodes = append(nodes, *target.NodeName)
-						}
-					case "Node":
-						nodes = append(nodes, target.TargetRef.Name)
-					}
-				}
-			}
 		default:
 			return nil, fmt.Errorf("object is not an endpointslice")
 		}
@@ -882,21 +785,6 @@ func (d *Discovery) mustNewSharedIndexInformer(lw cache.ListerWatcher, exampleOb
 	return informer
 }
 
-func checkDiscoveryV1Supported(client kubernetes.Interface) (bool, error) {
-	k8sVer, err := client.Discovery().ServerVersion()
-	if err != nil {
-		return false, err
-	}
-	semVer, err := utilversion.ParseSemantic(k8sVer.String())
-	if err != nil {
-		return false, err
-	}
-	// The discovery.k8s.io/v1beta1 API version of EndpointSlice will no longer be served in v1.25.
-	// discovery.k8s.io/v1 is available since Kubernetes v1.21
-	// https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-25
-	return semVer.Major() >= 1 && semVer.Minor() >= 21, nil
-}
-
 func addObjectMetaLabels(labelSet model.LabelSet, objectMeta metav1.ObjectMeta, role Role) {
 	labelSet[model.LabelName(metaLabelPrefix+string(role)+"_name")] = lv(objectMeta.Name)
 
diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md
index 5df7dae3c02..24d2b50ee92 100644
--- a/docs/configuration/configuration.md
+++ b/docs/configuration/configuration.md
@@ -2125,6 +2125,8 @@ The `endpointslice` role discovers targets from existing endpointslices. For eac
 address referenced in the endpointslice object one target is discovered. If the endpoint is backed by a pod, all
 additional container ports of the pod, not bound to an endpoint port, are discovered as targets as well.
 
+The role requires the `discovery.k8s.io/v1` API version (available since Kubernetes v1.21).
+
 Available meta labels:
 
 * `__meta_kubernetes_namespace`: The namespace of the endpoints object.
@@ -2145,7 +2147,7 @@ Available meta labels:
   * `__meta_kubernetes_endpointslice_endpoint_topology_present_kubernetes_io_hostname`: Flag that shows if the referenced object has a kubernetes.io/hostname annotation.
   * `__meta_kubernetes_endpointslice_endpoint_hostname`: Hostname of the referenced endpoint.
   * `__meta_kubernetes_endpointslice_endpoint_node_name`: Name of the Node hosting the referenced endpoint.
-  * `__meta_kubernetes_endpointslice_endpoint_zone`: Zone the referenced endpoint exists in (only available when using the `discovery.k8s.io/v1` API group).
+  * `__meta_kubernetes_endpointslice_endpoint_zone`: Zone the referenced endpoint exists in.
   * `__meta_kubernetes_endpointslice_port`: Port of the referenced endpoint.
   * `__meta_kubernetes_endpointslice_port_name`: Named port of the referenced endpoint.
   * `__meta_kubernetes_endpointslice_port_protocol`: Protocol of the referenced endpoint.
@@ -2158,6 +2160,8 @@ The `ingress` role discovers a target for each path of each ingress.
 This is generally useful for blackbox monitoring of an ingress.
 The address will be set to the host specified in the ingress spec.
 
+The role requires the `networking.k8s.io/v1` API version (available since Kubernetes v1.19).
+
 Available meta labels:
 
 * `__meta_kubernetes_namespace`: The namespace of the ingress object.


Test patch:
diff --git a/discovery/kubernetes/endpointslice_adaptor_test.go b/discovery/kubernetes/endpointslice_adaptor_test.go
index 1ee33371938..de33c64b661 100644
--- a/discovery/kubernetes/endpointslice_adaptor_test.go
+++ b/discovery/kubernetes/endpointslice_adaptor_test.go
@@ -18,7 +18,6 @@ import (
 
 	"github.com/stretchr/testify/require"
 	v1 "k8s.io/api/discovery/v1"
-	"k8s.io/api/discovery/v1beta1"
 )
 
 func Test_EndpointSliceAdaptor_v1(t *testing.T) {
@@ -48,31 +47,3 @@ func Test_EndpointSliceAdaptor_v1(t *testing.T) {
 		require.Equal(t, endpointSlice.Ports[i].AppProtocol, portAdaptor.appProtocol())
 	}
 }
-
-func Test_EndpointSliceAdaptor_v1beta1(t *testing.T) {
-	endpointSlice := makeEndpointSliceV1beta1()
-	adaptor := newEndpointSliceAdaptorFromV1beta1(endpointSlice)
-
-	require.Equal(t, endpointSlice.ObjectMeta.Name, adaptor.name())
-	require.Equal(t, endpointSlice.ObjectMeta.Namespace, adaptor.namespace())
-	require.Equal(t, endpointSlice.AddressType, v1beta1.AddressType(adaptor.addressType()))
-	require.Equal(t, endpointSlice.Labels, adaptor.labels())
-	require.Equal(t, "testendpoints", endpointSlice.Labels[v1beta1.LabelServiceName])
-
-	for i, endpointAdaptor := range adaptor.endpoints() {
-		require.Equal(t, endpointSlice.Endpoints[i].Addresses, endpointAdaptor.addresses())
-		require.Equal(t, endpointSlice.Endpoints[i].Hostname, endpointAdaptor.hostname())
-		require.Equal(t, endpointSlice.Endpoints[i].Conditions.Ready, endpointAdaptor.conditions().ready())
-		require.Equal(t, endpointSlice.Endpoints[i].Conditions.Serving, endpointAdaptor.conditions().serving())
-		require.Equal(t, endpointSlice.Endpoints[i].Conditions.Terminating, endpointAdaptor.conditions().terminating())
-		require.Equal(t, endpointSlice.Endpoints[i].TargetRef, endpointAdaptor.targetRef())
-		require.Equal(t, endpointSlice.Endpoints[i].Topology, endpointAdaptor.topology())
-	}
-
-	for i, portAdaptor := range adaptor.ports() {
-		require.Equal(t, endpointSlice.Ports[i].Name, portAdaptor.name())
-		require.Equal(t, endpointSlice.Ports[i].Port, portAdaptor.port())
-		require.EqualValues(t, endpointSlice.Ports[i].Protocol, portAdaptor.protocol())
-		require.Equal(t, endpointSlice.Ports[i].AppProtocol, portAdaptor.appProtocol())
-	}
-}
diff --git a/discovery/kubernetes/endpointslice_test.go b/discovery/kubernetes/endpointslice_test.go
index 6ef83081be2..c7e99b0a007 100644
--- a/discovery/kubernetes/endpointslice_test.go
+++ b/discovery/kubernetes/endpointslice_test.go
@@ -21,7 +21,6 @@ import (
 	"github.com/stretchr/testify/require"
 	corev1 "k8s.io/api/core/v1"
 	v1 "k8s.io/api/discovery/v1"
-	"k8s.io/api/discovery/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
@@ -114,62 +113,8 @@ func makeEndpointSliceV1() *v1.EndpointSlice {
 	}
 }
 
-func makeEndpointSliceV1beta1() *v1beta1.EndpointSlice {
-	return &v1beta1.EndpointSlice{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      "testendpoints",
-			Namespace: "default",
-			Labels: map[string]string{
-				v1beta1.LabelServiceName: "testendpoints",
-			},
-			Annotations: map[string]string{
-				"test.annotation": "test",
-			},
-		},
-		AddressType: v1beta1.AddressTypeIPv4,
-		Ports: []v1beta1.EndpointPort{
-			{
-				Name:     strptr("testport"),
-				Port:     int32ptr(9000),
-				Protocol: protocolptr(corev1.ProtocolTCP),
-			},
-		},
-		Endpoints: []v1beta1.Endpoint{
-			{
-				Addresses: []string{"1.2.3.4"},
-				Hostname:  strptr("testendpoint1"),
-			}, {
-				Addresses: []string{"2.3.4.5"},
-				Conditions: v1beta1.EndpointConditions{
-					Ready:       boolptr(true),
-					Serving:     boolptr(true),
-					Terminating: boolptr(false),
-				},
-			}, {
-				Addresses: []string{"3.4.5.6"},
-				Conditions: v1beta1.EndpointConditions{
-					Ready:       boolptr(false),
-					Serving:     boolptr(true),
-					Terminating: boolptr(true),
-				},
-			}, {
-				Addresses: []string{"4.5.6.7"},
-				Conditions: v1beta1.EndpointConditions{
-					Ready:       boolptr(true),
-					Serving:     boolptr(true),
-					Terminating: boolptr(false),
-				},
-				TargetRef: &corev1.ObjectReference{
-					Kind: "Node",
-					Name: "barbaz",
-				},
-			},
-		},
-	}
-}
-
 func TestEndpointSliceDiscoveryBeforeRun(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.25.0")
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}})
 
 	k8sDiscoveryTest{
 		discovery: n,
@@ -249,71 +194,6 @@ func TestEndpointSliceDiscoveryBeforeRun(t *testing.T) {
 	}.Run(t)
 }
 
-func TestEndpointSliceDiscoveryBeforeRunV1beta1(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "1.20.0")
-
-	k8sDiscoveryTest{
-		discovery: n,
-		beforeRun: func() {
-			obj := makeEndpointSliceV1beta1()
-			c.DiscoveryV1beta1().EndpointSlices(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
-		},
-		expectedMaxItems: 1,
-		expectedRes: map[string]*targetgroup.Group{
-			"endpointslice/default/testendpoints": {
-				Targets: []model.LabelSet{
-					{
-						"__address__": "1.2.3.4:9000",
-						"__meta_kubernetes_endpointslice_endpoint_hostname": "testendpoint1",
-						"__meta_kubernetes_endpointslice_port":              "9000",
-						"__meta_kubernetes_endpointslice_port_name":         "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":     "TCP",
-					},
-					{
-						"__address__": "2.3.4.5:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "3.4.5.6:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "false",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "true",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "4.5.6.7:9000",
-						"__meta_kubernetes_endpointslice_address_target_kind":             "Node",
-						"__meta_kubernetes_endpointslice_address_target_name":             "barbaz",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-				},
-				Labels: model.LabelSet{
-					"__meta_kubernetes_endpointslice_address_type":                            "IPv4",
-					"__meta_kubernetes_namespace":                                             "default",
-					"__meta_kubernetes_endpointslice_name":                                    "testendpoints",
-					"__meta_kubernetes_endpointslice_label_kubernetes_io_service_name":        "testendpoints",
-					"__meta_kubernetes_endpointslice_labelpresent_kubernetes_io_service_name": "true",
-					"__meta_kubernetes_endpointslice_annotation_test_annotation":              "test",
-					"__meta_kubernetes_endpointslice_annotationpresent_test_annotation":       "true",
-				},
-				Source: "endpointslice/default/testendpoints",
-			},
-		},
-	}.Run(t)
-}
-
 func TestEndpointSliceDiscoveryAdd(t *testing.T) {
 	obj := &corev1.Pod{
 		ObjectMeta: metav1.ObjectMeta{
@@ -353,25 +233,25 @@ func TestEndpointSliceDiscoveryAdd(t *testing.T) {
 			PodIP:  "1.2.3.4",
 		},
 	}
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.20.0", obj)
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, obj)
 
 	k8sDiscoveryTest{
 		discovery: n,
 		afterStart: func() {
-			obj := &v1beta1.EndpointSlice{
+			obj := &v1.EndpointSlice{
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "testendpoints",
 					Namespace: "default",
 				},
-				AddressType: v1beta1.AddressTypeIPv4,
-				Ports: []v1beta1.EndpointPort{
+				AddressType: v1.AddressTypeIPv4,
+				Ports: []v1.EndpointPort{
 					{
 						Name:     strptr("testport"),
 						Port:     int32ptr(9000),
 						Protocol: protocolptr(corev1.ProtocolTCP),
 					},
 				},
-				Endpoints: []v1beta1.Endpoint{
+				Endpoints: []v1.Endpoint{
 					{
 						Addresses: []string{"4.3.2.1"},
 						TargetRef: &corev1.ObjectReference{
@@ -379,13 +259,13 @@ func TestEndpointSliceDiscoveryAdd(t *testing.T) {
 							Name:      "testpod",
 							Namespace: "default",
 						},
-						Conditions: v1beta1.EndpointConditions{
+						Conditions: v1.EndpointConditions{
 							Ready: boolptr(false),
 						},
 					},
 				},
 			}
-			c.DiscoveryV1beta1().EndpointSlices(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
+			c.DiscoveryV1().EndpointSlices(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
 		},
 		expectedMaxItems: 1,
 		expectedRes: map[string]*targetgroup.Group{
@@ -440,118 +320,34 @@ func TestEndpointSliceDiscoveryAdd(t *testing.T) {
 }
 
 func TestEndpointSliceDiscoveryDelete(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.21.0", makeEndpointSliceV1())
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, makeEndpointSliceV1())
 
 	k8sDiscoveryTest{
 		discovery: n,
 		afterStart: func() {
 			obj := makeEndpointSliceV1()
-			c.DiscoveryV1beta1().EndpointSlices(obj.Namespace).Delete(context.Background(), obj.Name, metav1.DeleteOptions{})
+			c.DiscoveryV1().EndpointSlices(obj.Namespace).Delete(context.Background(), obj.Name, metav1.DeleteOptions{})
 		},
 		expectedMaxItems: 2,
 		expectedRes: map[string]*targetgroup.Group{
 			"endpointslice/default/testendpoints": {
 				Source: "endpointslice/default/testendpoints",
-				Targets: []model.LabelSet{
-					{
-						"__address__": "1.2.3.4:9000",
-						"__meta_kubernetes_endpointslice_address_target_kind":                "",
-						"__meta_kubernetes_endpointslice_address_target_name":                "",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":          "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":        "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating":    "false",
-						"__meta_kubernetes_endpointslice_endpoint_hostname":                  "testendpoint1",
-						"__meta_kubernetes_endpointslice_endpoint_node_name":                 "foobar",
-						"__meta_kubernetes_endpointslice_endpoint_topology_present_topology": "true",
-						"__meta_kubernetes_endpointslice_endpoint_topology_topology":         "value",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                      "us-east-1a",
-						"__meta_kubernetes_endpointslice_port":                               "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":                  "http",
-						"__meta_kubernetes_endpointslice_port_name":                          "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                      "TCP",
-					},
-					{
-						"__address__": "2.3.4.5:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1b",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "3.4.5.6:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "false",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "true",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1c",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "4.5.6.7:9000",
-						"__meta_kubernetes_endpointslice_address_target_kind":             "Node",
-						"__meta_kubernetes_endpointslice_address_target_name":             "barbaz",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1a",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-				},
-				Labels: map[model.LabelName]model.LabelValue{
-					"__meta_kubernetes_endpointslice_address_type":                            "IPv4",
-					"__meta_kubernetes_endpointslice_name":                                    "testendpoints",
-					"__meta_kubernetes_endpointslice_label_kubernetes_io_service_name":        "testendpoints",
-					"__meta_kubernetes_endpointslice_labelpresent_kubernetes_io_service_name": "true",
-					"__meta_kubernetes_endpointslice_annotation_test_annotation":              "test",
-					"__meta_kubernetes_endpointslice_annotationpresent_test_annotation":       "true",
-					"__meta_kubernetes_namespace":                                             "default",
-				},
 			},
 		},
 	}.Run(t)
 }
 
 func TestEndpointSliceDiscoveryUpdate(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.21.0", makeEndpointSliceV1())
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, makeEndpointSliceV1())
 
 	k8sDiscoveryTest{
 		discovery: n,
 		afterStart: func() {
-			obj := &v1beta1.EndpointSlice{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:      "testendpoints",
-					Namespace: "default",
-				},
-				AddressType: v1beta1.AddressTypeIPv4,
-				Ports: []v1beta1.EndpointPort{
-					{
-						Name:     strptr("testport"),
-						Port:     int32ptr(9000),
-						Protocol: protocolptr(corev1.ProtocolTCP),
-					},
-				},
-				Endpoints: []v1beta1.Endpoint{
-					{
-						Addresses: []string{"1.2.3.4"},
-						Hostname:  strptr("testendpoint1"),
-					}, {
-						Addresses: []string{"2.3.4.5"},
-						Conditions: v1beta1.EndpointConditions{
-							Ready: boolptr(true),
-						},
-					},
-				},
-			}
-			c.DiscoveryV1beta1().EndpointSlices(obj.Namespace).Update(context.Background(), obj, metav1.UpdateOptions{})
+			obj := makeEndpointSliceV1()
+			obj.ObjectMeta.Labels = nil
+			obj.ObjectMeta.Annotations = nil
+			obj.Endpoints = obj.Endpoints[0:2]
+			c.DiscoveryV1().EndpointSlices(obj.Namespace).Update(context.Background(), obj, metav1.UpdateOptions{})
 		},
 		expectedMaxItems: 2,
 		expectedRes: map[string]*targetgroup.Group{
@@ -586,39 +382,11 @@ func TestEndpointSliceDiscoveryUpdate(t *testing.T) {
 						"__meta_kubernetes_endpointslice_port_name":                       "testport",
 						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
 					},
-					{
-						"__address__": "3.4.5.6:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "false",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "true",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1c",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "4.5.6.7:9000",
-						"__meta_kubernetes_endpointslice_address_target_kind":             "Node",
-						"__meta_kubernetes_endpointslice_address_target_name":             "barbaz",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1a",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
 				},
 				Labels: model.LabelSet{
-					"__meta_kubernetes_endpointslice_address_type":                            "IPv4",
-					"__meta_kubernetes_endpointslice_name":                                    "testendpoints",
-					"__meta_kubernetes_endpointslice_label_kubernetes_io_service_name":        "testendpoints",
-					"__meta_kubernetes_endpointslice_labelpresent_kubernetes_io_service_name": "true",
-					"__meta_kubernetes_endpointslice_annotation_test_annotation":              "test",
-					"__meta_kubernetes_endpointslice_annotationpresent_test_annotation":       "true",
-					"__meta_kubernetes_namespace":                                             "default",
+					"__meta_kubernetes_endpointslice_address_type": "IPv4",
+					"__meta_kubernetes_endpointslice_name":         "testendpoints",
+					"__meta_kubernetes_namespace":                  "default",
 				},
 			},
 		},
@@ -626,85 +394,18 @@ func TestEndpointSliceDiscoveryUpdate(t *testing.T) {
 }
 
 func TestEndpointSliceDiscoveryEmptyEndpoints(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.21.0", makeEndpointSliceV1())
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, makeEndpointSliceV1())
 
 	k8sDiscoveryTest{
 		discovery: n,
 		afterStart: func() {
-			obj := &v1beta1.EndpointSlice{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:      "testendpoints",
-					Namespace: "default",
-				},
-				AddressType: v1beta1.AddressTypeIPv4,
-				Ports: []v1beta1.EndpointPort{
-					{
-						Name:     strptr("testport"),
-						Port:     int32ptr(9000),
-						Protocol: protocolptr(corev1.ProtocolTCP),
-					},
-				},
-				Endpoints: []v1beta1.Endpoint{},
-			}
-			c.DiscoveryV1beta1().EndpointSlices(obj.Namespace).Update(context.Background(), obj, metav1.UpdateOptions{})
+			obj := makeEndpointSliceV1()
+			obj.Endpoints = []v1.Endpoint{}
+			c.DiscoveryV1().EndpointSlices(obj.Namespace).Update(context.Background(), obj, metav1.UpdateOptions{})
 		},
 		expectedMaxItems: 2,
 		expectedRes: map[string]*targetgroup.Group{
 			"endpointslice/default/testendpoints": {
-				Targets: []model.LabelSet{
-					{
-						"__address__": "1.2.3.4:9000",
-						"__meta_kubernetes_endpointslice_address_target_kind":                "",
-						"__meta_kubernetes_endpointslice_address_target_name":                "",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":          "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":        "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating":    "false",
-						"__meta_kubernetes_endpointslice_endpoint_hostname":                  "testendpoint1",
-						"__meta_kubernetes_endpointslice_endpoint_node_name":                 "foobar",
-						"__meta_kubernetes_endpointslice_endpoint_topology_present_topology": "true",
-						"__meta_kubernetes_endpointslice_endpoint_topology_topology":         "value",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                      "us-east-1a",
-						"__meta_kubernetes_endpointslice_port":                               "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":                  "http",
-						"__meta_kubernetes_endpointslice_port_name":                          "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                      "TCP",
-					},
-					{
-						"__address__": "2.3.4.5:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1b",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "3.4.5.6:9000",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "false",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "true",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1c",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-					{
-						"__address__": "4.5.6.7:9000",
-						"__meta_kubernetes_endpointslice_address_target_kind":             "Node",
-						"__meta_kubernetes_endpointslice_address_target_name":             "barbaz",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_ready":       "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_serving":     "true",
-						"__meta_kubernetes_endpointslice_endpoint_conditions_terminating": "false",
-						"__meta_kubernetes_endpointslice_endpoint_zone":                   "us-east-1a",
-						"__meta_kubernetes_endpointslice_port":                            "9000",
-						"__meta_kubernetes_endpointslice_port_app_protocol":               "http",
-						"__meta_kubernetes_endpointslice_port_name":                       "testport",
-						"__meta_kubernetes_endpointslice_port_protocol":                   "TCP",
-					},
-				},
 				Labels: model.LabelSet{
 					"__meta_kubernetes_endpointslice_address_type":                            "IPv4",
 					"__meta_kubernetes_endpointslice_name":                                    "testendpoints",
@@ -721,7 +422,7 @@ func TestEndpointSliceDiscoveryEmptyEndpoints(t *testing.T) {
 }
 
 func TestEndpointSliceDiscoveryWithService(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.21.0", makeEndpointSliceV1())
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, makeEndpointSliceV1())
 
 	k8sDiscoveryTest{
 		discovery: n,
@@ -813,7 +514,7 @@ func TestEndpointSliceDiscoveryWithService(t *testing.T) {
 }
 
 func TestEndpointSliceDiscoveryWithServiceUpdate(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, "v1.21.0", makeEndpointSliceV1())
+	n, c := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{Names: []string{"default"}}, makeEndpointSliceV1())
 
 	k8sDiscoveryTest{
 		discovery: n,
diff --git a/discovery/kubernetes/ingress_test.go b/discovery/kubernetes/ingress_test.go
index 8e6654c2ccb..9bddfb1e14f 100644
--- a/discovery/kubernetes/ingress_test.go
+++ b/discovery/kubernetes/ingress_test.go
@@ -20,7 +20,6 @@ import (
 
 	"github.com/prometheus/common/model"
 	v1 "k8s.io/api/networking/v1"
-	"k8s.io/api/networking/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	"github.com/prometheus/prometheus/discovery/targetgroup"
@@ -89,60 +88,6 @@ func makeIngress(tls TLSMode) *v1.Ingress {
 	return ret
 }
 
-func makeIngressV1beta1(tls TLSMode) *v1beta1.Ingress {
-	ret := &v1beta1.Ingress{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:        "testingress",
-			Namespace:   "default",
-			Labels:      map[string]string{"test/label": "testvalue"},
-			Annotations: map[string]string{"test/annotation": "testannotationvalue"},
-		},
-		Spec: v1beta1.IngressSpec{
-			IngressClassName: classString("testclass"),
-			TLS:              nil,
-			Rules: []v1beta1.IngressRule{
-				{
-					Host: "example.com",
-					IngressRuleValue: v1beta1.IngressRuleValue{
-						HTTP: &v1beta1.HTTPIngressRuleValue{
-							Paths: []v1beta1.HTTPIngressPath{
-								{Path: "/"},
-								{Path: "/foo"},
-							},
-						},
-					},
-				},
-				{
-					// No backend config, ignored
-					Host: "nobackend.example.com",
-					IngressRuleValue: v1beta1.IngressRuleValue{
-						HTTP: &v1beta1.HTTPIngressRuleValue{},
-					},
-				},
-				{
-					Host: "test.example.com",
-					IngressRuleValue: v1beta1.IngressRuleValue{
-						HTTP: &v1beta1.HTTPIngressRuleValue{
-							Paths: []v1beta1.HTTPIngressPath{{}},
-						},
-					},
-				},
-			},
-		},
-	}
-
-	switch tls {
-	case TLSYes:
-		ret.Spec.TLS = []v1beta1.IngressTLS{{Hosts: []string{"example.com", "test.example.com"}}}
-	case TLSMixed:
-		ret.Spec.TLS = []v1beta1.IngressTLS{{Hosts: []string{"example.com"}}}
-	case TLSWildcard:
-		ret.Spec.TLS = []v1beta1.IngressTLS{{Hosts: []string{"*.example.com"}}}
-	}
-
-	return ret
-}
-
 func classString(v string) *string {
 	return &v
 }
@@ -212,20 +157,6 @@ func TestIngressDiscoveryAdd(t *testing.T) {
 	}.Run(t)
 }
 
-func TestIngressDiscoveryAddV1beta1(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleIngress, NamespaceDiscovery{Names: []string{"default"}}, "v1.18.0")
-
-	k8sDiscoveryTest{
-		discovery: n,
-		afterStart: func() {
-			obj := makeIngressV1beta1(TLSNo)
-			c.NetworkingV1beta1().Ingresses("default").Create(context.Background(), obj, metav1.CreateOptions{})
-		},
-		expectedMaxItems: 1,
-		expectedRes:      expectedTargetGroups("default", TLSNo),
-	}.Run(t)
-}
-
 func TestIngressDiscoveryAddTLS(t *testing.T) {
 	n, c := makeDiscovery(RoleIngress, NamespaceDiscovery{Names: []string{"default"}})
 
@@ -240,20 +171,6 @@ func TestIngressDiscoveryAddTLS(t *testing.T) {
 	}.Run(t)
 }
 
-func TestIngressDiscoveryAddTLSV1beta1(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleIngress, NamespaceDiscovery{Names: []string{"default"}}, "v1.18.0")
-
-	k8sDiscoveryTest{
-		discovery: n,
-		afterStart: func() {
-			obj := makeIngressV1beta1(TLSYes)
-			c.NetworkingV1beta1().Ingresses("default").Create(context.Background(), obj, metav1.CreateOptions{})
-		},
-		expectedMaxItems: 1,
-		expectedRes:      expectedTargetGroups("default", TLSYes),
-	}.Run(t)
-}
-
 func TestIngressDiscoveryAddMixed(t *testing.T) {
 	n, c := makeDiscovery(RoleIngress, NamespaceDiscovery{Names: []string{"default"}})
 
@@ -268,20 +185,6 @@ func TestIngressDiscoveryAddMixed(t *testing.T) {
 	}.Run(t)
 }
 
-func TestIngressDiscoveryAddMixedV1beta1(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleIngress, NamespaceDiscovery{Names: []string{"default"}}, "v1.18.0")
-
-	k8sDiscoveryTest{
-		discovery: n,
-		afterStart: func() {
-			obj := makeIngressV1beta1(TLSMixed)
-			c.NetworkingV1beta1().Ingresses("default").Create(context.Background(), obj, metav1.CreateOptions{})
-		},
-		expectedMaxItems: 1,
-		expectedRes:      expectedTargetGroups("default", TLSMixed),
-	}.Run(t)
-}
-
 func TestIngressDiscoveryNamespaces(t *testing.T) {
 	n, c := makeDiscovery(RoleIngress, NamespaceDiscovery{Names: []string{"ns1", "ns2"}})
 
@@ -303,27 +206,6 @@ func TestIngressDiscoveryNamespaces(t *testing.T) {
 	}.Run(t)
 }
 
-func TestIngressDiscoveryNamespacesV1beta1(t *testing.T) {
-	n, c := makeDiscoveryWithVersion(RoleIngress, NamespaceDiscovery{Names: []string{"ns1", "ns2"}}, "v1.18.0")
-
-	expected := expectedTargetGroups("ns1", TLSNo)
-	for k, v := range expectedTargetGroups("ns2", TLSNo) {
-		expected[k] = v
-	}
-	k8sDiscoveryTest{
-		discovery: n,
-		afterStart: func() {
-			for _, ns := range []string{"ns1", "ns2"} {
-				obj := makeIngressV1beta1(TLSNo)
-				obj.Namespace = ns
-				c.NetworkingV1beta1().Ingresses(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
-			}
-		},
-		expectedMaxItems: 2,
-		expectedRes:      expected,
-	}.Run(t)
-}
-
 func TestIngressDiscoveryOwnNamespace(t *testing.T) {
 	n, c := makeDiscovery(RoleIngress, NamespaceDiscovery{IncludeOwnNamespace: true})
 
diff --git a/discovery/kubernetes/kubernetes_test.go b/discovery/kubernetes/kubernetes_test.go
index 552f8a44538..9f84c5efb47 100644
--- a/discovery/kubernetes/kubernetes_test.go
+++ b/discovery/kubernetes/kubernetes_test.go
@@ -46,7 +46,7 @@ func TestMain(m *testing.M) {
 
 // makeDiscovery creates a kubernetes.Discovery instance for testing.
 func makeDiscovery(role Role, nsDiscovery NamespaceDiscovery, objects ...runtime.Object) (*Discovery, kubernetes.Interface) {
-	return makeDiscoveryWithVersion(role, nsDiscovery, "v1.22.0", objects...)
+	return makeDiscoveryWithVersion(role, nsDiscovery, "v1.25.0", objects...)
 }
 
 // makeDiscoveryWithVersion creates a kubernetes.Discovery instance with the specified kubernetes version for testing.
@@ -285,40 +285,6 @@ func TestRetryOnError(t *testing.T) {
 	}
 }
 
-func TestCheckNetworkingV1Supported(t *testing.T) {
-	tests := []struct {
-		version       string
-		wantSupported bool
-		wantErr       bool
-	}{
-		{version: "v1.18.0", wantSupported: false, wantErr: false},
-		{version: "v1.18.1", wantSupported: false, wantErr: false},
-		// networking v1 is supported since Kubernetes v1.19
-		{version: "v1.19.0", wantSupported: true, wantErr: false},
-		{version: "v1.20.0-beta.2", wantSupported: true, wantErr: false},
-		// error patterns
-		{version: "", wantSupported: false, wantErr: true},
-		{version: "<>", wantSupported: false, wantErr: true},
-	}
-
-	for _, tc := range tests {
-		tc := tc
-		t.Run(tc.version, func(t *testing.T) {
-			clientset := fake.NewSimpleClientset()
-			fakeDiscovery, _ := clientset.Discovery().(*fakediscovery.FakeDiscovery)
-			fakeDiscovery.FakedServerVersion = &version.Info{GitVersion: tc.version}
-			supported, err := checkNetworkingV1Supported(clientset)
-
-			if tc.wantErr {
-				require.Error(t, err)
-			} else {
-				require.NoError(t, err)
-			}
-			require.Equal(t, tc.wantSupported, supported)
-		})
-	}
-}
-
 func TestFailuresCountMetric(t *testing.T) {
 	tests := []struct {
 		role             Role