瀏覽代碼

fix detection of k8s volume names mounted with `subPath`

Nikolay Sivko 4 年之前
父節點
當前提交
dfb7f3e544
共有 7 個文件被更改,包括 66 次插入43 次删除
  1. 22 0
      common/volumes.go
  2. 29 0
      common/volumes_test.go
  3. 2 8
      containers/container.go
  4. 3 4
      containers/containerd.go
  5. 3 4
      containers/dockerd.go
  6. 7 7
      containers/metrics.go
  7. 0 20
      containers/volumes.go

+ 22 - 0
common/volumes.go

@@ -0,0 +1,22 @@
+package common
+
+import (
+	"regexp"
+)
+
+var (
+	k8sVolumeDir = regexp.MustCompile(`.+/(volumes/kubernetes.io~([^/]+)|volume-subpaths)/([^/]+)`)
+)
+
+func ParseKubernetesVolumeSource(source string) string {
+	groups := k8sVolumeDir.FindStringSubmatch(source)
+	if len(groups) != 4 {
+		return ""
+	}
+	provisioner, volume := groups[2], groups[3]
+	switch provisioner {
+	case "secret", "configmap", "empty-dir", "projected":
+		return ""
+	}
+	return volume
+}

+ 29 - 0
common/volumes_test.go

@@ -0,0 +1,29 @@
+package common
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestParseKubernetesVolumeSource(t *testing.T) {
+	assert.Equal(t,
+		"pvc-90af9c02-ec70-446a-a16a-3ce17d4f42b4",
+		ParseKubernetesVolumeSource("/var/lib/kubelet/pods/ed56844b-2ad5-4858-9305-abea47bd39fc/volumes/kubernetes.io~csi/pvc-90af9c02-ec70-446a-a16a-3ce17d4f42b4/mount"),
+	)
+	assert.Equal(t,
+		"pvc-0307b722-e448-4d73-9d75-091ebf367264",
+		ParseKubernetesVolumeSource("/var/lib/kubelet/pods/adf669ca-c3f8-49de-9ad4-9dd66721dc0d/volume-subpaths/pvc-0307b722-e448-4d73-9d75-091ebf367264/pg/0"),
+	)
+	assert.Equal(t,
+		"",
+		ParseKubernetesVolumeSource("/var/lib/kubelet/pods/adf669ca-c3f8-49de-9ad4-9dd66721dc0d/volumes/kubernetes.io~projected/kube-api-access-jvvq6"),
+	)
+	assert.Equal(t,
+		"",
+		ParseKubernetesVolumeSource("/var/lib/kubelet/pods/7cac0d4b-0562-4a25-bbd9-601c60048eb9/etc-hosts"))
+
+	assert.Equal(t,
+		"",
+		ParseKubernetesVolumeSource("/var/lib/kubelet/pods/db6e284a-fbab-4629-8f17-9f5fea38bea7/volumes/kubernetes.io~configmap/config-volume"),
+	)
+}

+ 2 - 8
containers/container.go

@@ -29,17 +29,12 @@ type ContainerID string
 type ContainerMetadata struct {
 	name        string
 	labels      map[string]string
-	volumes     map[string]Volume
+	volumes     map[string]string
 	logPath     string
 	logDecoder  logparser.Decoder
 	hostListens map[string][]netaddr.IPPort
 }
 
