fix diskspace plugin in Docker (#18035)
* fix diskspace in Docker * freez mount_point_stat_path
Ilya Mashchenko committed
Jun 29, 2024 at 11:36 UTC
f8350a705cdb9d8b1744cd6071825d7dddd69241
4 files changed
+49
-19
packaging/docker/README.md
+8
@@ -50,6 +50,7 @@ along with their descriptions.
50
| Component | Mounts | Description |
51
|:----------------------:|:--------------------------:|--------------------------------------------------------------------------------------------------------------------------------------------|
52
| netdata | /etc/os-release | Host info detection. |
53
+| diskspace.plugin | / | Host mount points monitoring. |
54
| cgroups.plugin | /sys, /var/run/docker.sock | Docker containers monitoring and name resolution. |
55
| go.d.plugin | /var/run/docker.sock | Docker Engine and containers monitoring. See [docker](https://github.com/netdata/go.d.plugin/tree/master/modules/docker#readme) collector. |
56
| go.d.plugin | /var/log | Web servers logs tailing. See [weblog](https://github.com/netdata/go.d.plugin/tree/master/modules/weblog#readme) collector. |
@@ -80,6 +81,7 @@ docker run -d --name=netdata \
81
-v netdataconfig:/etc/netdata \
82
-v netdatalib:/var/lib/netdata \
83
-v netdatacache:/var/cache/netdata \
84
+ -v /:/host/root:ro,rslave \
85
-v /etc/passwd:/host/etc/passwd:ro \
86
-v /etc/group:/host/etc/group:ro \
87
-v /etc/localtime:/etc/localtime:ro \
@@ -121,6 +123,7 @@ services:
123
- netdataconfig:/etc/netdata
124
- netdatalib:/var/lib/netdata
125
- netdatacache:/var/cache/netdata
126
+ - /:/host/root:ro,rslave
127
- /etc/passwd:/host/etc/passwd:ro
128
- /etc/group:/host/etc/group:ro
129
- /etc/localtime:/etc/localtime:ro
@@ -233,6 +236,7 @@ docker run -d --name=netdata \
236
-v $(pwd)/netdataconfig/netdata:/etc/netdata \
237
-v netdatalib:/var/lib/netdata \
238
-v netdatacache:/var/cache/netdata \
239
+ -v /:/host/root:ro,rslave \
240
-v /etc/passwd:/host/etc/passwd:ro \
241
-v /etc/group:/host/etc/group:ro \
242
-v /etc/localtime:/etc/localtime:ro \
@@ -274,6 +278,7 @@ services:
278
- ./netdataconfig/netdata:/etc/netdata
279
- netdatalib:/var/lib/netdata
280
- netdatacache:/var/cache/netdata
281
+ - /:/host/root:ro,rslave
282
- /etc/passwd:/host/etc/passwd:ro
283
- /etc/group:/host/etc/group:ro
284
- /etc/localtime:/etc/localtime:ro
@@ -349,6 +354,7 @@ services:
354
- netdataconfig:/etc/netdata
355
- netdatalib:/var/lib/netdata
356
- netdatacache:/var/cache/netdata
357
+ - /:/host/root:ro,rslave
358
- /etc/passwd:/host/etc/passwd:ro
359
- /etc/group:/host/etc/group:ro
360
- /etc/localtime:/etc/localtime:ro
@@ -402,6 +408,7 @@ services:
408
- netdataconfig:/etc/netdata
409
- netdatalib:/var/lib/netdata
410
- netdatacache:/var/cache/netdata
411
+ - /:/host/root:ro,rslave
412
- /etc/passwd:/host/etc/passwd:ro
413
- /etc/group:/host/etc/group:ro
414
- /etc/localtime:/etc/localtime:ro
@@ -449,6 +456,7 @@ services:
456
- netdataconfig:/etc/netdata
457
- netdatalib:/var/lib/netdata
458
- netdatacache:/var/cache/netdata
459
+ - /:/host/root:ro,rslave
460
- /etc/passwd:/host/etc/passwd:ro
461
- /etc/group:/host/etc/group:ro
462
- /etc/localtime:/etc/localtime:ro
src/collectors/diskspace.plugin/plugin_diskspace.c
+14
-11
@@ -111,6 +111,7 @@ void mountpoint_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *entr
111
struct basic_mountinfo {
112
char *persistent_id;
113
char *root;
114
+ char *mount_point_stat_path;
115
char *mount_point;
116
char *filesystem;
117
@@ -123,12 +124,13 @@ static netdata_mutex_t slow_mountinfo_mutex;
124
static struct basic_mountinfo *basic_mountinfo_create_and_copy(struct mountinfo* mi)
125
{
126
struct basic_mountinfo *bmi = callocz(1, sizeof(struct basic_mountinfo));
126
-
127
+
128
if (mi) {
129
bmi->persistent_id = strdupz(mi->persistent_id);
129
- bmi->root = strdupz(mi->root);
130
- bmi->mount_point = strdupz(mi->mount_point);
131
- bmi->filesystem = strdupz(mi->filesystem);
130
+ bmi->root = strdupz(mi->root);
131
+ bmi->mount_point_stat_path = strdupz(mi->mount_point_stat_path);
132
+ bmi->mount_point = strdupz(mi->mount_point);
133
+ bmi->filesystem = strdupz(mi->filesystem);
134
}
135
136
return bmi;
@@ -150,6 +152,7 @@ static void free_basic_mountinfo(struct basic_mountinfo *bmi)
152
if (bmi) {
153
freez(bmi->persistent_id);
154
freez(bmi->root);
155
+ freez(bmi->mount_point_stat_path);
156
freez(bmi->mount_point);
157
freez(bmi->filesystem);
158
@@ -359,9 +362,9 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
362
usec_t start_time = now_monotonic_high_precision_usec();
363
struct stat bs;
364
362
- if(stat(mi->mount_point, &bs) == -1) {
365
+ if(stat(mi->mount_point_stat_path, &bs) == -1) {
366
collector_error("DISKSPACE: Cannot stat() mount point '%s' (disk '%s', filesystem '%s', root '%s')."
364
- , mi->mount_point
367
+ , mi->mount_point_stat_path
368
, disk
369
, mi->filesystem?mi->filesystem:""
370
, mi->root?mi->root:""
@@ -372,7 +375,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
375
else {
376
if((bs.st_mode & S_IFMT) != S_IFDIR) {
377
collector_error("DISKSPACE: Mount point '%s' (disk '%s', filesystem '%s', root '%s') is not a directory."
375
- , mi->mount_point
378
+ , mi->mount_point_stat_path
379
, disk
380
, mi->filesystem?mi->filesystem:""
381
, mi->root?mi->root:""
@@ -451,10 +454,10 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
454
usec_t start_time = now_monotonic_high_precision_usec();
455
struct statvfs buff_statvfs;
456
454
- if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
457
+ if (statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0) {
458
if(!m->shown_error) {
459
collector_error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
457
- , mi->mount_point
460
+ , mi->mount_point_stat_path
461
, disk
462
, mi->filesystem?mi->filesystem:""
463
, mi->root?mi->root:""
@@ -489,10 +492,10 @@ static inline void do_slow_disk_space_stats(struct basic_mountinfo *mi, int upda
492
m->updated = true;
493
494
struct statvfs buff_statvfs;
492
- if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
495
+ if (statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0) {
496
if(!m->shown_error) {
497
collector_error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
495
- , mi->mount_point
498
+ , mi->mount_point_stat_path
499
, mi->persistent_id
500
, mi->filesystem?mi->filesystem:""
501
, mi->root?mi->root:""
src/collectors/proc.plugin/proc_self_mountinfo.c
+25
-7
@@ -113,6 +113,7 @@ struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *ro
113
114
static void mountinfo_free(struct mountinfo *mi) {
115
freez(mi->root);
116
+ freez(mi->mount_point_stat_path);
117
freez(mi->mount_point);
118
freez(mi->mount_options);
119
freez(mi->persistent_id);
@@ -212,13 +213,23 @@ static inline int mount_point_is_protected(char *mount_point)
213
// read the whole mountinfo into a linked list
214
struct mountinfo *mountinfo_read(int do_statvfs) {
215
char filename[FILENAME_MAX + 1];
215
- snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
216
- procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
217
- if(unlikely(!ff)) {
216
+
217
+ snprintfz(filename, FILENAME_MAX, "%s/root/proc/1/mountinfo", netdata_configured_host_prefix);
218
+ procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
219
+
220
+ // Inside docker with '-v "/:/host/root:ro'
221
+ bool host_root_prefix = ff != NULL;
222
+
223
+ if (!ff) {
224
+ snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
225
+ ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
226
+ }
227
+ if (!ff) {
228
snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix);
229
ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
220
- if(unlikely(!ff)) return NULL;
230
}
231
+ if (!ff)
232
+ return NULL;
233
234
ff = procfile_readall(ff);
235
if(unlikely(!ff))
@@ -269,9 +280,16 @@ struct mountinfo *mountinfo_read(int do_statvfs) {
280
mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
281
mi->root_hash = simple_hash(mi->root);
282
272
- mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
283
+ mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w));w++;
284
mi->mount_point_hash = simple_hash(mi->mount_point);
285
286
+ if (host_root_prefix) {
287
+ snprintfz(filename, FILENAME_MAX, "%s/root%s", netdata_configured_host_prefix, mi->mount_point);
288
+ mi->mount_point_stat_path = strdupz(filename);
289
+ } else {
290
+ mi->mount_point_stat_path = strdupz(mi->mount_point);
291
+ }
292
+
293
mi->persistent_id = strdupz(mi->mount_point);
294
netdata_fix_chart_id(mi->persistent_id);
295
mi->persistent_id_hash = simple_hash(mi->persistent_id);
@@ -339,7 +357,7 @@ struct mountinfo *mountinfo_read(int do_statvfs) {
357
// mark as BIND the duplicates (i.e. same filesystem + same source)
358
if(do_statvfs) {
359
struct stat buf;
342
- if(unlikely(stat(mi->mount_point, &buf) == -1)) {
360
+ if(unlikely(stat(mi->mount_point_stat_path, &buf) == -1)) {
361
mi->st_dev = 0;
362
mi->flags |= MOUNTINFO_NO_STAT;
363
}
@@ -391,7 +409,7 @@ struct mountinfo *mountinfo_read(int do_statvfs) {
409
// check if it has size
410
if(do_statvfs && !(mi->flags & MOUNTINFO_IS_DUMMY)) {
411
struct statvfs buff_statvfs;
394
- if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) {
412
+ if(unlikely(statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0)) {
413
mi->flags |= MOUNTINFO_NO_STAT;
414
}
415
else if(unlikely(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */)) {
src/collectors/proc.plugin/proc_self_mountinfo.h
+2
-1
@@ -24,7 +24,8 @@ struct mountinfo {
24
char *root; // root: root of the mount within the filesystem.
25
uint32_t root_hash;
26
27
- char *mount_point; // mount point: mount point relative to the process's root.
27
+ char *mount_point_stat_path; // the actual pathname of the mount point (may differ in Docker)
28
+ char *mount_point; // mount point: mount point relative to the process's root.
29
uint32_t mount_point_hash;
30
31
char *mount_options; // mount options: per-mount options.