[Перевод] Кластер Docker Swarm за 30 секунд

a2f09630c66d4a11bb308a42aa4ff715.JPG


В этом июне в качестве лейтмотива конференции DockerCon мы увидели демо, в котором 3-узловой Swarm-кластер был создан за 30 секунд, используя набор инструментов для кластеризации Swarm, интегрированную в Docker Engine 1.12.


Впечатляет, но, естественно, мне нужно было попробовать сделать это самому, чтобы увидеть своими глазами, если демо остановится.



Создание узлов в вашем Swarm


docker-machine create -d virtualbox node1  
docker-machine create -d virtualbox node2  
docker-machine create -d virtualbox node3
docker-machine ssh node1   # или 2, или 3

Я нашел самый простой путь, для начала работы со Swarm (Роем) — использовать docker-machine для создания хостов с установленным на них Docker Engine. Я использовал драйвер virtualbox«а, но вы можете использовать любой драйвер, который вы хотите, например, amazonec2.


Инициализация вашего менеджера


docker swarm init --advertise-addr [advertise ip]:2377 

697a7c3b1db445899e877ce6c885caef.png


Присоедините ваших воркеров (workers)


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


docker swarm join --token [token] [manager ip]:[manager port] 

46813dafaa1e48bdac1eb9e122a36719.png


Теперь у вас есть Swarm-кластер!


Давайте что-нибудь развернем (deploy)


Чтобы запустить приложение, мы используем служебную команду Docker«а create. С помощью флага --replicas вы можете очень просто масштабировать сервис.


Первоначально, мы хотим создать сеть верхнего уровня (оверлейную сеть), чтобы развернуть наше приложение.


docker network create -d overlay mynetwork  

До Docker Engine 1.12 оверлейные сети требовали внешнего хранилища ключ/значение. Но с созданием распределенного хранилища в Docker 1.12 это больше не требуется.


Давайте развернем простое приложение Apache на публичном порту 5001. Я использую специальный образ Apache, найденный мной на DockerHub, который печатает ID контейнера, обслуживающего запрос. Позже это будет использовано для демонстрации балансировки нагрузки.


docker service create --name web --network mynetwork --replicas 3 -p 5001:80 francois/apache-hostname 

Вы можете использовать следующие команды, чтобы проверить ваш новый сервис:


docker service ls  
docker service tasks web

Сетка маршрутизации


Добавления сетки маршрутизации и децентрализованной архитектуры в Docker 1.12 позволяет любым узлам-работникам в кластере маршрутизировать (направлять) трафик к другим узлам.


В нашем веб-сервисе, выше, мы открыли кластерный (cluster-wide) порт 5001. Вы можете послать запрос на любой узел на порт 5001, и сетка маршрутизации направит запрос на тот узел, который запустил контейнер.


curl [ip]:5001 

923acc389ee04afa9d0b530568df11b4.png


Балансирование нагрузки


Всегда, когда создается новая служба, виртуальный IP создается вместе с этой службой. IPVS владеет (осуществляет) балансировкой нагрузки, высокопроизводительным уровнем 4 балансирования нагрузки, который встроен в ядро Linux.


Чтобы показать это, запустим curl несколько раз, для демонстрации изменение ID контейнера.


078a2007434b4703a118c1588545b758.png


Балансировка нагрузки при помощи Docker 1.12 является контейнер-осведомленной (container-aware). Хост-осведомленная (host-aware) балансировочная система, такая как nginx или haproxy, удаляет или добавляет контейнеры требуемой конфигурации обновления балансирования нагрузки и перезапуска этих сервисов. Существует полезная библиотека, называемая Interlock, которая прослушивает Docker Events API и обновляет конфигурацию/осуществляет перезапуск сервиса «на лету». Но этот инструмент больше требуется после нового добавления балансирования нагрузки в Docker 1.12.


Это не может быть так просто…


Эта картинка из Nigel Poulton очень хорошо обобщает различия между старым Swarm и новым Swarm.


c09906320600455396c4e2fe9a38379a.jpg


Перевод картинки:


Старый путь (много шагов и команд не показано)


  1. Создать ключи
  2. Перезапустить демоны manager1 и node1 с TLS-флагами на 2376
  3. Запустить распределенный сервис Consul (контейнер)
  4. Запустить клиент Consul на node1 (не показано, но он успешно присоединился к серверу Consul)
  5. Начать управление Swarm (контейнер) на 2376 и карты 3376:2376
    5.1. Скопировать ключи в контейнер Swarm менеджера с помощью объема и специальных ключей и порт для менеджера команд Swarm
    5.2. Успешно получить роль лидера
  6. Начать присоединять к Swarm контейнер на node1
    6.1. Не монтируйте ключи внутрь контейнера и задайте команду присоединения как неподдерживаемую опцию
  7. Сконфигурируйте клиент при помощи DOCKER_HOST (указывающий на Swarm)
    7.1. …

