Skip to content

Commit 8c694f1

Browse files
authored
Improve container and imagefs stats (#233)
Signed-off-by: Xinfeng Liu <[email protected]>
1 parent cfbffa7 commit 8c694f1

22 files changed

+632
-349
lines changed

core/container_remove.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ package core
1919
import (
2020
"context"
2121
"fmt"
22+
"time"
23+
2224
"github.com/Mirantis/cri-dockerd/libdocker"
2325
"github.com/docker/docker/api/types"
2426
v1 "k8s.io/cri-api/pkg/apis/runtime/v1"
25-
"time"
2627
)
2728

2829
// RemoveContainer removes the container.

core/docker_service.go

+38-76
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"github.com/Mirantis/cri-dockerd/network/kubenet"
3939
"github.com/Mirantis/cri-dockerd/store"
4040
"github.com/Mirantis/cri-dockerd/streaming"
41+
"github.com/Mirantis/cri-dockerd/utils"
4142
"github.com/blang/semver"
4243
dockertypes "github.com/docker/docker/api/types"
4344
"github.com/sirupsen/logrus"
@@ -66,11 +67,9 @@ const (
6667
containerLogPathLabelKey = "io.kubernetes.container.logpath"
6768
sandboxIDLabelKey = "io.kubernetes.sandbox.id"
6869

69-
// The expiration time of version cache.
70-
versionCacheTTL = 60 * time.Second
71-
// The expiration time of 'docker info' cache.
72-
infoCacheTTL = 60 * time.Second
73-
maxMsgSize = 1024 * 1024 * 16
70+
systemInfoCacheMinTTL = time.Minute
71+
72+
maxMsgSize = 1024 * 1024 * 16
7473

7574
defaultCgroupDriver = "cgroupfs"
7675
)
@@ -156,6 +155,7 @@ func NewDockerService(
156155
checkpointManager: checkpointManager,
157156
networkReady: make(map[string]bool),
158157
containerCleanupInfos: make(map[string]*containerCleanupInfo),
158+
containerStatsCache: newContainerStatsCache(),
159159
}
160160

161161
// check docker version compatibility.
@@ -216,23 +216,18 @@ func NewDockerService(
216216
plug.Name(),
217217
)
218218

219-
ds.infoCache = store.NewObjectCache(
220-
func() (interface{}, error) {
221-
return ds.client.Info()
222-
},
223-
infoCacheTTL,
224-
)
219+
dockerInfo, err := ds.getDockerInfo()
220+
if err != nil {
221+
return nil, fmt.Errorf("Failed to execute Info() call to the Docker client")
222+
}
223+
logrus.Debugf("Docker Info: %+v", dockerInfo)
224+
ds.dockerRootDir = dockerInfo.DockerRootDir
225225

226226
// skipping cgroup driver checks for Windows
227227
if runtime.GOOS == "linux" {
228228
// NOTE: cgroup driver is only detectable in docker 1.11+
229229
cgroupDriver := defaultCgroupDriver
230-
dockerInfo, err := ds.getDockerInfo()
231-
logrus.Infof("Docker Info: %+v", dockerInfo)
232-
if err != nil {
233-
logrus.Error(err, "Failed to execute Info() call to the Docker client")
234-
logrus.Infof("Falling back to use the default driver %s", cgroupDriver)
235-
} else if len(dockerInfo.CgroupDriver) == 0 {
230+
if len(dockerInfo.CgroupDriver) == 0 {
236231
logrus.Info("No cgroup driver is set in Docker")
237232
logrus.Infof("Falling back to use the default driver %s", cgroupDriver)
238233
} else {
@@ -249,18 +244,11 @@ func NewDockerService(
249244
ds.cgroupDriver = cgroupDriver
250245
}
251246

252-
ds.versionCache = store.NewObjectCache(
253-
func() (interface{}, error) {
254-
v, err := ds.client.Version()
255-
fixAPIVersion(v)
256-
return v, err
257-
},
258-
versionCacheTTL,
259-
)
260-
261247
// Register prometheus metrics.
262248
metrics.Register()
263249

250+
go ds.startStatsCollection()
251+
264252
return ds, nil
265253
}
266254

@@ -280,14 +268,14 @@ type dockerService struct {
280268
// cgroup driver used by Docker runtime.
281269
cgroupDriver string
282270
checkpointManager store.CheckpointManager
283-
// caches the version of the runtime.
284-
// To be compatible with multiple docker versions, we need to perform
285-
// version checking for some operations. Use this cache to avoid querying
286-
// the docker daemon every time we need to do such checks.
287-
versionCache *store.ObjectCache
288271

289-
// caches "docker info"
290-
infoCache *store.ObjectCache
272+
// cache for 'docker version' and 'docker info'
273+
systemInfoCache utils.Cache
274+
275+
// docker root directory
276+
dockerRootDir string
277+
278+
containerStatsCache *containerStatsCache
291279

292280
// containerCleanupInfos maps container IDs to the `containerCleanupInfo` structs
293281
// needed to clean up after containers have been removed.
@@ -340,17 +328,18 @@ func (ds *dockerService) AlphaVersion(
340328
}
341329

342330
// getDockerVersion gets the version information from docker.
343-
func (ds *dockerService) getDockerVersion() (v *dockertypes.Version, err error) {
344-
if ds.versionCache != nil {
345-
v, err = ds.getDockerVersionFromCache()
346-
} else {
347-
v, err = ds.client.Version()
348-
fixAPIVersion(v)
349-
}
331+
func (ds *dockerService) getDockerVersion() (*dockertypes.Version, error) {
332+
res, err := ds.systemInfoCache.Memoize("docker_version", systemInfoCacheMinTTL, func() (interface{}, error) {
333+
return ds.client.Version()
334+
})
350335
if err != nil {
351-
return nil, fmt.Errorf("failed to get docker version: %v", err)
336+
return nil, fmt.Errorf("failed to get docker version from dockerd: %v", err)
352337
}
353-
return v, nil
338+
cachedValue := res.(*dockertypes.Version)
339+
// make a copy
340+
v := *cachedValue
341+
fixAPIVersion(&v)
342+
return &v, nil
354343
}
355344

356345
// fixAPIVersion remedy Docker API version (e.g., 1.23) which is not semver compatible by
@@ -362,16 +351,15 @@ func fixAPIVersion(v *dockertypes.Version) {
362351
}
363352

364353
// getDockerInfo gets the information of "docker info".
365-
func (ds *dockerService) getDockerInfo() (v *dockertypes.Info, err error) {
366-
if ds.infoCache != nil {
367-
v, err = ds.getDockerInfoFromCache()
368-
} else {
369-
v, err = ds.client.Info()
370-
}
354+
func (ds *dockerService) getDockerInfo() (*dockertypes.Info, error) {
355+
res, err := ds.systemInfoCache.Memoize("docker_info", systemInfoCacheMinTTL, func() (interface{}, error) {
356+
return ds.client.Info()
357+
})
371358
if err != nil {
372-
return nil, fmt.Errorf("failed to get docker info: %v", err)
359+
return nil, fmt.Errorf("failed to get docker info from dockerd: %v", err)
373360
}
374-
return v, nil
361+
info := res.(*dockertypes.Info)
362+
return info, nil
375363
}
376364

377365
// UpdateRuntimeConfig updates the runtime config. Currently only handles podCIDR updates.
@@ -524,29 +512,3 @@ func (ds *dockerService) getDockerAPIVersion() (*semver.Version, error) {
524512
}
525513
return &apiVersion, nil
526514
}
527-
528-
func (ds *dockerService) getDockerVersionFromCache() (*dockertypes.Version, error) {
529-
// We only store on key in the cache.
530-
const dummyKey = "version"
531-
value, err := ds.versionCache.Get(dummyKey)
532-
if err != nil {
533-
return nil, err
534-
}
535-
dv, ok := value.(*dockertypes.Version)
536-
if !ok {
537-
return nil, fmt.Errorf("converted to *dockertype.Version error")
538-
}
539-
return dv, nil
540-
}
541-
542-
func (ds *dockerService) getDockerInfoFromCache() (*dockertypes.Info, error) {
543-
value, err := ds.infoCache.Get("info")
544-
if err != nil {
545-
return nil, err
546-
}
547-
dv, ok := value.(*dockertypes.Info)
548-
if !ok {
549-
return nil, fmt.Errorf("converted to *dockertype.Info error")
550-
}
551-
return dv, nil
552-
}

core/docker_service_test.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,12 @@ func newTestDockerService() (*dockerService, *libdocker.FakeDockerClient, *clock
102102
network: pm,
103103
checkpointManager: ckm,
104104
networkReady: make(map[string]bool),
105+
dockerRootDir: "/docker/root/dir",
105106
}, c, fakeClock
106107
}
107108

108109
func newTestDockerServiceWithVersionCache() (*dockerService, *libdocker.FakeDockerClient, *clock.FakeClock) {
109110
ds, c, fakeClock := newTestDockerService()
110-
ds.versionCache = store.NewObjectCache(
111-
func() (interface{}, error) {
112-
return ds.getDockerVersion()
113-
},
114-
time.Hour*10,
115-
)
116111
return ds, c, fakeClock
117112
}
118113

core/image_linux.go

-81
This file was deleted.

core/imagefs.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package core
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"github.com/Mirantis/cri-dockerd/utils"
8+
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
9+
)
10+
11+
// ImageFsStatsCache caches imagefs stats.
12+
var ImageFsStatsCache utils.Cache
13+
14+
const imageFsStatsMinTTL = 30 * time.Second
15+
16+
// ImageFsInfo returns information of the filesystem that is used to store images.
17+
func (ds *dockerService) ImageFsInfo(
18+
_ context.Context,
19+
_ *runtimeapi.ImageFsInfoRequest,
20+
) (*runtimeapi.ImageFsInfoResponse, error) {
21+
22+
res, err := ImageFsStatsCache.Memoize("imagefs", imageFsStatsMinTTL, func() (interface{}, error) {
23+
return ds.imageFsInfo()
24+
})
25+
if err != nil {
26+
return nil, err
27+
}
28+
stats := res.(*runtimeapi.ImageFsInfoResponse)
29+
return stats, nil
30+
31+
}

0 commit comments

Comments
 (0)