@@ -70,6 +70,7 @@ const (
70
70
WorkingPodCountKey = "working_pods"
71
71
OrphanedRuntimePodTotalKey = "orphaned_runtime_pods_total"
72
72
RestartedPodTotalKey = "restarted_pods_total"
73
+ ImagePullDurationKey = "image_pull_duration_seconds"
73
74
74
75
// Metrics keys of remote runtime operations
75
76
RuntimeOperationsKey = "runtime_operations_total"
@@ -126,8 +127,30 @@ const (
126
127
EphemeralContainer = "ephemeral_container"
127
128
)
128
129
130
+ type imageSizeBucket struct {
131
+ lowerBoundInBytes uint64
132
+ label string
133
+ }
134
+
129
135
var (
130
136
podStartupDurationBuckets = []float64 {0.5 , 1 , 2 , 3 , 4 , 5 , 6 , 8 , 10 , 20 , 30 , 45 , 60 , 120 , 180 , 240 , 300 , 360 , 480 , 600 , 900 , 1200 , 1800 , 2700 , 3600 }
137
+ imagePullDurationBuckets = []float64 {1 , 5 , 10 , 20 , 30 , 60 , 120 , 180 , 240 , 300 , 360 , 480 , 600 , 900 , 1200 , 1800 , 2700 , 3600 }
138
+ // imageSizeBuckets has the labels to be associated with image_pull_duration_seconds metric. For example, if the size of
139
+ // an image pulled is between 1GB and 5GB, the label will be "1GB-5GB".
140
+ imageSizeBuckets = []imageSizeBucket {
141
+ {0 , "0-10MB" },
142
+ {10 * 1024 * 1024 , "10MB-100MB" },
143
+ {100 * 1024 * 1024 , "100MB-500MB" },
144
+ {500 * 1024 * 1024 , "500MB-1GB" },
145
+ {1 * 1024 * 1024 * 1024 , "1GB-5GB" },
146
+ {5 * 1024 * 1024 * 1024 , "5GB-10GB" },
147
+ {10 * 1024 * 1024 * 1024 , "10GB-20GB" },
148
+ {20 * 1024 * 1024 * 1024 , "20GB-30GB" },
149
+ {30 * 1024 * 1024 * 1024 , "30GB-40GB" },
150
+ {40 * 1024 * 1024 * 1024 , "40GB-60GB" },
151
+ {60 * 1024 * 1024 * 1024 , "60GB-100GB" },
152
+ {100 * 1024 * 1024 * 1024 , "GT100GB" },
153
+ }
131
154
)
132
155
133
156
var (
@@ -822,6 +845,20 @@ var (
822
845
StabilityLevel : metrics .ALPHA ,
823
846
},
824
847
)
848
+
849
+ // ImagePullDuration is a Histogram that tracks the duration (in seconds) it takes for an image to be pulled,
850
+ // including the time spent in the waiting queue of image puller.
851
+ // The metric is broken down by bucketed image size.
852
+ ImagePullDuration = metrics .NewHistogramVec (
853
+ & metrics.HistogramOpts {
854
+ Subsystem : KubeletSubsystem ,
855
+ Name : ImagePullDurationKey ,
856
+ Help : "Duration in seconds to pull an image." ,
857
+ Buckets : imagePullDurationBuckets ,
858
+ StabilityLevel : metrics .ALPHA ,
859
+ },
860
+ []string {"image_size_in_bytes" },
861
+ )
825
862
)
826
863
827
864
var registerMetrics sync.Once
@@ -835,6 +872,7 @@ func Register(collectors ...metrics.StableCollector) {
835
872
legacyregistry .MustRegister (PodStartDuration )
836
873
legacyregistry .MustRegister (PodStartSLIDuration )
837
874
legacyregistry .MustRegister (PodStartTotalDuration )
875
+ legacyregistry .MustRegister (ImagePullDuration )
838
876
legacyregistry .MustRegister (NodeStartupPreKubeletDuration )
839
877
legacyregistry .MustRegister (NodeStartupPreRegistrationDuration )
840
878
legacyregistry .MustRegister (NodeStartupRegistrationDuration )
@@ -921,3 +959,18 @@ func SinceInSeconds(start time.Time) float64 {
921
959
func SetNodeName (name types.NodeName ) {
922
960
NodeName .WithLabelValues (string (name )).Set (1 )
923
961
}
962
+
963
+ func GetImageSizeBucket (sizeInBytes uint64 ) string {
964
+ if sizeInBytes == 0 {
965
+ return "N/A"
966
+ }
967
+
968
+ for i := len (imageSizeBuckets ) - 1 ; i >= 0 ; i -- {
969
+ if sizeInBytes > imageSizeBuckets [i ].lowerBoundInBytes {
970
+ return imageSizeBuckets [i ].label
971
+ }
972
+ }
973
+
974
+ // return empty string when sizeInBytes is 0 (error getting image size)
975
+ return ""
976
+ }
0 commit comments