Новый путь


С Docker 1.12 вы также как и раньше можете инсталлировать внешние распределенные службы (consul, etcd, zookeeper), или отдельную службу планирования. Настройка TLS сквозная из коробки, нет «незащищенного режима». У меня не существует никаких сомнений, что новый Docker Swarm является самым быстрым путем для получения запущенного и работающего docker-native кластера, готового быть развернутым в продакеш.


А что насчет большого масштабирования? Спасибо усилиям «капитана» Docker«a Chanwit Kaewkasi и DockerSwarm2000, они показали нам, что вы можете создать кластер из 2384 узлов и 96287 контейнеров.


Режим Swarm является самым оптимальным


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


docker swarm init

Swarm в Docker«е 1.12 также поддерживает согласования, плавающие обновления (rolling updates) образа, глобальные сервисы и сервисы по расписанию, базирующиеся на ограничениях.


Отказ узла в Docker Swarm


Также хочу затронуть тему отказа узлов в Docker Swarm.
Команды, относящиеся к сервисам Docker Engine 1.12, являются декларативными. Например, если вы задаете команду «Я хочу 3 реплики данного сервиса», то кластер будет поддерживать это состояние.
В случае отказа узла, контейнеры которого были задействованы, swarm обнаружит, что желаемое состояние не совпадает с действительным, и автоматически исправит ситуацию путем перераспределения контейнеров на другие доступные узлы.


Чтобы это продемонстрировать, давайте зададим новый сервис с тремя репликами.


docker service create --name web --replicas 3 francois/apache-hostname

Запустите, чтобы проверить работу сервиса


docker service tasks web 

0150b52310804a1aacf0e1004cc920e7.png


Сейчас у нас есть по одному контейнеру на каждом из узлов. Давайте выведем из строя узел 3, чтобы посмотреть на регулирование swarm в действии.


# Run this on node3 
docker swarm leave  

Теперь желаемое состояние не совпадает с действительным. У нас есть только 2 действующих контейнера, тогда как мы обозначили 3 контейнера, когда запускали сервис.


Использование докер сервиса дает вам возможность увидеть, что количество реплик уменьшилось до двух, а затем снова вернулось к трем


0bb55ddbfd2b45b3bb777196e8cc7a75.png


9faf1a4ef320443bb1f9a7175e78b23f.png


docker service tasks web покажет вам новый контейнер, назначенный на другом узле вашего кластера.


453a4b2aca7041f4a0a5af51743bc201.png


Этот пример показывает только регулирование контейнеров на рабочих узлах. Совершенно другой процесс происходит, когда из строя выходит менеджер, особенно, если это лидер raft группы для решения задач консенсуса.


Глобальные сервисы


Глобальные сервисы полезны, когда вы хотите создать контейнер на каждом узле вашего кластера. Подумайте о ведении протокола или мониторинге.


docker service create --mode=global --name prometheus prom/prometheus

3f6757cf11764eb3b393b293c02139fb.png


Помните, я говорил, что сервисы являются декларативными? Когда вы добавляете новый узел к вашему кластеру, swarm определяет, что желаемое состояние не совпадает с действительным, и запускает экземпляр глобального контейнера на этом узле.


Ограничения


Для демонстрации ограничений я использовал докер машину, чтобы ускорить новую машину с помощью engine label.


docker-machine create -d virtualbox --engine-label com.example.storage="ssd" sw3  

Затем я добавил ее в swarm.


docker swarm join --token [token] [manager ip]:[manager port] 

Далее я создал сервис, ссылающийся на это ограничение.


docker service create --name web2 --replicas 3 --constraint 'engine.labels.com.example.storage == ssd' francois/apache-hostname

ff2923da59d949b9ac39aac201cca787.png


Помните, я говорил, что сервисы являются декларативными? ;) Это означает, что, когда мы масштабируем этот сервис, он запоминает наши ограничения и масштабирует только отвечающие условиям узлы.


099cd12511284429b79fd9f5d9b1c003.png


John Zaccone


Docker Captain и Software Engineer в Ippon Technologies, который любит вбрасывать вещи на рынок побыстрее. Специализируется на agile, микросервисах, контейнерах, автоматизации, REST, devops.

Комментарии (0)

© Habrahabr.ru