@@ -38,6 +38,7 @@ import (
38
38
"github.com/Mirantis/cri-dockerd/network/kubenet"
39
39
"github.com/Mirantis/cri-dockerd/store"
40
40
"github.com/Mirantis/cri-dockerd/streaming"
41
+ "github.com/Mirantis/cri-dockerd/utils"
41
42
"github.com/blang/semver"
42
43
dockertypes "github.com/docker/docker/api/types"
43
44
"github.com/sirupsen/logrus"
@@ -66,11 +67,9 @@ const (
66
67
containerLogPathLabelKey = "io.kubernetes.container.logpath"
67
68
sandboxIDLabelKey = "io.kubernetes.sandbox.id"
68
69
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
74
73
75
74
defaultCgroupDriver = "cgroupfs"
76
75
)
@@ -156,6 +155,7 @@ func NewDockerService(
156
155
checkpointManager : checkpointManager ,
157
156
networkReady : make (map [string ]bool ),
158
157
containerCleanupInfos : make (map [string ]* containerCleanupInfo ),
158
+ containerStatsCache : newContainerStatsCache (),
159
159
}
160
160
161
161
// check docker version compatibility.
@@ -216,23 +216,18 @@ func NewDockerService(
216
216
plug .Name (),
217
217
)
218
218
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
225
225
226
226
// skipping cgroup driver checks for Windows
227
227
if runtime .GOOS == "linux" {
228
228
// NOTE: cgroup driver is only detectable in docker 1.11+
229
229
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 {
236
231
logrus .Info ("No cgroup driver is set in Docker" )
237
232
logrus .Infof ("Falling back to use the default driver %s" , cgroupDriver )
238
233
} else {
@@ -249,18 +244,11 @@ func NewDockerService(
249
244
ds .cgroupDriver = cgroupDriver
250
245
}
251
246
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
-
261
247
// Register prometheus metrics.
262
248
metrics .Register ()
263
249
250
+ go ds .startStatsCollection ()
251
+
264
252
return ds , nil
265
253
}
266
254
@@ -280,14 +268,14 @@ type dockerService struct {
280
268
// cgroup driver used by Docker runtime.
281
269
cgroupDriver string
282
270
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
288
271
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
291
279
292
280
// containerCleanupInfos maps container IDs to the `containerCleanupInfo` structs
293
281
// needed to clean up after containers have been removed.
@@ -340,17 +328,18 @@ func (ds *dockerService) AlphaVersion(
340
328
}
341
329
342
330
// 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
+ })
350
335
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 )
352
337
}
353
- return v , nil
338
+ cachedValue := res .(* dockertypes.Version )
339
+ // make a copy
340
+ v := * cachedValue
341
+ fixAPIVersion (& v )
342
+ return & v , nil
354
343
}
355
344
356
345
// fixAPIVersion remedy Docker API version (e.g., 1.23) which is not semver compatible by
@@ -362,16 +351,15 @@ func fixAPIVersion(v *dockertypes.Version) {
362
351
}
363
352
364
353
// 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
+ })
371
358
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 )
373
360
}
374
- return v , nil
361
+ info := res .(* dockertypes.Info )
362
+ return info , nil
375
363
}
376
364
377
365
// UpdateRuntimeConfig updates the runtime config. Currently only handles podCIDR updates.
@@ -524,29 +512,3 @@ func (ds *dockerService) getDockerAPIVersion() (*semver.Version, error) {
524
512
}
525
513
return & apiVersion , nil
526
514
}
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
- }
0 commit comments