пятница, 14 ноября 2014 г.

Боль и страдания при обновлении связанных контейнеров docker

Довольно типовая ситуация в использовании контейнеров docker — linked containers.

Ну например, хотим мы запустить на каком то хосте, скажем wordpress.

Проблем с образами нет, wordpress сам их клепает, красивые, в ногу со временем, скорее всего без уязвимостей, но внутри себя он не содержит СУБД.

Это очень в стиле докера, одному контейнеру - один процесс. Нужно mysql поднять рядом, в другом контейнере.

А затем связать через --link.

Почему? Ну причин несколько:

Во первых айпишники докер контейнеров меняются при перезапуске, и вы наверняка не захотите следить за этим руками, и изобретать велосипед.

Во вторых, это очень удобная абстракция, передал --link mysql:my-host1 и внутри контейнера днс имя mysql разрешается в ip адрес контейнера my-host1. Комбинируй их как хочешь, за всем этим будет следить хост процесс docker.

Вот пример использования, сначала запустим mysql дадим ему имя wmysql:

docker run -d --name=wmysql -v /media/wordpress-mysql:/var/lib/mysql -d korjavin/docker-mysql
Залогинимся туда  с хост машины (мелкий хак с использованием docker inspect для выяснения ипа контейнера)

mysql --host=$(docker inspect --format {{.NetworkSettings.IPAddress}} wmysql)  -u root
Создадим там юзера для wordpress
GRANT ALL PRIVILEGES ON *.* TO 'wordpress'@'%' iDENTIFIED BY '12345' WITH GRANT OPTION;
 А затем привяжем к нему wordpress контейнер

docker run -d -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=12345 --name=wordpress --link wmysql:mysql -p 80:80 wordpress

Всё, работа сделана:  рестартуй контейнеры, хост, что угодно связь между контейнерами останется.

Удобно.

Но есть тут хорошая ложка дёгтя.

Сразу отмечу что в реальной жизни у меня wordpress понадобился только единожды для быстрого наколенного способа создать rss поток и симитировать подкаст из набора mp3 файлов, что б залить его в телефон для удобного прослушивания, интересный опыт, и docker оказался очень кстати, опишу как-нибудь отдельно.

А обычно, дерево зависимостей контейнеров у меня сильно сложнее, воркеры зависят от менеджеров и все вместе зависят от баз, и рядом еще крутятся утилиты.

И вот наступает час ИКС, когда тебе нужно обновить какой-то из контейнеров, на который слинкованы другие.

Без проблем, останавливаешь, обновляешь, запускаешь, и внезапно всё падает. Все связи между ними.

Ну ладно, рестартуешь все зависимые, думаешь они линк восстановят, ан нет. 

Как так? Имя же не изменилось.

А видимо имя не имеет значения. Имя это вам для удобства, внутри, в кишочках оно видимо связано по id контейнера который изменился.

Это только моя догадка, потому как docker inspect отрицает, и показывает связь по именам:

        "Links": [
            "/wmysql:/wordpress/mysql"
        ],
Но факт в том что оно перестает работать.

И ты, чувствую себя обезьянкой, должен остановить все свои зависимые контейнеры, вспомнить правильный способ и последовательность их запуска, нужные передаваемые ключи, и всё рестартовать.

Большое разочарование.

Как с этим бороться глобально?

Ну способов несколько:

Один из них делать толстые контейнеры с несколькими процессами внутри и супервайзером следящим за ними.  Я уверен что так делать не стоит.
Если хочется такое, просто забудьте про докер, и запускайте всё напрямую на хосте.

Второй, написать скрипты перезапуска в правильном порядке и т.д и т.п. Мне руками писать их не хочется, я всё пытаюсь приспособить к этому vagrant с его --provider=docker, но пока получается плохо.
Лезет и лезет всякая мелкая ерунда.
Я всё таки намерен это побороть, и когда закончу, опишу процесс.

Третий вариант, забить на линки. Совсем.
Представить себе что эти докеры крутятся на разных удаленных машинах, и нет у вас возможность связать внутри приватной сетки docker 172.17.
Строить полноценный кластер, с обнаружением (service discovery), распределенной конфигурацией и прочим. Что то вроде etcd или модного consul.
DigitalOcean предлагает строить это на coreos и даже написал серию отличных статей про coreos/fleet/etcd и прочее.
Этим я тоже занимаюсь, для одной из своих задач, но в целом, для 90% моих задач это явный и жуткий оверкилл.

Представьте, что для обычного вордпресса, вам вдруг понадобилось 3 разных хоста, с кучей обвязок, с отдельными service discovery контейнерами, и с кучей ада про systemd и fleet.
Эмм, это что, упрощение? Надежность? Да тут способов прострелить себе ногу больше чем поставить себе wordpress без всяких контейнеров.






Вот такая очередная печалька про модные контейнеры.
Я более чем уверен что в каком-нибудь очередном релизе докера это исправят, ибо развивается он динамично, и каждый релиз что-нибудь такое и решает.
Но пока, даже в очень простых случаях, всё время на что то наступаешь.




Кстати если вы еще не в курсе, команда docker проводит регулярные Docker Online Meetup я из посещаю — довольно интересно, советую.