关于LXD容器出现OOM错误,以及添加内存条后容器无法启动的解决

发布时间 2023-09-22 17:05:33作者: treasurew_wang

目前实验室的GPU服务器有4张3090显卡,但是只有32GB内存,频繁出现OOM(Out Of Memory)错误,因此博主通过添加大swap文件暂时缓解该问题,并采购内存条以解决该问题,同时解决添加内存条后lxc报错的问题。

问题描述

某次查看内核日志时,发现某容器出现了OOM(Out Of Memory)错误,有进程被强制kill,询问容器使用者,发现确实存在该问题,模型较大,取的batch size较大,程序跑不起来。
报错内容类似下面部分:

[2064598.795126] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=ns,mems_allowed=0,oom_memcg=/lxc/199,task_memcg=/lxc/199/ns/system.slice/clamav-daemon.service,task=clamd,pid=3647031,uid=100107
[2064598.796609] Memory cgroup out of memory: Killed process 3647031 (clamd) total-vm:1342176kB, anon-rss:1099032kB, file-rss:0kB, shmem-rss:0kB
[2064598.916492] oom_reaper: reaped process 3647031 (clamd), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

报错信息摘自:https://forum.proxmox.com/threads/oom-kill-process-inside-lxc-memory-cgroup-out-of-memory.65106/

通过swap文件来缓解该问题

对一台电脑来说,如果内存不够,有个简单的治标不治本的方法,也就是增加虚拟内存,允许内存将部分内容交换至磁盘,从而有种可用内存空间很大的假象。当然这种方法只是权宜之计,毕竟磁盘速度相比内存实在太慢,如果内存需求过高,会频繁产生缺页中断,极大影响性能。

对于lxd容器来说,它默认关闭了交换分区的使用,我们可以开启它来缓解该问题。


# 开启某lxd容器的交换分区
lxc config set <container_name> limits.memory.swap true

# 重启lxd容器
lxc restart <container_name>

# 对应的全局配置
lxc profile set default limits.memory.swap true

然后,我们可以在容器内通过以下指令查看内存使用

free -m

添加物理内存

既然内存不够,解决该问题的最直接的方法就是添加内存条。由于使用的是戴尔T630服务器,需要使用专用的RECC内存,普通的内存过不了自检。

服务器有两个CPU,内存条安装顺序比较特殊,可以参考https://www.dell.com/support/manuals/zh-cn/poweredge-t630/t630_om/%E7%B3%BB%E7%BB%9F%E5%86%85%E5%AD%98?guid=guid-77d112e3-72cf-40bf-bcf6-6a61e3a2520d&lang=zh-cn,简而言之就是每个CPU平均分配,优先填充编号小的,充分利用多通道。

安装完成后,在宿主机执行free -m,可以看到内存容量增加,完结撒花……?并没有=.=

问题描述

当我运行lxc start <container_name>后,系统报错,报错信息如下:

lxc user1 20230918061253.563 WARN     conf - conf.c:lxc_map_ids:3592 - newuidmap binary is missing
lxc user1 20230918061253.563 WARN     conf - conf.c:lxc_map_ids:3598 - newgidmap binary is missing
lxc user1 20230918061253.564 WARN     conf - conf.c:lxc_map_ids:3592 - newuidmap binary is missing
lxc user1 20230918061253.564 WARN     conf - conf.c:lxc_map_ids:3598 - newgidmap binary is missing
lxc user1 20230918061253.565 WARN     cgfsng - cgroups/cgfsng.c:fchowmodat:1252 - No such file or directory - Failed to fchownat(42, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )
lxc user1 20230918061253.803 ERROR    conf - conf.c:run_buffer:321 - Script exited with status 1
lxc user1 20230918061253.803 ERROR    conf - conf.c:lxc_setup:4400 - Failed to run mount hooks
lxc user1 20230918061253.803 ERROR    start - start.c:do_start:1275 - Failed to setup container "user1"
lxc user1 20230918061253.803 ERROR    sync - sync.c:sync_wait:34 - An error occurred in another process (expected sequence number 4)
lxc user1 20230918061253.814 WARN     network - network.c:lxc_delete_network_priv:3617 - Failed to rename interface with index 0 from "eth0" to its initial name "vethd562e700"
lxc user1 20230918061253.814 ERROR    lxccontainer - lxccontainer.c:wait_on_daemonized_start:877 - Received container state "ABORTING" instead of "RUNNING"
lxc user1 20230918061253.814 ERROR    start - start.c:__lxc_start:2074 - Failed to spawn container "user1"
lxc user1 20230918061253.814 WARN     start - start.c:lxc_abort:1039 - No such process - Failed to send SIGKILL via pidfd 43 for process 12872
lxc user1 20230918061258.923 WARN     conf - conf.c:lxc_map_ids:3592 - newuidmap binary is missing
lxc user1 20230918061258.923 WARN     conf - conf.c:lxc_map_ids:3598 - newgidmap binary is missing
lxc 20230918061258.956 ERROR    af_unix - af_unix.c:lxc_abstract_unix_recv_fds_iov:218 - Connection reset by peer - Failed to receive response
lxc 20230918061258.956 ERROR    commands - commands.c:lxc_cmd_rsp_recv_fds:127 - Failed to receive file descriptors for command "get_state"

经过简单测试,对于新建容器、删除容器、配置容器等操作皆可进行,唯独无法运行容器。

注意到其中有一条报错信息和cgroup有关,而且有memory.oom.group的字样,加上刚插上内存条就出现这样的错误,于是猜测是lxc发现内存实际信息与它以为的信息不一致了。

lxc user1 20230918061253.565 WARN     cgfsng - cgroups/cgfsng.c:fchowmodat:1252 - No such file or directory - Failed to fchownat(42, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )

解决方法

首先是重启,然后找办法重启lxc和lxd,希望能通过这些方法使它更新内存信息,但是失败了。

后续将lxc默认的关于memory的配置、容器的关于memory的配置删去,重新启动容器,问题解决,相关指令如下:

# 全局配置
lxc profile unset default limits.memory.swap
lxc profile unset default limits.memory

# 容器配置
lxc config unset <container_name> limits.memory.swap
lxc config unset <container_name> limits.memory

由于unset得太快,并未确定是哪条设置产生的影响,由于新建容器也无法运行,猜测是全局的限制内存指令造成的影响,读者感兴趣可以依次尝试。