Проблемы с удалением docker-контейнеров: device or resource busy

Oct 30, 2017 08:37 · 489 words · 3 minute read docker

Столкнулся с проблемой на одном из серверов с установленной ОС Centos 7 — при обновлении docker-контейнеров запускается новый экземпляр контейнера, но старый при этом не удаляется. Давайте разберемся!

В консоли при этом можно увидеть ошибку примерно следующего содержания:

Error response from daemon: Driver overlay failed to remove root filesystem 88189a16be60761a2c04a455206650048e784d750533ce2858bcabe2f528c92e: rename /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21 /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21-removing: device or resource busy

Информация об установленном docker’е:

docker version
Client:
 Version:      17.06.0-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:20:36 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.06.0-ce
 API version:  1.30 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:21:56 2017
 OS/Arch:      linux/amd64
 Experimental: false
docker info
Containers: 9
 Running: 8
 Paused: 0
 Stopped: 1
Images: 9
Server Version: 17.06.0-ce
Storage Driver: overlay
 Backing Filesystem: extfs
 Supports d_type: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: cfb82a876ecc11b5ca0977d1733adbe58599088a
runc version: 2d41c047c83e09a6d61d464906feb2a2f3c52aa4
init version: 949e6fa
Security Options:
 seccomp
  Profile: default
Kernel Version: 3.10.0-514.26.2.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 31.13GiB
Name: example.com
ID: 7ZTI:WFHT:H5N5:PJBW:DE64:DPKN:PQFD:7HFH:2F5Q:DAUG:H5FH:EKK2
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: ealebed
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

Удаление контейнера с ключом -f также не помогает, примерно в половине случаев проблема уходит после перезапуска сервиса docker. Выяснить, какой еще процесс использует каталог не удалось ни через mount, ни через lsof, ни с помощью fuser

Как оказалось, проблема давно известна и связана с контейнером cAdvisor, который часто используется для мониторинга запущенных контейнеров:

It seems Cadvisor, with permission to access other container’s volumes could lock them on the run

Здесь написано, что у каждого pid есть свой mountinfo, который находится в /proc/[pid]/mountinfo и отличается от mountinfo машины-хоста.

Делаем следующим образом:

grep docker /proc/*/mountinfo | grep 2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21

/proc/1495/mountinfo:634 537 0:92 / /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged rw,relatime shared:244 - overlay overlay rw,lowerdir=/var/lib/docker/overlay/5e43c3efd86aba4c2a2d13699b61ae93dcb15e4cdb425ffe5f2de290abb94b26/root,upperdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/upper,workdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/work
/proc/7080/mountinfo:632 586 0:92 / /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged rw,relatime shared:253 - overlay overlay rw,lowerdir=/var/lib/docker/overlay/5e43c3efd86aba4c2a2d13699b61ae93dcb15e4cdb425ffe5f2de290abb94b26/root,upperdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/upper,workdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/work
/proc/16445/mountinfo:632 586 0:92 / /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged rw,relatime shared:253 - overlay overlay rw,lowerdir=/var/lib/docker/overlay/5e43c3efd86aba4c2a2d13699b61ae93dcb15e4cdb425ffe5f2de290abb94b26/root,upperdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/upper,workdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/work
/proc/16446/mountinfo:632 586 0:92 / /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged rw,relatime shared:253 - overlay overlay rw,lowerdir=/var/lib/docker/overlay/5e43c3efd86aba4c2a2d13699b61ae93dcb15e4cdb425ffe5f2de290abb94b26/root,upperdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/upper,workdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/work
/proc/16447/mountinfo:632 586 0:92 / /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged rw,relatime shared:253 - overlay overlay rw,lowerdir=/var/lib/docker/overlay/5e43c3efd86aba4c2a2d13699b61ae93dcb15e4cdb425ffe5f2de290abb94b26/root,upperdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/upper,workdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/work

Видим, что процессы 16447, 16446, 16445, 7080, 1495 все еще ссылаются на данный каталог и не дают нам его удалить. Подключаемся как суперпользователь в пространство имен (namespace) интересующего нас процесса с помощью команды:

nsenter -m -t 16447 /bin/bash

Смотрим список примонтированных каталогов (с помощью grep выбираем только интересующие):

[root@example /]# mount | grep 2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21
overlay on /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay/5e43c3efd86aba4c2a2d13699b61ae93dcb15e4cdb425ffe5f2de290abb94b26/root,upperdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/upper,workdir=/var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/work)

Отмонтируем, проверяем результат и выходим из пространства имен процесса:

[root@example /]# umount /var/lib/docker/overlay/2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21/merged
[root@example /]# mount | grep 2b70ddff2ab1de78ca8c6f04b89c1cef6234bc1c880439b989ef4f0acb3c5b21
[root@example /]# exit

Повторяем данную процедуру для всех процессов, ссылающихся на данный каталог (16447, 16446, 16445, 7080, 1495). После проделанных действий можно удалить старый контейнер с помощью команды:

docker rm <id_контейнера>
tweet Share