Menu

目录

信号量残留

使用devicemapper作为graphdriver时,强杀可能导致信号量残留。docker在操作dm的过程中会创建信号量,如果在释放信号量前,daemon被强杀,可能导致该信号量无法释放,一次强杀最多泄露一个信号量,泄露概率低。而linux系统有信号量上限限制,当信号量泄露次数达到上线值时将无法创建新的信号量,进而导致docker daemon启动失败。排查方法如下:

  1. 首先查看系统上残留的信号量

    $ ipcs 
    ------ Message Queues -------- 
    key        msqid      owner      perms      used-bytes   messages 
    ------ Shared Memory Segments -------- 
    key        shmid      owner      perms      bytes      nattch     status 
    ------ Semaphore Arrays -------- 
    key        semid      owner      perms      nsems 
    0x0d4d3358 238977024  root       600        1 
    0x0d4d0ec9 270172161  root       600        1 
    0x0d4dc02e 281640962  root       600        1
    
  2. 接着用dmsetup查看devicemapper创建的信号量,该信号量集合是上一步中查看到的系统信号量的子集

    $ dmsetup udevcookies 
    
  3. 最后查看内核信号量设置上限,第四个值就是当前系统的信号量使用上限

    $ cat /proc/sys/kernel/sem 
    250     32000   32      128
    

    如果步骤1中残留的信号量数量与步骤3中看到的信号量上限相等,则是达到上限,此时docker daemon无法正常启动。可以使用下述命令增加信号量使用上限值来让docker恢复启动

    $ echo 250 32000  32  1024 > /proc/sys/kernel/sem
    

    也可以手动清理devicemapper残留的信号量(下面是清理一分钟以前申请的dm相关信号量)

    $ dmsetup udevcomplete_all 1 
    This operation will destroy all semaphores older than 1 minutes with keys that have a prefix 3405 (0xd4d). 
    Do you really want to continue? [y/n]: y 
    0 semaphores with keys prefixed by 3405 (0xd4d) destroyed. 0 skipped.