Skip to content

Commit a0980c8

Browse files
author
Julian van den Berkmortel
committed
Add metric for pod tolerations (Ref: #1744)
1 parent 4692dc6 commit a0980c8

File tree

4 files changed

+102
-1
lines changed

4 files changed

+102
-1
lines changed

docs/pod-metrics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
| kube_pod_status_reason | Gauge | The pod status reasons | |`pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `reason`=&lt;Evicted\|NodeAffinity\|NodeLost\|Shutdown\|UnexpectedAdmissionError&gt; <br> `uid`=&lt;pod-uid&gt; | EXPERIMENTAL | - |
4848
| kube_pod_status_scheduled_time | Gauge | Unix timestamp when pod moved into scheduled status | seconds |`pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | STABLE | - |
4949
| kube_pod_status_unschedulable | Gauge | Describes the unschedulable status for the pod | |`pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | STABLE | - |
50+
| kube_pod_tolerations | Gauge | Information about the pod tolerations | | `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; <br> `key`=&lt;toleration-key&gt; <br> `operator`=&lt;toleration-operator&gt; <br> `value`=&lt;toleration-value&gt; <br> `effect`=&lt;toleration-effect&gt; `toleration_seconds`=&lt;toleration-seconds&gt; | EXPERIMENTAL | - |
5051

5152
## Useful metrics queries
5253

internal/store/pod.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func podMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
8585
createPodStatusScheduledFamilyGenerator(),
8686
createPodStatusScheduledTimeFamilyGenerator(),
8787
createPodStatusUnschedulableFamilyGenerator(),
88+
createPodTolerationsFamilyGenerator(),
8889
createPodNodeSelectorsFamilyGenerator(),
8990
}
9091
}
@@ -1403,6 +1404,62 @@ func createPodStatusUnschedulableFamilyGenerator() generator.FamilyGenerator {
14031404
)
14041405
}
14051406

1407+
func createPodTolerationsFamilyGenerator() generator.FamilyGenerator {
1408+
return *generator.NewFamilyGenerator(
1409+
"kube_pod_tolerations",
1410+
"Information about the pod tolerations",
1411+
metric.Gauge,
1412+
"",
1413+
wrapPodFunc(func(p *v1.Pod) *metric.Family {
1414+
var ms []*metric.Metric
1415+
1416+
for _, t := range p.Spec.Tolerations {
1417+
var labelKeys []string
1418+
var labelValues []string
1419+
1420+
if t.Key != "" {
1421+
labelKeys = append(labelKeys, "key")
1422+
labelValues = append(labelValues, t.Key)
1423+
}
1424+
1425+
if t.Operator != "" {
1426+
labelKeys = append(labelKeys, "operator")
1427+
labelValues = append(labelValues, string(t.Operator))
1428+
}
1429+
1430+
if t.Value != "" {
1431+
labelKeys = append(labelKeys, "value")
1432+
labelValues = append(labelValues, t.Value)
1433+
}
1434+
1435+
if t.Effect != "" {
1436+
labelKeys = append(labelKeys, "effect")
1437+
labelValues = append(labelValues, string(t.Effect))
1438+
}
1439+
1440+
if t.TolerationSeconds != nil {
1441+
labelKeys = append(labelKeys, "toleration_seconds")
1442+
labelValues = append(labelValues, strconv.FormatInt(*t.TolerationSeconds, 10))
1443+
}
1444+
1445+
if len(labelKeys) == 0 {
1446+
continue
1447+
}
1448+
1449+
ms = append(ms, &metric.Metric{
1450+
LabelKeys: labelKeys,
1451+
LabelValues: labelValues,
1452+
Value: 1,
1453+
})
1454+
}
1455+
1456+
return &metric.Family{
1457+
Metrics: ms,
1458+
}
1459+
}),
1460+
)
1461+
}
1462+
14061463
func createPodNodeSelectorsFamilyGenerator() generator.FamilyGenerator {
14071464
return *generator.NewOptInFamilyGenerator(
14081465
"kube_pod_nodeselectors",

internal/store/pod_test.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,47 @@ func TestPodStore(t *testing.T) {
19261926
"kube_pod_annotations",
19271927
},
19281928
},
1929+
{
1930+
Obj: &v1.Pod{
1931+
ObjectMeta: metav1.ObjectMeta{
1932+
Name: "pod1",
1933+
Namespace: "ns1",
1934+
UID: "uid1",
1935+
},
1936+
Spec: v1.PodSpec{
1937+
Tolerations: []v1.Toleration{
1938+
{
1939+
Key: "key1",
1940+
Operator: v1.TolerationOpEqual,
1941+
Value: "value1",
1942+
Effect: v1.TaintEffectNoSchedule,
1943+
},
1944+
{
1945+
Key: "key2",
1946+
Operator: v1.TolerationOpExists,
1947+
},
1948+
{
1949+
Key: "key3",
1950+
Operator: v1.TolerationOpEqual,
1951+
Value: "value3",
1952+
},
1953+
{
1954+
// an empty toleration to ensure that an empty toleration does not result in a metric
1955+
},
1956+
},
1957+
},
1958+
},
1959+
Want: `
1960+
# HELP kube_pod_tolerations Information about the pod tolerations
1961+
# TYPE kube_pod_tolerations gauge
1962+
kube_pod_tolerations{namespace="ns1",pod="pod1",uid="uid1",key="key1",operator="Equal",value="value1",effect="NoSchedule"} 1
1963+
kube_pod_tolerations{namespace="ns1",pod="pod1",uid="uid1",key="key2",operator="Exists"} 1
1964+
kube_pod_tolerations{namespace="ns1",pod="pod1",uid="uid1",key="key3",operator="Equal",value="value3"} 1
1965+
`,
1966+
MetricNames: []string{
1967+
"kube_pod_tolerations",
1968+
},
1969+
},
19291970
}
19301971

