Skip to content

Commit

Permalink
feat: Add support for endpoint topology routing hints (#2090)
Browse files Browse the repository at this point in the history
* Add support for endpoint topology routing hints

Fix goimports

Fix gocritic issue

* Update docs/endpointslice-metrics.md

Co-authored-by: Manuel Rüger <manuel@rueg.eu>

* Update internal/store/endpointslice.go

Co-authored-by: Manuel Rüger <manuel@rueg.eu>

* Update Dockerfile

* Update Dockerfile

* Update endpointslice_test.go

* Redesign metric

* Update endpointslice.go

Remove unneeded label

* Update endpointslice.go

* Update endpointslice-metrics.md

* Fix test

* Remove hostname

* Update docs/endpointslice-metrics.md

---------

Co-authored-by: Manuel Rüger <manuel@rueg.eu>
Co-authored-by: Damien Grisonnet <damien.grisonnet@epita.fr>
  • Loading branch information
3 people authored Aug 31, 2023
1 parent dbd4568 commit f369828
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/endpointslice-metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
| kube_endpointslice_info | Gauge | | `endpointslice`=&lt;endpointslice-name&gt; <br> `namespace`=&lt;endpointslice-namespace&gt; | EXPERIMENTAL |
| kube_endpointslice_ports | Gauge | | `endpointslice`=&lt;endpointslice-name&gt; <br> `namespace`=&lt;endpointslice-namespace&gt; <br> `port_name`=&lt;endpointslice-port-name&gt; <br> `port_protocol`=&lt;endpointslice-port-protocol&gt; <br> `port_number`=&lt;endpointslice-port-number&gt; | EXPERIMENTAL |
| kube_endpointslice_endpoints | Gauge | | `endpointslice`=&lt;endpointslice-name&gt; <br> `namespace`=&lt;endpointslice-namespace&gt; <br> `ready`=&lt;endpointslice-ready&gt; <br> `serving`=&lt;endpointslice-serving&gt; <br> `terminating`=&lt;endpointslice-terminating&gt; <br> `hostname`=&lt;endpointslice-hostname&gt; <br> `targetref_kind`=&lt;endpointslice-targetref-kind&gt; <br> `targetref_name`=&lt;endpointslice-targetref-name&gt; <br> `targetref_namespace`=&lt;endpointslice-targetref-namespace&gt; <br> `nodename`=&lt;endpointslice-nodename&gt; <br> `endpoint_zone`=&lt;endpointslice-zone&gt; | EXPERIMENTAL |
| kube_endpointslice_endpoints_hints | Gauge | Each line is a hint applied to an endpoint-slice | `endpointslice`=&lt;endpointslice-name&gt; <br> `namespace`=&lt;endpointslice-namespace&gt; <br> `address`=&lt;endpointslice-address[0]&gt; <br> `for_zone`=&lt;endpointslice-hint&gt; | EXPERIMENTAL |
| kube_endpointslice_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](./cli-arguments.md) | `endpointslice`=&lt;endpointslice-name&gt; <br> `namespace`=&lt;endpointslice-namespace&gt; <br> `label_ENDPOINTSLICE_LABEL`=&lt;ENDPOINTSLICE_LABEL&gt; | EXPERIMENTAL |
| kube_endpointslice_created | Gauge | | `endpointslice`=&lt;endpointslice-name&gt; <br> `namespace`=&lt;endpointslice-namespace&gt; | EXPERIMENTAL |
42 changes: 41 additions & 1 deletion internal/store/endpointslice.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,44 @@ func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string)
}
}),
),
*generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_endpoints_hints",
"Topology routing hints attached to endpoints",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
m := []*metric.Metric{}
for _, ep := range e.Endpoints {
// Hint is populated when the endpoint is configured to be zone aware and preferentially route requests to its local zone.
// If there is no hint, skip this metric
if ep.Hints != nil && len(ep.Hints.ForZones) > 0 {
var (
labelKeys,
labelValues []string
)

// Per Docs.
// This must contain at least one address but no more than
// 100. These are all assumed to be fungible and clients may choose to only
// use the first element. Refer to: https://issue.k8s.io/106267
labelKeys = append(labelKeys, "address")
labelValues = append(labelValues, ep.Addresses[0])

for _, zone := range ep.Hints.ForZones {
m = append(m, &metric.Metric{
LabelKeys: append(labelKeys, "for_zone"),
LabelValues: append(labelValues, zone.Name),
Value: 1,
})
}
}
}
return &metric.Family{
Metrics: m,
}
}),
),
*generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_endpoints",
"Endpoints attached to the endpointslice.",
Expand Down Expand Up @@ -134,9 +172,11 @@ func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string)
for _, address := range ep.Addresses {
newlabelValues := make([]string, len(labelValues))
copy(newlabelValues, labelValues)
newlabelValues = append(newlabelValues, address)

m = append(m, &metric.Metric{
LabelKeys: labelKeys,
LabelValues: append(newlabelValues, address),
LabelValues: newlabelValues,
Value: 1,
})
}
Expand Down
40 changes: 40 additions & 0 deletions internal/store/endpointslice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ func TestEndpointSliceStore(t *testing.T) {
},
Want: `
# HELP kube_endpointslice_endpoints Endpoints attached to the endpointslice.
# HELP kube_endpointslice_endpoints_hints Topology routing hints attached to endpoints
# TYPE kube_endpointslice_endpoints gauge
# TYPE kube_endpointslice_endpoints_hints gauge
kube_endpointslice_endpoints{address="10.0.0.1",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1
kube_endpointslice_endpoints{address="192.168.1.10",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1
`,
Expand All @@ -122,6 +124,44 @@ func TestEndpointSliceStore(t *testing.T) {
"kube_endpointslice_endpoints",
},
},
{
Obj: &discoveryv1.EndpointSlice{
ObjectMeta: metav1.ObjectMeta{
Name: "test_endpointslice-endpoints",
},
AddressType: "IPv4",
Endpoints: []discoveryv1.Endpoint{
{
NodeName: &nodename,
Conditions: discoveryv1.EndpointConditions{
Ready: &ready,
Terminating: &terminating,
},
Hostname: &hostname,
Zone: &zone,
Addresses: addresses,
Hints: &discoveryv1.EndpointHints{
ForZones: []discoveryv1.ForZone{
{Name: "zone1"},
},
},
},
},
},
Want: `
# HELP kube_endpointslice_endpoints Endpoints attached to the endpointslice.
# HELP kube_endpointslice_endpoints_hints Topology routing hints attached to endpoints
# TYPE kube_endpointslice_endpoints gauge
# TYPE kube_endpointslice_endpoints_hints gauge
kube_endpointslice_endpoints_hints{address="10.0.0.1",endpointslice="test_endpointslice-endpoints",for_zone="zone1"} 1
kube_endpointslice_endpoints{address="10.0.0.1",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1
kube_endpointslice_endpoints{address="192.168.1.10",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1
`,

MetricNames: []string{
"kube_endpointslice_endpoints",
},
},
{
AllowAnnotationsList: []string{
"foo",
Expand Down

0 comments on commit f369828

Please sign in to comment.