mirror of
https://github.com/prometheus/prometheus.git
synced 2025-07-03 11:03:25 +00:00
discovery/kubernetes: Add Kubernetes EndpointSlice discovery
Signed-off-by: Frederic Branczyk <fbranczyk@gmail.com> Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
This commit is contained in:
parent
abb4fba3c2
commit
f6c5a75661
4 changed files with 1120 additions and 18 deletions
|
@ -27,6 +27,7 @@ import (
|
|||
config_util "github.com/prometheus/common/config"
|
||||
"github.com/prometheus/common/model"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
disv1beta1 "k8s.io/api/discovery/v1beta1"
|
||||
"k8s.io/api/networking/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
|
@ -67,11 +68,12 @@ type Role string
|
|||
|
||||
// The valid options for Role.
|
||||
const (
|
||||
RoleNode Role = "node"
|
||||
RolePod Role = "pod"
|
||||
RoleService Role = "service"
|
||||
RoleEndpoint Role = "endpoints"
|
||||
RoleIngress Role = "ingress"
|
||||
RoleNode Role = "node"
|
||||
RolePod Role = "pod"
|
||||
RoleService Role = "service"
|
||||
RoleEndpoint Role = "endpoints"
|
||||
RoleEndpointSlice Role = "endpointslice"
|
||||
RoleIngress Role = "ingress"
|
||||
)
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
|
@ -97,11 +99,12 @@ type SDConfig struct {
|
|||
}
|
||||
|
||||
type roleSelector struct {
|
||||
node resourceSelector
|
||||
pod resourceSelector
|
||||
service resourceSelector
|
||||
endpoints resourceSelector
|
||||
ingress resourceSelector
|
||||
node resourceSelector
|
||||
pod resourceSelector
|
||||
service resourceSelector
|
||||
endpoints resourceSelector
|
||||
endpointslice resourceSelector
|
||||
ingress resourceSelector
|
||||
}
|
||||
|
||||
type SelectorConfig struct {
|
||||
|
@ -124,7 +127,7 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||
return err
|
||||
}
|
||||
if c.Role == "" {
|
||||
return errors.Errorf("role missing (one of: pod, service, endpoints, node, ingress)")
|
||||
return errors.Errorf("role missing (one of: pod, service, endpoints, endpointslice, node, ingress)")
|
||||
}
|
||||
err = c.HTTPClientConfig.Validate()
|
||||
if err != nil {
|
||||
|
@ -136,11 +139,12 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||
|
||||
foundSelectorRoles := make(map[Role]struct{})
|
||||
allowedSelectors := map[Role][]string{
|
||||
RolePod: {string(RolePod)},
|
||||
RoleService: {string(RoleService)},
|
||||
RoleEndpoint: {string(RolePod), string(RoleService), string(RoleEndpoint)},
|
||||
RoleNode: {string(RoleNode)},
|
||||
RoleIngress: {string(RoleIngress)},
|
||||
RolePod: {string(RolePod)},
|
||||
RoleService: {string(RoleService)},
|
||||
RoleEndpointSlice: {string(RolePod), string(RoleService), string(RoleEndpointSlice)},
|
||||
RoleEndpoint: {string(RolePod), string(RoleService), string(RoleEndpoint)},
|
||||
RoleNode: {string(RoleNode)},
|
||||
RoleIngress: {string(RoleIngress)},
|
||||
}
|
||||
|
||||
for _, selector := range c.Selectors {
|
||||
|
@ -150,7 +154,7 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||
foundSelectorRoles[selector.Role] = struct{}{}
|
||||
|
||||
if _, ok := allowedSelectors[c.Role]; !ok {
|
||||
return errors.Errorf("invalid role: %q, expecting one of: pod, service, endpoints, node or ingress", c.Role)
|
||||
return errors.Errorf("invalid role: %q, expecting one of: pod, service, endpoints, endpointslice, node or ingress", c.Role)
|
||||
}
|
||||
var allowed bool
|
||||
for _, role := range allowedSelectors[c.Role] {
|
||||
|
@ -193,7 +197,7 @@ func init() {
|
|||
prometheus.MustRegister(eventCount)
|
||||
|
||||
// Initialize metric vectors.
|
||||
for _, role := range []string{"endpoints", "node", "pod", "service", "ingress"} {
|
||||
for _, role := range []string{"endpointslice", "endpoints", "node", "pod", "service", "ingress"} {
|
||||
for _, evt := range []string{"add", "delete", "update"} {
|
||||
eventCount.WithLabelValues(role, evt)
|
||||
}
|
||||
|
@ -282,6 +286,9 @@ func mapSelector(rawSelector []SelectorConfig) roleSelector {
|
|||
rs := roleSelector{}
|
||||
for _, resourceSelectorRaw := range rawSelector {
|
||||
switch resourceSelectorRaw.Role {
|
||||
case RoleEndpointSlice:
|
||||
rs.endpointslice.field = resourceSelectorRaw.Field
|
||||
rs.endpointslice.label = resourceSelectorRaw.Label
|
||||
case RoleEndpoint:
|
||||
rs.endpoints.field = resourceSelectorRaw.Field
|
||||
rs.endpoints.label = resourceSelectorRaw.Label
|
||||
|
@ -310,6 +317,58 @@ func (d *Discovery) Run(ctx context.Context, ch chan<- []*targetgroup.Group) {
|
|||
namespaces := d.getNamespaces()
|
||||
|
||||
switch d.role {
|
||||
case RoleEndpointSlice:
|
||||
for _, namespace := range namespaces {
|
||||
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)
|
||||
},
|
||||
}
|
||||
s := d.client.CoreV1().Services(namespace)
|
||||
slw := &cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
options.FieldSelector = d.selectors.service.field
|
||||
options.LabelSelector = d.selectors.service.label
|
||||
return s.List(ctx, options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
options.FieldSelector = d.selectors.service.field
|
||||
options.LabelSelector = d.selectors.service.label
|
||||
return s.Watch(ctx, options)
|
||||
},
|
||||
}
|
||||
p := d.client.CoreV1().Pods(namespace)
|
||||
plw := &cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
options.FieldSelector = d.selectors.pod.field
|
||||
options.LabelSelector = d.selectors.pod.label
|
||||
return p.List(ctx, options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
options.FieldSelector = d.selectors.pod.field
|
||||
options.LabelSelector = d.selectors.pod.label
|
||||
return p.Watch(ctx, options)
|
||||
},
|
||||
}
|
||||
eps := NewEndpointSlice(
|
||||
log.With(d.logger, "role", "endpointslice"),
|
||||
cache.NewSharedInformer(slw, &apiv1.Service{}, resyncPeriod),
|
||||
cache.NewSharedInformer(elw, &disv1beta1.EndpointSlice{}, resyncPeriod),
|
||||
cache.NewSharedInformer(plw, &apiv1.Pod{}, resyncPeriod),
|
||||
)
|
||||
d.discoverers = append(d.discoverers, eps)
|
||||
go eps.endpointSliceInf.Run(ctx.Done())
|
||||
go eps.serviceInf.Run(ctx.Done())
|
||||
go eps.podInf.Run(ctx.Done())
|
||||
}
|
||||
case RoleEndpoint:
|
||||
for _, namespace := range namespaces {
|
||||
e := d.client.CoreV1().Endpoints(namespace)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue