diff --git a/internal/store/node.go b/internal/store/node.go index d059e20df7..01300ca183 100644 --- a/internal/store/node.go +++ b/internal/store/node.go @@ -56,6 +56,8 @@ func nodeMetricFamilies(allowAnnotationsList, allowLabelsList []string) []genera createNodeStatusCapacityFamilyGenerator(), createNodeStatusConditionFamilyGenerator(), createNodeStateAddressFamilyGenerator(), + createNodeVolumeCountGenerator(), + createNodeVolumeInUseGenerator(), } } @@ -506,6 +508,44 @@ func createNodeStatusConditionFamilyGenerator() generator.FamilyGenerator { ) } +func createNodeVolumeCountGenerator() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_node_volumes_attached_count", + "Number of volumes attached to the node", + metric.Gauge, + basemetrics.STABLE, + "", + wrapNodeFunc(func(n *v1.Node) *metric.Family { + return &metric.Family{ + Metrics: []*metric.Metric{ + { + Value: float64(len(n.Status.VolumesAttached)), + }, + }, + } + }), + ) +} + +func createNodeVolumeInUseGenerator() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_node_volumes_in_use_count", + "Number of volumes in use on the node", + metric.Gauge, + basemetrics.STABLE, + "", + wrapNodeFunc(func(n *v1.Node) *metric.Family { + return &metric.Family{ + Metrics: []*metric.Metric{ + { + Value: float64(len(n.Status.VolumesInUse)), + }, + }, + } + }), + ) +} + func wrapNodeFunc(f func(*v1.Node) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { node := obj.(*v1.Node) diff --git a/internal/store/node_test.go b/internal/store/node_test.go index 6457aef20e..462fc67b11 100644 --- a/internal/store/node_test.go +++ b/internal/store/node_test.go @@ -298,6 +298,43 @@ func TestNodeStore(t *testing.T) { `, MetricNames: []string{"kube_node_status_addresses"}, }, + { + Obj: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "127.0.0.1", + }, + Status: v1.NodeStatus{ + VolumesAttached: []v1.AttachedVolume{ + {Name: "volume1", DevicePath: "/dev/sda1"}, + {Name: "volume2", DevicePath: "/dev/sda2"}, + }, + }, + }, + Want: ` + # HELP kube_node_volumes_attached_count [STABLE] Number of volumes attached to the node + # TYPE kube_node_volumes_attached_count gauge + kube_node_volumes_attached_count{node="127.0.0.1"} 2 + `, + MetricNames: []string{"kube_node_volumes_attached_count"}, + }, + { + Obj: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "127.0.0.1", + }, + Status: v1.NodeStatus{ + VolumesInUse: []v1.UniqueVolumeName{ + "volume1", + }, + }, + }, + Want: ` + # HELP kube_node_volumes_in_use_count [STABLE] Number of volumes in use on the node + # TYPE kube_node_volumes_in_use_count gauge + kube_node_volumes_in_use_count{node="127.0.0.1"} 1 + `, + MetricNames: []string{"kube_node_volumes_in_use_count"}, + }, } for i, c := range cases { c.Func = generator.ComposeMetricGenFuncs(nodeMetricFamilies(nil, nil))