autodetects cgroupsv2 on systems with systemd (#9249)
Timotej S committed
Jun 25, 2020 at 09:46 UTC
2a764ebe4f649fb08b129566a3b28c86c932aeba
1 file changed
+128
-1
collectors/cgroups.plugin/sys_fs_cgroup.c
+128
-1
@@ -73,6 +73,129 @@ static uint32_t Write_hash = 0;
73
static uint32_t user_hash = 0;
74
static uint32_t system_hash = 0;
75
76
+enum cgroups_type { CGROUPS_AUTODETECT_FAIL, CGROUPS_V1, CGROUPS_V2 };
77
+
78
+enum cgroups_systemd_setting {
79
+ SYSTEMD_CGROUP_ERR,
80
+ SYSTEMD_CGROUP_LEGACY,
81
+ SYSTEMD_CGROUP_HYBRID,
82
+ SYSTEMD_CGROUP_UNIFIED
83
+};
84
+
85
+struct cgroups_systemd_config_setting {
86
+ char *name;
87
+ enum cgroups_systemd_setting setting;
88
+};
89
+
90
+static struct cgroups_systemd_config_setting cgroups_systemd_options[] = {
91
+ { .name = "legacy", .setting = SYSTEMD_CGROUP_LEGACY },
92
+ { .name = "hybrid", .setting = SYSTEMD_CGROUP_HYBRID },
93
+ { .name = "unified", .setting = SYSTEMD_CGROUP_UNIFIED },
94
+ { .name = NULL, .setting = SYSTEMD_CGROUP_ERR },
95
+};
96
+
97
+/* on Fed systemd is not in PATH for some reason */
98
+#define SYSTEMD_CMD_RHEL "/usr/lib/systemd/systemd --version"
99
+#define SYSTEMD_HIERARCHY_STRING "default-hierarchy="
100
+
101
+#define MAXSIZE_PROC_CMDLINE 4096
102
+static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
103
+{
104
+ pid_t command_pid;
105
+ enum cgroups_systemd_setting retval = SYSTEMD_CGROUP_ERR;
106
+ char buf[MAXSIZE_PROC_CMDLINE];
107
+ char *begin, *end;
108
+
109
+ FILE *f = mypopen(exec, &command_pid);
110
+
111
+ if (!f)
112
+ return retval;
113
+
114
+ while (fgets(buf, MAXSIZE_PROC_CMDLINE, f) != NULL) {
115
+ if ((begin = strstr(buf, SYSTEMD_HIERARCHY_STRING))) {
116
+ end = begin = begin + strlen(SYSTEMD_HIERARCHY_STRING);
117
+ if (!*begin)
118
+ break;
119
+ while (isalpha(*end))
120
+ end++;
121
+ *end = 0;
122
+ for (int i = 0; cgroups_systemd_options[i].name; i++) {
123
+ if (!strcmp(begin, cgroups_systemd_options[i].name)) {
124
+ retval = cgroups_systemd_options[i].setting;
125
+ break;
126
+ }
127
+ }
128
+ break;
129
+ }
130
+ }
131
+
132
+ if (mypclose(f, command_pid))
133
+ return SYSTEMD_CGROUP_ERR;
134
+
135
+ return retval;
136
+}
137
+
138
+static enum cgroups_type cgroups_try_detect_version()
139
+{
140
+ pid_t command_pid;
141
+ char buf[MAXSIZE_PROC_CMDLINE];
142
+ enum cgroups_systemd_setting systemd_setting;
143
+ int cgroups2_available = 0;
144
+
145
+ // 1. check if cgroups2 availible on system at all
146
+ FILE *f = mypopen("grep cgroup /proc/filesystems", &command_pid);
147
+ if (!f) {
148
+ error("popen failed");
149
+ return CGROUPS_AUTODETECT_FAIL;
150
+ }
151
+ while (fgets(buf, MAXSIZE_PROC_CMDLINE, f) != NULL) {
152
+ if (strstr(buf, "cgroup2")) {
153
+ cgroups2_available = 1;
154
+ break;
155
+ }
156
+ }
157
+ if(mypclose(f, command_pid))
158
+ return CGROUPS_AUTODETECT_FAIL;
159
+
160
+ if(!cgroups2_available)
161
+ return CGROUPS_V1;
162
+
163
+ // 2. check systemd compiletime setting
164
+ if ((systemd_setting = cgroups_detect_systemd("systemd --version")) == SYSTEMD_CGROUP_ERR)
165
+ systemd_setting = cgroups_detect_systemd(SYSTEMD_CMD_RHEL);
166
+
167
+ if(systemd_setting == SYSTEMD_CGROUP_ERR)
168
+ return CGROUPS_AUTODETECT_FAIL;
169
+
170
+ if(systemd_setting == SYSTEMD_CGROUP_LEGACY || systemd_setting == SYSTEMD_CGROUP_HYBRID) {
171
+ // curently we prefer V1 if HYBRID is set as it seems to be more feature complete
172
+ // in the future we might want to continue here if SYSTEMD_CGROUP_HYBRID
173
+ // and go ahead with V2
174
+ return CGROUPS_V1;
175
+ }
176
+
177
+ // 3. if we are unified as on Fedora (default cgroups2 only mode)
178
+ // check kernel command line flag that can override that setting
179
+ f = fopen("/proc/cmdline", "r");
180
+ if (!f) {
181
+ error("Error reading kernel boot commandline parameters");
182
+ return CGROUPS_AUTODETECT_FAIL;
183
+ }
184
+
185
+ if (!fgets(buf, MAXSIZE_PROC_CMDLINE, f)) {
186
+ error("couldn't read all cmdline params into buffer");
187
+ return CGROUPS_AUTODETECT_FAIL;
188
+ }
189
+
190
+ fclose(f);
191
+
192
+ if (strstr(buf, "systemd.unified_cgroup_hierarchy=0")) {
193
+ info("cgroups v2 (unified cgroups) is available but are disabled on this system.");
194
+ return CGROUPS_V1;
195
+ }
196
+ return CGROUPS_V2;
197
+}
198
+
199
void read_cgroup_plugin_configuration() {
200
system_page_size = sysconf(_SC_PAGESIZE);
201
@@ -89,7 +212,11 @@ void read_cgroup_plugin_configuration() {
212
if(cgroup_check_for_new_every < cgroup_update_every)
213
cgroup_check_for_new_every = cgroup_update_every;
214
92
- cgroup_use_unified_cgroups = config_get_boolean_ondemand("plugin:cgroups", "use unified cgroups", cgroup_use_unified_cgroups);
215
+ cgroup_use_unified_cgroups = config_get_boolean_ondemand("plugin:cgroups", "use unified cgroups", CONFIG_BOOLEAN_AUTO);
216
+ if(cgroup_use_unified_cgroups == CONFIG_BOOLEAN_AUTO)
217
+ cgroup_use_unified_cgroups = (cgroups_try_detect_version() == CGROUPS_V2);
218
+
219
+ info("use unified cgroups %s", cgroup_use_unified_cgroups ? "true" : "false");
220
221
cgroup_containers_chart_priority = (int)config_get_number("plugin:cgroups", "containers priority", cgroup_containers_chart_priority);
222
if(cgroup_containers_chart_priority < 1)