19311972
for i, c := range cases {
@@ -2018,7 +2059,7 @@ func BenchmarkPodStore(b *testing.B) {
20182059
},
20192060
}
20202061

2021-
expectedFamilies := 45
2062+
expectedFamilies := 46
20222063
for n := 0; n < b.N; n++ {
20232064
families := f(pod)
20242065
if len(families) != expectedFamilies {

pkg/app/server_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ func TestFullScrapeCycle(t *testing.T) {
234234
# HELP kube_pod_status_scheduled Describes the status of the scheduling process for the pod.
235235
# HELP kube_pod_status_scheduled_time Unix timestamp when pod moved into scheduled status
236236
# HELP kube_pod_status_unschedulable Describes the unschedulable status for the pod.
237+
# HELP kube_pod_tolerations Information about the pod tolerations
237238
# TYPE kube_pod_annotations gauge
238239
# TYPE kube_pod_completion_time gauge
239240
# TYPE kube_pod_container_info gauge
@@ -278,6 +279,7 @@ func TestFullScrapeCycle(t *testing.T) {
278279
# TYPE kube_pod_status_scheduled gauge
279280
# TYPE kube_pod_status_scheduled_time gauge
280281
# TYPE kube_pod_status_unschedulable gauge
282+
# TYPE kube_pod_tolerations gauge
281283
kube_pod_annotations{namespace="default",pod="pod0",uid="abc-0"} 1
282284
kube_pod_container_info{namespace="default",pod="pod0",uid="abc-0",container="pod1_con1",image_spec="k8s.gcr.io/hyperkube2_spec",image="k8s.gcr.io/hyperkube2",image_id="docker://sha256:bbb",container_id="docker://cd456"} 1
283285
kube_pod_container_info{namespace="default",pod="pod0",uid="abc-0",container="pod1_con2",image_spec="k8s.gcr.io/hyperkube3_spec",image="k8s.gcr.io/hyperkube3",image_id="docker://sha256:ccc",container_id="docker://ef789"} 1

0 commit comments

Comments
 (0)