Skip to content

Commit 3921e6c

Browse files
committed
added pull time and size logs, added error handling to image size check (after panic seen locally in kind), added size metrics, added size error count metric
1 parent 5fad043 commit 3921e6c

File tree

2 files changed

+60
-25
lines changed

2 files changed

+60
-25
lines changed

pkg/remoteimage/pull.go

+47-18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package remoteimage
22

33
import (
44
"context"
5+
"fmt"
56
"time"
67

78
"github.com/containerd/containerd/reference/docker"
@@ -14,7 +15,7 @@ import (
1415

1516
type Puller interface {
1617
Pull(context.Context) error
17-
ImageSize(context.Context) int
18+
ImageSize(context.Context) (int, error)
1819
}
1920

2021
func NewPuller(imageSvc cri.ImageServiceClient, image docker.Named,
@@ -34,48 +35,76 @@ type puller struct {
3435

3536
// Returns the compressed size of the image that was pulled in bytes
3637
// see https://github.com/containerd/containerd/issues/9261
37-
func (p puller) ImageSize(ctx context.Context) int {
38+
func (p puller) ImageSize(ctx context.Context) (size int, err error) {
39+
defer func() {
40+
if err != nil {
41+
klog.Errorf(err.Error())
42+
metrics.OperationErrorsCount.WithLabelValues("size-error").Inc()
43+
}
44+
}()
3845
imageSpec := &cri.ImageSpec{Image: p.image.String()}
39-
imageStatusResponse, _ := p.imageSvc.ImageStatus(ctx, &cri.ImageStatusRequest{
46+
if imageStatusResponse, err := p.imageSvc.ImageStatus(ctx, &cri.ImageStatusRequest{
4047
Image: imageSpec,
41-
})
42-
return int(imageStatusResponse.Image.Size_)
48+
}); err != nil {
49+
size = 0
50+
err = fmt.Errorf("remoteimage.ImageSize(): call returned an error: %s", err.Error())
51+
return size, err
52+
} else if imageStatusResponse == nil {
53+
size = 0
54+
err = fmt.Errorf("remoteimage.ImageSize(): imageStatusResponse is nil")
55+
return size, err
56+
} else if imageStatusResponse.Image == nil {
57+
size = 0
58+
err = fmt.Errorf("remoteimage.ImageSize(): imageStatusResponse.Image is nil")
59+
return size, err
60+
} else {
61+
size = imageStatusResponse.Image.Size()
62+
err = nil
63+
return size, err
64+
}
4365
}
4466

4567
func (p puller) Pull(ctx context.Context) (err error) {
4668
startTime := time.Now()
4769
defer func() { // must capture final value of "err"
4870
elapsed := time.Since(startTime).Seconds()
71+
// pull time metrics and logs
72+
klog.Infof("remoteimage.Pull(): pulled %s in %d milliseconds", p.image.String(), int(1000*elapsed))
4973
metrics.ImagePullTimeHist.WithLabelValues(metrics.BoolToString(err != nil)).Observe(elapsed)
5074
metrics.ImagePullTime.WithLabelValues(p.image.String(), metrics.BoolToString(err != nil)).Set(elapsed)
5175
if err != nil {
5276
metrics.OperationErrorsCount.WithLabelValues("pull-error").Inc()
53-
} else {
54-
go func() {
55-
size := p.ImageSize(ctx)
56-
metrics.ImagePullSizeBytes.WithLabelValues(p.image.String()).Set(float64(size))
57-
}()
5877
}
5978
go func() {
60-
//TODO: this is a hack to ensure data is cleared in a reasonable timeframe and does not build up.
61-
// pushgateway may remove the need for this. https://prometheus.io/docs/practices/pushing/
79+
//TODO: this is a hack to ensure data is cleared in a reasonable time frame (after scrape) and does not build up.
6280
time.Sleep(1 * time.Minute)
6381
metrics.ImagePullTime.DeleteLabelValues(p.image.String(), metrics.BoolToString(err != nil))
64-
if err == nil {
65-
metrics.ImagePullSizeBytes.DeleteLabelValues(p.image.String())
66-
}
6782
}()
83+
// pull size metrics and logs
84+
if err == nil { // only size if pull was successful
85+
if size, err2 := p.ImageSize(ctx); err2 != nil {
86+
// log entries and error counts emitted inside ImageSize() method
87+
} else { // success
88+
klog.Infof("remoteimage.Pull(): pulled %s with size of %d bytes", p.image.String(), size)
89+
metrics.ImagePullSizeBytes.WithLabelValues(p.image.String()).Set(float64(size))
90+
go func() {
91+
//TODO: this is a hack to ensure data is cleared in a reasonable time frame (after scrape) and does not build up.
92+
time.Sleep(1 * time.Minute)
93+
metrics.ImagePullSizeBytes.DeleteLabelValues(p.image.String())
94+
}()
95+
}
96+
}
6897
}()
6998
repo := p.image.Name()
7099
imageSpec := &cri.ImageSpec{Image: p.image.String()}
71100
creds, withCredentials := p.keyring.Lookup(repo)
72-
klog.V(2).Infof("remoteimage.Pull(): len(creds)=%d, withCreds=%t", len(creds), withCredentials)
101+
// klog.V(2).Infof("remoteimage.Pull(): len(creds)=%d, withCreds=%t", len(creds), withCredentials)
73102
if !withCredentials {
74103
_, err = p.imageSvc.PullImage(ctx, &cri.PullImageRequest{
75104
Image: imageSpec,
76105
})
77106

78-
klog.V(2).Infof("remoteimage.Pull(no creds): completed with err=%v", err)
107+
klog.V(2).Infof("remoteimage.Pull(no creds): pulling %s completed with err=%v", p.image.String(), err)
79108
return
80109
}
81110

@@ -96,7 +125,7 @@ func (p puller) Pull(ctx context.Context) (err error) {
96125
})
97126

98127
if err == nil {
99-
klog.V(2).Info("remoteimage.Pull(with creds): completed with err==nil")
128+
klog.V(2).Info("remoteimage.Pull(with creds): pulling %s completed with err==nil", p.image.String())
100129
return
101130
}
102131

pkg/remoteimageasync/synchronizer_test.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -227,24 +227,27 @@ type pullerMock struct {
227227
image string
228228
msDurationLow int
229229
msDurationHigh int
230+
size int // negative size indicates error should be returned
230231
}
231232

232233
func getPullerMock(image string, ms_duration int) pullerMock {
233-
return pullerMock{
234-
image: image,
235-
msDurationLow: ms_duration,
236-
msDurationHigh: ms_duration,
237-
}
234+
return getPullerMockRand(image, ms_duration, ms_duration)
238235
}
239236

240237
func getPullerMockRand(image string, ms_low, ms_high int) pullerMock {
241238
return pullerMock{
242239
image: image,
243240
msDurationLow: ms_low,
244241
msDurationHigh: ms_high,
242+
size: 0,
245243
}
246244
}
247245

246+
// negative size indicates error should be returned
247+
func (p *pullerMock) SetSize(size int) {
248+
p.size = size
249+
}
250+
248251
func (p pullerMock) Pull(ctx context.Context) (err error) {
249252
dur := time.Duration(p.msDurationLow) * time.Millisecond
250253
if p.msDurationLow != p.msDurationHigh {
@@ -268,8 +271,11 @@ func (p pullerMock) Pull(ctx context.Context) (err error) {
268271
}
269272
}
270273

271-
func (p pullerMock) ImageSize(ctx context.Context) int {
272-
return 0
274+
func (p pullerMock) ImageSize(ctx context.Context) (int, error) {
275+
if p.size < 0 {
276+
return 0, fmt.Errorf("error occurred when checking image size")
277+
}
278+
return p.size, nil
273279
}
274280

275281
const nonExistentImage = "docker.io/warmmetal/container-image-csi-driver-test:simple-fs-doesnt-exist"

0 commit comments

Comments
 (0)