Ready for production

Зайчатки разума

Записная книжка айтишника

Ready for production

2018-11-13 22:42:34 — Evgeniy Shumilov

- Ты видишь контейнер?

- Вижу.

- И я вижу. А его нет!

  Достаточно давно я заметил где-то фразу о том, что "docker is ready for production". С тех пор периодически вспоминаю её, каждый раз, когда сталкиваюсь с какими-либо проблемами разного масштаба, связанными с докером. Не поймите меня неправильно, мне нравится эта технология, но для меня странным остаётся тот набор детских заболеваний, которыми этот продукт страдает во вполне зрелом возрасте. Так же не понимаю этого дикого ажиотажа вокруг именно докера, когда всё что нужно и не нужно, пытаются затолкнуть в контейнер, не взирая на то, насколько это удобно и целесообразно в текущей ситуации. Создаётся впечатление, что во-первых, раньше не было никакой контейнеризации в принципе - ни jails на BSD, ни OpenVZ и LXC на линуксе, а во-вторых - и сейчас нет никаких иных технологий, кроме докера - ни snap/flatpack (да-да, иксовые приложения для десктопа тоже пытаются завернуть в докер), ни virtualenv для пайтона - ничего подобного, ни пакетов, ни средств вроде puppet/ansible. Конечно, у докера есть удобные средства доставки, с этим никто не спорит, но не понятно, почему выстрелил в своё время именно он, что его сделало таким "модным, стильным, молодёжным". Скажем, OpenVZ мне нравился откровенно больше, чем LXC, но и тем и другим я пользовался задолго до того, как появился докер. Что помешало обрасти средствами доставки и прочими плюшечками тому же OpenVZ? Отсутствие нативной поддержки в ядре?


  Но вернёмся к нашим китообразным. Например, ещё недавно было: маппинг файла внутрь контейнера в rw. Изменяем файл снаружи, но чтобы его содержимое изменилось внутри контейнера, нужно контейнер перезагрузить, хотя так быть по идее не должно.

  Периодически при попытке запустить новую задачу через docker run --rm в каком-то окружении, докер выдаёт, что контейнер с именем скажем, test-environment_run_26 уже существует, поэтому создан не будет. Дёргаем ту же команду руками в том же окружении ещё раз - создаётся контейнер с каким-нибудь именем test-environment_run_28 и всё работает как ни в чём не бывало. Проблема прилетает раз в несколько дней. То есть, если я захочу запустить что-то критичное, то я должен по идее дёргать докер в while и каждый раз проверять - взлетел он или не взлетел и по исчерпании N попыток слать большой и жирный алерт.

  Ещё одна замечательная проблема - это контейнер Шрёдингера. Справедливости ради могу заметить, что не встречал уже пару месяцев после недавних апдейтов. То есть, контейнер как инвертированный суслик из ДМБ: docker ps его видит, docker stop его как бы останавливает, docker kill как бы убивает, но контейнер при этом остаётся видим через docker ps. При этом любая попытка дёрнуть что угодно внутри контейнера заканчивается следующим:
OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
Как в том анекдоте про кефир и сдачу:

- Контейнер запущен?
- Запущен!
- Я в него шелл ставил?
- Ставил!
- Запусти шелл!
- Какой шелл???

  Следующий пункт: предположим, мы ставим докер из репозитория операционной системы. У меня это debian 9, но подозреваю, что и во многих других дистрибутивах проблема с высокой долей вероятности есть. Может быть мейнтейнеры пакета считают заполнение всего пространства раздела под завязку логами интересной фичей, но мне вот так не кажется. Предположим, я об этой фиче не знаю и решаю после продолжительных тестов выкатить что-то в продакшен на докере. Предположим (ну, это уже совсем сомнительный сценарий, тем не менее), у меня не настроен алерт на малое количетсво места на разделах. Что мы получаем в итоге? Накопившийся за какое-то время лог по адресу /var/lib/docker/containers/длинныйтолстыйхэш/длинныйтолстыйхеш.json. Почему трудно было добавить в пакет один конфиг для rsyslog для ротейта?

  Или, например, решил я мигрировать пофайлово с одного инстанса на другой вместе с докером и прочими контейнерами. Мало ли, что случилось - подключил два блочных устройства и выборочно переношу файловую систему. Предположим, у меня только один контейнер с жалким альпайном. При этом - сюрприз! - директория /var/lib/docker при копировании показывает, что там более 100Гб, даже если размер раздела, на котором она лежит, скажем, 50Гб. Даёшь хардлинки и магию в массы!

  И вот, сегодня очередное приключение. Упала база данных в одном из тестовых окружений. Ведёт себя странно. Некоторые операции проходят, например, удаление таблиц проходит быстро, а попытка вывести show tables за 10 минут не дала никакого результата, как и show full processlist. Ежедневная заливка дампа из бекапа так же ни к чему не привела - висела сутки, пока не снял. Так как база тестовая и окружение надо было восстановить вот прямо сейчас, я убил инстанс и создал по-новой, накатил дамп, всё заработало конечно, но как-то очень уж медленно и печально. Поставил dstat и обнаружил, что каждую секунду идёт постоянная запись в 13-20мб/с и чтение в 50-80мб/c. Проверил базу на предмет процессов восстановления индексов innodb или чего-то подобного - безрезультатно, да и база накачена свежая. Docker stats не выдаёт никакого криминала. Поставил iotop - в топе сам dockerd. Остановил для эксперимента второе окружение - не помогло. Начал останавливать в основном все контейнеры по очереди. В итоге - все контейнеры докера остановлены, чтение/запись по-прежнему на уровне 70/15мб каждую секунду. В логах докера каждую секунду появляется по паре сообщений:

time="2018-11-13T10:48:48Z" level=info msg="shim reaped" id=00d615e034c4a15030603e0d46fe5484ff15bef968aff6bdfa3611a676acb6c9 module="containerd/tasks"
time="2018-11-13T10:48:48.184552519Z" level=info msg="ignoring event" module=libcontainerd namespace=moby topic=/tasks/delete type="*events.TaskDelete"

  Останавливаю докер, поднимаю обратно - чтение/запись нормализуется. К сожалению, разбираться в источнике проблемы было некогда, нужно было её устранить как можно быстрее.
По субъективным впечатлениям, таких проблем на чистом OpenVZ и LXC не было.

Теги: docker, админское

comments powered by Disqus