报错分析:Value specified in CPUShares is out of range: unknown

发布时间 2023-10-31 16:16:46作者: 半山随笔

启动容器时报错:

Caused by:
    org.freedesktop.DBus.Error.InvalidArgs: Value specified in CPUShares is out of range: unknown

初看log不知从哪里来,既不是docker也不是容器运行时,也不是kernel。想到CPUShares跟cgroup相关,cgroup的driver除了sysfs还有systemd。于是找来systemd的source code,终于找到相关的代码。

log出处见https://github.com/systemd/systemd/blob/d19434fbf81db04d03c8cffa87821f754a86635b/src/core/dbus-cgroup.c#L900

源码分析:

BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);

#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val)        \
        static int bus_cgroup_set_##function(                           \
                        Unit *u,                                        \
                        const char *name,                               \
                        uint64_t *p,                                    \
                        sd_bus_message *message,                        \
                        UnitWriteFlags flags,                           \
                        sd_bus_error *error) {                          \
                                                                        \
                uint64_t v;                                             \
                int r;                                                  \
                                                                        \
                assert(p);                                              \
                                                                        \
                r = sd_bus_message_read(message, "t", &v);              \
                if (r < 0)                                              \
                        return r;                                       \
                                                                        \
                if (!check(v))                                          \
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
                                                 "Value specified in %s is out of range", name); \

BUS_DEFINE_SET_CGROUP_WEIGHT宏会check从message中传来的cpushares的值,check也是一个宏CGROUP_CPU_SHARES_IS_OK。

static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) {
        return
            x == CGROUP_CPU_SHARES_INVALID ||
            (x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX);
}

#define CGROUP_CPU_SHARES_INVALID UINT64_MAX
#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
#define CGROUP_CPU_SHARES_MAX UINT64_C(262144)

也就是cpushares须在[2, 262144]或者为u64(-1)而docker传入的cpushares默认是0,运行时未加必要的检查,将0传给systemd导致error。

此外CPUWeight也是有限制的,为[1, 10000],超出限制也会有类似的错误。