-type Volume struct {
-	provisioner string
-	volume      string
-}
-
 type Delays struct {
 	cpu  time.Duration
 	disk time.Duration
@@ -194,8 +189,7 @@ func (c *Container) Collect(ch chan<- prometheus.Metric) {
 				continue
 			}
 			for mountPoint, fsStat := range mounts {
-				v := c.metadata.volumes[mountPoint]
-				dls := []string{mountPoint, dev.Name, v.provisioner, v.volume}
+				dls := []string{mountPoint, dev.Name, c.metadata.volumes[mountPoint]}
 				ch <- gauge(metrics.DiskSize, float64(fsStat.CapacityBytes), dls...)
 				ch <- gauge(metrics.DiskUsed, float64(fsStat.UsedBytes), dls...)
 				ch <- gauge(metrics.DiskReserved, float64(fsStat.ReservedBytes), dls...)

+ 3 - 4
containers/containerd.go

@@ -7,6 +7,7 @@ import (
 	"github.com/containerd/containerd"
 	"github.com/containerd/containerd/oci"
 	"github.com/containerd/containerd/pkg/cri/constants"
+	"github.com/coroot/coroot-node-agent/common"
 	"github.com/coroot/coroot-node-agent/proc"
 	"github.com/coroot/logparser"
 	"k8s.io/klog/v2"
@@ -45,7 +46,7 @@ func ContainerdInspect(containerID string) (*ContainerMetadata, error) {
 
 	res := &ContainerMetadata{
 		labels:  c.Labels,
-		volumes: map[string]Volume{},
+		volumes: map[string]string{},
 	}
 
 	var spec oci.Spec
@@ -53,9 +54,7 @@ func ContainerdInspect(containerID string) (*ContainerMetadata, error) {
 		klog.Warningln(err)
 	} else {
 		for _, m := range spec.Mounts {
-			if provisioner, volume := parseVolumeSource(m.Source); provisioner != "" && volume != "" {
-				res.volumes[m.Destination] = Volume{provisioner: provisioner, volume: volume}
-			}
+			res.volumes[m.Destination] = common.ParseKubernetesVolumeSource(m.Source)
 		}
 	}
 

+ 3 - 4
containers/dockerd.go

@@ -3,6 +3,7 @@ package containers
 import (
 	"context"
 	"fmt"
+	"github.com/coroot/coroot-node-agent/common"
 	"github.com/coroot/coroot-node-agent/proc"
 	"github.com/coroot/logparser"
 	"github.com/docker/docker/client"
@@ -44,13 +45,11 @@ func DockerdInspect(containerID string) (*ContainerMetadata, error) {
 	res := &ContainerMetadata{
 		name:        strings.TrimPrefix(c.Name, "/"),
 		labels:      c.Config.Labels,
-		volumes:     map[string]Volume{},
+		volumes:     map[string]string{},
 		hostListens: map[string][]netaddr.IPPort{},
 	}
 	for _, m := range c.Mounts {
-		if provisioner, volume := parseVolumeSource(m.Source); provisioner != "" && volume != "" {
-			res.volumes[m.Destination] = Volume{provisioner: provisioner, volume: volume}
-		}
+		res.volumes[m.Destination] = common.ParseKubernetesVolumeSource(m.Source)
 	}
 	if c.LogPath != "" && c.HostConfig.LogConfig.Type == "json-file" {
 		res.logPath = c.LogPath

+ 7 - 7
containers/metrics.go

@@ -51,13 +51,13 @@ var metrics = struct {
 	OOMKills:    metric("container_oom_kills_total", "Total number of times the container was terminated by the OOM killer"),
 
 	DiskDelay:      metric("container_resources_disk_delay_seconds_total", "Total time duration processes of the container have been waiting fot I/Os to complete"),
-	DiskSize:       metric("container_resources_disk_size_bytes", "Total capacity of the volume", "mount_point", "device", "provisioner", "volume"),
-	DiskUsed:       metric("container_resources_disk_used_bytes", "Used capacity of the volume", "mount_point", "device", "provisioner", "volume"),
-	DiskReserved:   metric("container_resources_disk_reserved_bytes", "Reserved capacity of the volume", "mount_point", "device", "provisioner", "volume"),
-	DiskReadOps:    metric("container_resources_disk_reads_total", "Total number of reads completed successfully by the container", "mount_point", "device", "provisioner", "volume"),
-	DiskReadBytes:  metric("container_resources_disk_read_bytes_total", "Total number of bytes read from the disk by the container", "mount_point", "device", "provisioner", "volume"),
-	DiskWriteOps:   metric("container_resources_disk_writes_total", "Total number of writes completed successfully by the container", "mount_point", "device", "provisioner", "volume"),
-	DiskWriteBytes: metric("container_resources_disk_written_bytes_total", "Total number of bytes written to the disk by the container", "mount_point", "device", "provisioner", "volume"),
+	DiskSize:       metric("container_resources_disk_size_bytes", "Total capacity of the volume", "mount_point", "device", "volume"),
+	DiskUsed:       metric("container_resources_disk_used_bytes", "Used capacity of the volume", "mount_point", "device", "volume"),
+	DiskReserved:   metric("container_resources_disk_reserved_bytes", "Reserved capacity of the volume", "mount_point", "device", "volume"),
+	DiskReadOps:    metric("container_resources_disk_reads_total", "Total number of reads completed successfully by the container", "mount_point", "device", "volume"),
+	DiskReadBytes:  metric("container_resources_disk_read_bytes_total", "Total number of bytes read from the disk by the container", "mount_point", "device", "volume"),
+	DiskWriteOps:   metric("container_resources_disk_writes_total", "Total number of writes completed successfully by the container", "mount_point", "device", "volume"),
+	DiskWriteBytes: metric("container_resources_disk_written_bytes_total", "Total number of bytes written to the disk by the container", "mount_point", "device", "volume"),
 
 	NetListenInfo:         metric("container_net_tcp_listen_info", "Listen address of the container", "listen_addr", "proxy"),
 	NetConnectsSuccessful: metric("container_net_tcp_successful_connects_total", "Total number of successful TCP connects", "destination", "actual_destination"),

+ 0 - 20
containers/volumes.go

@@ -1,20 +0,0 @@
-package containers
-
-import "regexp"
-
-var (
-	k8sVolumeDir = regexp.MustCompile(`.+/volumes/kubernetes.io~([^/]+)/([^/]+)`)
-)
-
-func parseVolumeSource(source string) (string, string) {
-	groups := k8sVolumeDir.FindStringSubmatch(source)
-	if len(groups) != 3 {
-		return "", ""
-	}
-	provisioner, volume := groups[1], groups[2]
-	switch provisioner {
-	case "secret", "configmap", "empty-dir":
-		return "", ""
-	}
-	return provisioner, volume
-}